Add blur setting to wallpaper preview
This commit is contained in:
parent
536e4d0b66
commit
fa3c368b77
@ -1,23 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "check-circle-filled-16@1x.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "check-circle-filled-16@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "check-circle-filled-16@3x.png",
|
||||
"scale" : "3x"
|
||||
"filename" : "check-circle-solid-16 1.pdf",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 238 B |
Binary file not shown.
|
Before Width: | Height: | Size: 399 B |
Binary file not shown.
|
Before Width: | Height: | Size: 605 B |
155
Signal/Images.xcassets/check-circle-filled-16.imageset/check-circle-solid-16 1.pdf
vendored
Normal file
155
Signal/Images.xcassets/check-circle-filled-16.imageset/check-circle-solid-16 1.pdf
vendored
Normal file
@ -0,0 +1,155 @@
|
||||
%PDF-1.7
|
||||
|
||||
1 0 obj
|
||||
<< /BBox [ 0.000000 0.000000 16.000000 16.000000 ]
|
||||
/Resources << >>
|
||||
/Subtype /Form
|
||||
/Length 2 0 R
|
||||
/Group << /Type /Group
|
||||
/S /Transparency
|
||||
>>
|
||||
/Type /XObject
|
||||
>>
|
||||
stream
|
||||
/DeviceRGB CS
|
||||
/DeviceRGB cs
|
||||
q
|
||||
1.000000 0.000000 -0.000000 1.000000 0.000000 -0.154968 cm
|
||||
1.000000 1.000000 1.000000 scn
|
||||
8.000004 16.154968 m
|
||||
6.417753 16.154968 4.871035 15.685777 3.555442 14.806726 c
|
||||
2.239848 13.927673 1.214468 12.678245 0.608967 11.216436 c
|
||||
0.003466 9.754627 -0.154960 8.146094 0.153721 6.594246 c
|
||||
0.462403 5.042397 1.224329 3.616934 2.343149 2.498114 c
|
||||
3.461969 1.379293 4.887434 0.617368 6.439281 0.308686 c
|
||||
7.991129 0.000004 9.599662 0.158431 11.061471 0.763932 c
|
||||
12.523280 1.369433 13.772710 2.394814 14.651761 3.710406 c
|
||||
15.530812 5.025999 16.000004 6.572718 16.000004 8.154968 c
|
||||
16.000004 10.276700 15.157149 12.311531 13.656858 13.811823 c
|
||||
12.156568 15.312114 10.121736 16.154968 8.000004 16.154968 c
|
||||
8.000004 16.154968 l
|
||||
h
|
||||
6.760004 4.594968 m
|
||||
3.760004 7.594968 l
|
||||
4.820004 8.664968 l
|
||||
6.760004 6.714969 l
|
||||
11.180004 11.154968 l
|
||||
12.240004 10.094969 l
|
||||
6.760004 4.594968 l
|
||||
h
|
||||
f
|
||||
n
|
||||
Q
|
||||
|
||||
endstream
|
||||
endobj
|
||||
|
||||
2 0 obj
|
||||
901
|
||||
endobj
|
||||
|
||||
3 0 obj
|
||||
<< /BBox [ 0.000000 0.000000 16.000000 16.000000 ]
|
||||
/Resources << >>
|
||||
/Subtype /Form
|
||||
/Length 4 0 R
|
||||
/Group << /Type /Group
|
||||
/S /Transparency
|
||||
>>
|
||||
/Type /XObject
|
||||
>>
|
||||
stream
|
||||
/DeviceRGB CS
|
||||
/DeviceRGB cs
|
||||
q
|
||||
1.000000 0.000000 -0.000000 1.000000 0.000000 0.000000 cm
|
||||
0.000000 0.000000 0.000000 scn
|
||||
0.000000 16.000000 m
|
||||
16.000000 16.000000 l
|
||||
16.000000 0.000000 l
|
||||
0.000000 0.000000 l
|
||||
0.000000 16.000000 l
|
||||
h
|
||||
f
|
||||
n
|
||||
Q
|
||||
|
||||
endstream
|
||||
endobj
|
||||
|
||||
4 0 obj
|
||||
232
|
||||
endobj
|
||||
|
||||
5 0 obj
|
||||
<< /XObject << /X1 1 0 R >>
|
||||
/ExtGState << /E1 << /SMask << /Type /Mask
|
||||
/G 3 0 R
|
||||
/S /Alpha
|
||||
>>
|
||||
/Type /ExtGState
|
||||
>> >>
|
||||
>>
|
||||
endobj
|
||||
|
||||
6 0 obj
|
||||
<< /Length 7 0 R >>
|
||||
stream
|
||||
/DeviceRGB CS
|
||||
/DeviceRGB cs
|
||||
q
|
||||
/E1 gs
|
||||
/X1 Do
|
||||
Q
|
||||
|
||||
endstream
|
||||
endobj
|
||||
|
||||
7 0 obj
|
||||
46
|
||||
endobj
|
||||
|
||||
8 0 obj
|
||||
<< /Annots []
|
||||
/Type /Page
|
||||
/MediaBox [ 0.000000 0.000000 16.000000 16.000000 ]
|
||||
/Resources 5 0 R
|
||||
/Contents 6 0 R
|
||||
/Parent 9 0 R
|
||||
>>
|
||||
endobj
|
||||
|
||||
9 0 obj
|
||||
<< /Kids [ 8 0 R ]
|
||||
/Count 1
|
||||
/Type /Pages
|
||||
>>
|
||||
endobj
|
||||
|
||||
10 0 obj
|
||||
<< /Type /Catalog
|
||||
/Pages 9 0 R
|
||||
>>
|
||||
endobj
|
||||
|
||||
xref
|
||||
0 11
|
||||
0000000000 65535 f
|
||||
0000000010 00000 n
|
||||
0000001159 00000 n
|
||||
0000001181 00000 n
|
||||
0000001661 00000 n
|
||||
0000001683 00000 n
|
||||
0000001981 00000 n
|
||||
0000002083 00000 n
|
||||
0000002104 00000 n
|
||||
0000002277 00000 n
|
||||
0000002351 00000 n
|
||||
trailer
|
||||
<< /ID [ (some) (id) ]
|
||||
/Root 10 0 R
|
||||
/Size 11
|
||||
>>
|
||||
startxref
|
||||
2411
|
||||
%%EOF
|
||||
12
Signal/Images.xcassets/circle-outline-16.imageset/Contents.json
vendored
Normal file
12
Signal/Images.xcassets/circle-outline-16.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "circle-outline-16.pdf",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
160
Signal/Images.xcassets/circle-outline-16.imageset/circle-outline-16.pdf
vendored
Normal file
160
Signal/Images.xcassets/circle-outline-16.imageset/circle-outline-16.pdf
vendored
Normal file
@ -0,0 +1,160 @@
|
||||
%PDF-1.7
|
||||
|
||||
1 0 obj
|
||||
<< /BBox [ 0.000000 0.000000 16.000000 16.000000 ]
|
||||
/Resources << >>
|
||||
/Subtype /Form
|
||||
/Length 2 0 R
|
||||
/Group << /Type /Group
|
||||
/S /Transparency
|
||||
>>
|
||||
/Type /XObject
|
||||
>>
|
||||
stream
|
||||
/DeviceRGB CS
|
||||
/DeviceRGB cs
|
||||
q
|
||||
1.000000 0.000000 -0.000000 1.000000 0.000000 -0.154968 cm
|
||||
1.000000 1.000000 1.000000 scn
|
||||
8.000004 14.654968 m
|
||||
9.285583 14.654968 10.542291 14.273750 11.611210 13.559521 c
|
||||
12.680129 12.845291 13.513250 11.830131 14.005220 10.642410 c
|
||||
14.497190 9.454691 14.625912 8.147758 14.375108 6.886881 c
|
||||
14.124304 5.626004 13.505239 4.467815 12.596198 3.558774 c
|
||||
11.687157 2.649733 10.528968 2.030668 9.268091 1.779864 c
|
||||
8.007215 1.529060 6.700281 1.657782 5.512561 2.149752 c
|
||||
4.324841 2.641722 3.309680 3.474843 2.595451 4.543762 c
|
||||
1.881222 5.612681 1.500004 6.869390 1.500004 8.154968 c
|
||||
1.502648 9.878063 2.188317 11.529827 3.406731 12.748241 c
|
||||
4.625144 13.966655 6.276909 14.652324 8.000004 14.654968 c
|
||||
8.000004 14.654968 l
|
||||
h
|
||||
8.000004 16.154968 m
|
||||
6.417753 16.154968 4.871035 15.685777 3.555442 14.806726 c
|
||||
2.239848 13.927673 1.214468 12.678245 0.608967 11.216436 c
|
||||
0.003466 9.754627 -0.154960 8.146094 0.153721 6.594246 c
|
||||
0.462403 5.042397 1.224329 3.616934 2.343149 2.498114 c
|
||||
3.461969 1.379293 4.887434 0.617368 6.439281 0.308686 c
|
||||
7.991129 0.000004 9.599662 0.158431 11.061471 0.763932 c
|
||||
12.523280 1.369433 13.772710 2.394814 14.651761 3.710406 c
|
||||
15.530812 5.025999 16.000004 6.572718 16.000004 8.154968 c
|
||||
16.000004 10.276700 15.157149 12.311531 13.656858 13.811823 c
|
||||
12.156568 15.312114 10.121736 16.154968 8.000004 16.154968 c
|
||||
8.000004 16.154968 l
|
||||
h
|
||||
f
|
||||
n
|
||||
Q
|
||||
|
||||
endstream
|
||||
endobj
|
||||
|
||||
2 0 obj
|
||||
1383
|
||||
endobj
|
||||
|
||||
3 0 obj
|
||||
<< /BBox [ 0.000000 0.000000 16.000000 16.000000 ]
|
||||
/Resources << >>
|
||||
/Subtype /Form
|
||||
/Length 4 0 R
|
||||
/Group << /Type /Group
|
||||
/S /Transparency
|
||||
>>
|
||||
/Type /XObject
|
||||
>>
|
||||
stream
|
||||
/DeviceRGB CS
|
||||
/DeviceRGB cs
|
||||
q
|
||||
1.000000 0.000000 -0.000000 1.000000 0.000000 0.000000 cm
|
||||
0.000000 0.000000 0.000000 scn
|
||||
0.000000 16.000000 m
|
||||
16.000000 16.000000 l
|
||||
16.000000 0.000000 l
|
||||
0.000000 0.000000 l
|
||||
0.000000 16.000000 l
|
||||
h
|
||||
f
|
||||
n
|
||||
Q
|
||||
|
||||
endstream
|
||||
endobj
|
||||
|
||||
4 0 obj
|
||||
232
|
||||
endobj
|
||||
|
||||
5 0 obj
|
||||
<< /XObject << /X1 1 0 R >>
|
||||
/ExtGState << /E1 << /SMask << /Type /Mask
|
||||
/G 3 0 R
|
||||
/S /Alpha
|
||||
>>
|
||||
/Type /ExtGState
|
||||
>> >>
|
||||
>>
|
||||
endobj
|
||||
|
||||
6 0 obj
|
||||
<< /Length 7 0 R >>
|
||||
stream
|
||||
/DeviceRGB CS
|
||||
/DeviceRGB cs
|
||||
q
|
||||
/E1 gs
|
||||
/X1 Do
|
||||
Q
|
||||
|
||||
endstream
|
||||
endobj
|
||||
|
||||
7 0 obj
|
||||
46
|
||||
endobj
|
||||
|
||||
8 0 obj
|
||||
<< /Annots []
|
||||
/Type /Page
|
||||
/MediaBox [ 0.000000 0.000000 16.000000 16.000000 ]
|
||||
/Resources 5 0 R
|
||||
/Contents 6 0 R
|
||||
/Parent 9 0 R
|
||||
>>
|
||||
endobj
|
||||
|
||||
9 0 obj
|
||||
<< /Kids [ 8 0 R ]
|
||||
/Count 1
|
||||
/Type /Pages
|
||||
>>
|
||||
endobj
|
||||
|
||||
10 0 obj
|
||||
<< /Type /Catalog
|
||||
/Pages 9 0 R
|
||||
>>
|
||||
endobj
|
||||
|
||||
xref
|
||||
0 11
|
||||
0000000000 65535 f
|
||||
0000000010 00000 n
|
||||
0000001641 00000 n
|
||||
0000001664 00000 n
|
||||
0000002144 00000 n
|
||||
0000002166 00000 n
|
||||
0000002464 00000 n
|
||||
0000002566 00000 n
|
||||
0000002587 00000 n
|
||||
0000002760 00000 n
|
||||
0000002834 00000 n
|
||||
trailer
|
||||
<< /ID [ (some) (id) ]
|
||||
/Root 10 0 R
|
||||
/Size 11
|
||||
>>
|
||||
startxref
|
||||
2894
|
||||
%%EOF
|
||||
@ -11,6 +11,7 @@ class PreviewWallpaperViewController: UIViewController {
|
||||
}
|
||||
private(set) var mode: Mode { didSet { modeDidChange() }}
|
||||
let thread: TSThread?
|
||||
lazy var blurButton = BlurButton { [weak self] shouldBlur in self?.standalonePage?.shouldBlur = shouldBlur }
|
||||
|
||||
let pageViewController = UIPageViewController(
|
||||
transitionStyle: .scroll,
|
||||
@ -90,6 +91,10 @@ class PreviewWallpaperViewController: UIViewController {
|
||||
safeAreaCover.autoPinEdge(toSuperviewEdge: .bottom)
|
||||
safeAreaCover.autoPinWidthToSuperview()
|
||||
safeAreaCover.autoPinEdge(.top, to: .bottom, of: buttonStack)
|
||||
|
||||
view.addSubview(blurButton)
|
||||
blurButton.autoPinEdge(.bottom, to: .top, of: buttonStack, withOffset: -24)
|
||||
blurButton.autoHCenterInSuperview()
|
||||
}
|
||||
|
||||
override func viewDidLoad() {
|
||||
@ -129,7 +134,7 @@ class PreviewWallpaperViewController: UIViewController {
|
||||
}
|
||||
}
|
||||
|
||||
private var standalonePage: UIViewController?
|
||||
private var standalonePage: WallpaperPage?
|
||||
func modeDidChange() {
|
||||
switch mode {
|
||||
case .photo(let selectedPhoto):
|
||||
@ -139,6 +144,7 @@ class PreviewWallpaperViewController: UIViewController {
|
||||
view.insertSubview(standalonePage.view, at: 0)
|
||||
addChild(standalonePage)
|
||||
standalonePage.view.autoPinEdgesToSuperviewEdges()
|
||||
blurButton.isHidden = false
|
||||
case .preset(let selectedWallpaper):
|
||||
if pageViewController.view.superview == nil {
|
||||
view.insertSubview(pageViewController.view, at: 0)
|
||||
@ -149,6 +155,7 @@ class PreviewWallpaperViewController: UIViewController {
|
||||
}
|
||||
|
||||
currentPage = WallpaperPage(wallpaper: selectedWallpaper)
|
||||
blurButton.isHidden = true
|
||||
}
|
||||
|
||||
mockConversationView.mode = buildMockConversationMode()
|
||||
@ -260,11 +267,15 @@ extension PreviewWallpaperViewController: UIPageViewControllerDataSource, UIPage
|
||||
|
||||
private class WallpaperPage: UIViewController {
|
||||
let wallpaper: Wallpaper
|
||||
weak var photo: UIImage?
|
||||
let photo: UIImage?
|
||||
var shouldBlur = false { didSet { updatePhoto() } }
|
||||
|
||||
init(wallpaper: Wallpaper, photo: UIImage? = nil) {
|
||||
self.wallpaper = wallpaper
|
||||
self.photo = photo
|
||||
super.init(nibName: nil, bundle: nil)
|
||||
|
||||
if photo != nil { prepareBlurredPhoto() }
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
@ -350,13 +361,68 @@ private class WallpaperPage: UIViewController {
|
||||
}
|
||||
}
|
||||
|
||||
private func updatePhoto() {
|
||||
guard let wallpaperImageView = wallpaperView as? UIImageView else { return }
|
||||
UIView.transition(with: wallpaperImageView, duration: 0.2, options: .transitionCrossDissolve) {
|
||||
wallpaperImageView.image = self.shouldBlur ? self.blurredPhoto : self.photo
|
||||
} completion: { _ in }
|
||||
}
|
||||
|
||||
private var blurredPhoto: UIImage?
|
||||
private func prepareBlurredPhoto() {
|
||||
DispatchQueue.global(qos: .userInteractive).async { [weak self] in
|
||||
guard let self = self else { return }
|
||||
|
||||
guard let clampFilter = CIFilter(name: "CIAffineClamp") else {
|
||||
return owsFailDebug("Failed to create blur filter")
|
||||
}
|
||||
|
||||
guard let blurFilter = CIFilter(name: "CIGaussianBlur", parameters: [kCIInputRadiusKey: 3]) else {
|
||||
return owsFailDebug("Failed to create blur filter")
|
||||
}
|
||||
|
||||
guard let photo = self.photo else {
|
||||
return owsFailDebug("Could not load src image.")
|
||||
}
|
||||
|
||||
guard let resizedPhoto = photo.resized(withMaxDimensionPixels: 300), let resizedCGPhoto = resizedPhoto.cgImage else {
|
||||
return owsFailDebug("Failed to downsize image for blur")
|
||||
}
|
||||
|
||||
// In order to get a nice edge-to-edge blur, we must apply a clamp filter and *then* the blur filter.
|
||||
let inputPhoto = CIImage(cgImage: resizedCGPhoto)
|
||||
clampFilter.setDefaults()
|
||||
clampFilter.setValue(inputPhoto, forKey: kCIInputImageKey)
|
||||
|
||||
guard let clampOutput = clampFilter.outputImage else {
|
||||
return owsFailDebug("Failed to clamp src image")
|
||||
}
|
||||
|
||||
blurFilter.setValue(clampOutput, forKey: kCIInputImageKey)
|
||||
|
||||
guard let blurredOutput = blurFilter.value(forKey: kCIOutputImageKey) as? CIImage else {
|
||||
return owsFailDebug("Failed to blur clamped image")
|
||||
}
|
||||
|
||||
let context = CIContext(options: nil)
|
||||
guard let blurredPhoto = context.createCGImage(blurredOutput, from: inputPhoto.extent) else {
|
||||
return owsFailDebug("Failed to create CGImage from blurred output")
|
||||
}
|
||||
|
||||
self.blurredPhoto = UIImage(cgImage: blurredPhoto)
|
||||
|
||||
// Once the blur is ready, update any content in case the user already blurred
|
||||
DispatchQueue.main.async { [weak self] in
|
||||
self?.updatePhoto()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
|
||||
super.viewWillTransition(to: size, with: coordinator)
|
||||
coordinator.animate { _ in
|
||||
self.updateWallpaperConstraints(reference: size)
|
||||
} completion: { _ in
|
||||
|
||||
}
|
||||
} completion: { _ in }
|
||||
}
|
||||
|
||||
private var previousReferenceSize: CGSize = .zero
|
||||
@ -401,3 +467,76 @@ extension WallpaperPage: UIScrollViewDelegate {
|
||||
return wallpaperView
|
||||
}
|
||||
}
|
||||
|
||||
class BlurButton: UIButton {
|
||||
let checkImageView = UIImageView()
|
||||
let label = UILabel()
|
||||
let action: (Bool) -> Void
|
||||
let backgroundView: UIView = {
|
||||
if UIAccessibility.isReduceTransparencyEnabled {
|
||||
let backgroundView = UIView()
|
||||
backgroundView.backgroundColor = .ows_blackAlpha80
|
||||
return backgroundView
|
||||
} else {
|
||||
let blurView = UIVisualEffectView(effect: UIBlurEffect(style: .dark))
|
||||
return blurView
|
||||
}
|
||||
}()
|
||||
|
||||
init(action: @escaping (Bool) -> Void) {
|
||||
self.action = action
|
||||
super.init(frame: .zero)
|
||||
|
||||
addTarget(self, action: #selector(didTap), for: .touchUpInside)
|
||||
|
||||
layoutMargins = UIEdgeInsets(top: 3, leading: 10, bottom: 3, trailing: 12)
|
||||
autoSetDimension(.height, toSize: 28, relation: .greaterThanOrEqual)
|
||||
|
||||
backgroundView.clipsToBounds = true
|
||||
backgroundView.isUserInteractionEnabled = false
|
||||
addSubview(backgroundView)
|
||||
backgroundView.autoPinEdgesToSuperviewEdges()
|
||||
|
||||
addSubview(checkImageView)
|
||||
checkImageView.autoPinEdge(toSuperviewMargin: .leading)
|
||||
checkImageView.autoPinHeightToSuperviewMargins()
|
||||
checkImageView.autoSetDimension(.width, toSize: 16)
|
||||
checkImageView.contentMode = .scaleAspectFit
|
||||
checkImageView.isUserInteractionEnabled = false
|
||||
|
||||
label.font = .ows_semiboldFont(withSize: 14)
|
||||
label.textColor = .white
|
||||
label.text = NSLocalizedString("WALLPAPER_PREVIEW_BLUR_BUTTON",
|
||||
comment: "Blur button on wallpaper preview.")
|
||||
addSubview(label)
|
||||
label.autoPinHeightToSuperviewMargins()
|
||||
label.autoPinEdge(toSuperviewMargin: .trailing)
|
||||
label.autoPinEdge(.leading, to: .trailing, of: checkImageView, withOffset: 10)
|
||||
label.isUserInteractionEnabled = false
|
||||
|
||||
isSelected = false
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
override func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
backgroundView.layer.cornerRadius = height / 2
|
||||
}
|
||||
|
||||
override var isSelected: Bool {
|
||||
didSet {
|
||||
UIView.transition(with: checkImageView, duration: 0.15, options: .transitionCrossDissolve) {
|
||||
self.checkImageView.image = self.isSelected ? #imageLiteral(resourceName: "check-circle-filled-16") : #imageLiteral(resourceName: "circle-outline-16")
|
||||
} completion: { _ in }
|
||||
}
|
||||
}
|
||||
|
||||
@objc
|
||||
func didTap() {
|
||||
isSelected = !isSelected
|
||||
action(isSelected)
|
||||
}
|
||||
}
|
||||
|
||||
@ -5182,6 +5182,9 @@
|
||||
/* Placeholder text for header of the wallpaper mini preview */
|
||||
"WALLPAPER_MINI_PREVIEW_CONTACT_NAME" = "Contact Name";
|
||||
|
||||
/* Blur button on wallpaper preview. */
|
||||
"WALLPAPER_PREVIEW_BLUR_BUTTON" = "Blur Photo";
|
||||
|
||||
/* The incoming bubble text when setting a photo */
|
||||
"WALLPAPER_PREVIEW_INCOMING_MESSAGE_PHOTO" = "Pinch to zoom, drag to adjust.";
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user