Compare commits
5 Commits
6857529d06
...
eafb506d64
Author | SHA1 | Date |
---|---|---|
Shadowfacts | eafb506d64 | |
Shadowfacts | fe00015248 | |
Shadowfacts | 509ed305cd | |
Shadowfacts | c05107bccd | |
Shadowfacts | 4fcc32ca4b |
|
@ -43,9 +43,10 @@ class GalleryDismissAnimationController: NSObject, UIViewControllerAnimatedTrans
|
||||||
let appliedSourceToDestTransform: Bool
|
let appliedSourceToDestTransform: Bool
|
||||||
if destFrameInContainer.width > 0 && destFrameInContainer.height > 0 {
|
if destFrameInContainer.width > 0 && destFrameInContainer.height > 0 {
|
||||||
appliedSourceToDestTransform = true
|
appliedSourceToDestTransform = true
|
||||||
|
let scale = min(destFrameInContainer.width / sourceFrameInContainer.width, destFrameInContainer.height / sourceFrameInContainer.height)
|
||||||
let sourceToDestTransform = origSourceTransform
|
let sourceToDestTransform = origSourceTransform
|
||||||
.translatedBy(x: destFrameInContainer.midX - sourceFrameInContainer.midX, y: destFrameInContainer.midY - sourceFrameInContainer.midY)
|
.translatedBy(x: destFrameInContainer.midX - sourceFrameInContainer.midX, y: destFrameInContainer.midY - sourceFrameInContainer.midY)
|
||||||
.scaledBy(x: destFrameInContainer.width / sourceFrameInContainer.width, y: destFrameInContainer.height / sourceFrameInContainer.height)
|
.scaledBy(x: scale, y: scale)
|
||||||
sourceView.transform = sourceToDestTransform
|
sourceView.transform = sourceToDestTransform
|
||||||
} else {
|
} else {
|
||||||
appliedSourceToDestTransform = false
|
appliedSourceToDestTransform = false
|
||||||
|
|
|
@ -64,8 +64,7 @@ class GalleryItemViewController: UIViewController {
|
||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
|
|
||||||
let scrollView = UIScrollView()
|
scrollView = UIScrollView()
|
||||||
self.scrollView = scrollView
|
|
||||||
scrollView.translatesAutoresizingMaskIntoConstraints = false
|
scrollView.translatesAutoresizingMaskIntoConstraints = false
|
||||||
scrollView.delegate = self
|
scrollView.delegate = self
|
||||||
|
|
||||||
|
@ -91,7 +90,9 @@ class GalleryItemViewController: UIViewController {
|
||||||
topControlsView.translatesAutoresizingMaskIntoConstraints = false
|
topControlsView.translatesAutoresizingMaskIntoConstraints = false
|
||||||
view.addSubview(topControlsView)
|
view.addSubview(topControlsView)
|
||||||
|
|
||||||
var shareConfig = UIButton.Configuration.plain()
|
var shareConfig = UIButton.Configuration.gray()
|
||||||
|
shareConfig.cornerStyle = .capsule
|
||||||
|
shareConfig.background.backgroundColor = .black.withAlphaComponent(0.25)
|
||||||
shareConfig.baseForegroundColor = .white
|
shareConfig.baseForegroundColor = .white
|
||||||
shareConfig.image = UIImage(systemName: "square.and.arrow.up")
|
shareConfig.image = UIImage(systemName: "square.and.arrow.up")
|
||||||
shareButton = UIButton(configuration: shareConfig)
|
shareButton = UIButton(configuration: shareConfig)
|
||||||
|
@ -100,7 +101,9 @@ class GalleryItemViewController: UIViewController {
|
||||||
updateShareButton()
|
updateShareButton()
|
||||||
topControlsView.addSubview(shareButton)
|
topControlsView.addSubview(shareButton)
|
||||||
|
|
||||||
var closeConfig = UIButton.Configuration.plain()
|
var closeConfig = UIButton.Configuration.gray()
|
||||||
|
closeConfig.cornerStyle = .capsule
|
||||||
|
closeConfig.background.backgroundColor = .black.withAlphaComponent(0.25)
|
||||||
closeConfig.baseForegroundColor = .white
|
closeConfig.baseForegroundColor = .white
|
||||||
closeConfig.image = UIImage(systemName: "xmark")
|
closeConfig.image = UIImage(systemName: "xmark")
|
||||||
let closeButton = UIButton(configuration: closeConfig)
|
let closeButton = UIButton(configuration: closeConfig)
|
||||||
|
@ -288,8 +291,8 @@ class GalleryItemViewController: UIViewController {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let heightScale = view.safeAreaLayoutGuide.layoutFrame.height / content.contentSize.height
|
let heightScale = view.bounds.height / content.contentSize.height
|
||||||
let widthScale = view.safeAreaLayoutGuide.layoutFrame.width / content.contentSize.width
|
let widthScale = view.bounds.width / content.contentSize.width
|
||||||
let minScale = min(widthScale, heightScale)
|
let minScale = min(widthScale, heightScale)
|
||||||
let maxScale = minScale >= 1 ? minScale + 2 : 2
|
let maxScale = minScale >= 1 ? minScale + 2 : 2
|
||||||
|
|
||||||
|
|
|
@ -49,9 +49,11 @@ class GalleryPresentationAnimationController: NSObject, UIViewControllerAnimated
|
||||||
let origSourceTransform = sourceView.transform
|
let origSourceTransform = sourceView.transform
|
||||||
let sourceToDestTransform: CGAffineTransform?
|
let sourceToDestTransform: CGAffineTransform?
|
||||||
if destFrameInContainer.width > 0 && destFrameInContainer.height > 0 {
|
if destFrameInContainer.width > 0 && destFrameInContainer.height > 0 {
|
||||||
|
// Scale evenly in both dimensions, to prevent the source view appearing to stretch/distort during the animation.
|
||||||
|
let scale = min(destFrameInContainer.width / sourceFrameInContainer.width, destFrameInContainer.height / sourceFrameInContainer.height)
|
||||||
sourceToDestTransform = origSourceTransform
|
sourceToDestTransform = origSourceTransform
|
||||||
.translatedBy(x: destFrameInContainer.midX - sourceFrameInContainer.midX, y: destFrameInContainer.midY - sourceFrameInContainer.midY)
|
.translatedBy(x: destFrameInContainer.midX - sourceFrameInContainer.midX, y: destFrameInContainer.midY - sourceFrameInContainer.midY)
|
||||||
.scaledBy(x: destFrameInContainer.width / sourceFrameInContainer.width, y: destFrameInContainer.height / sourceFrameInContainer.height)
|
.scaledBy(x: scale, y: scale)
|
||||||
} else {
|
} else {
|
||||||
sourceToDestTransform = nil
|
sourceToDestTransform = nil
|
||||||
}
|
}
|
||||||
|
@ -59,9 +61,17 @@ class GalleryPresentationAnimationController: NSObject, UIViewControllerAnimated
|
||||||
let content = itemViewController.takeContent()
|
let content = itemViewController.takeContent()
|
||||||
content.view.translatesAutoresizingMaskIntoConstraints = true
|
content.view.translatesAutoresizingMaskIntoConstraints = true
|
||||||
|
|
||||||
container.addSubview(to.view)
|
// Use a separate dimming view from to.view, so that the gallery controls can be in front of the moving content.
|
||||||
container.addSubview(content.view)
|
let dimmingView = UIView()
|
||||||
|
dimmingView.backgroundColor = .black
|
||||||
|
dimmingView.frame = container.bounds
|
||||||
|
dimmingView.layer.opacity = 0
|
||||||
|
|
||||||
|
container.addSubview(dimmingView)
|
||||||
|
container.addSubview(content.view)
|
||||||
|
container.addSubview(to.view)
|
||||||
|
|
||||||
|
to.view.backgroundColor = nil
|
||||||
to.view.layer.opacity = 0
|
to.view.layer.opacity = 0
|
||||||
content.view.frame = sourceFrameInContainer
|
content.view.frame = sourceFrameInContainer
|
||||||
content.view.layer.opacity = 0
|
content.view.layer.opacity = 0
|
||||||
|
@ -77,6 +87,8 @@ class GalleryPresentationAnimationController: NSObject, UIViewControllerAnimated
|
||||||
let animator = UIViewPropertyAnimator(duration: duration, timingParameters: spring)
|
let animator = UIViewPropertyAnimator(duration: duration, timingParameters: spring)
|
||||||
|
|
||||||
animator.addAnimations {
|
animator.addAnimations {
|
||||||
|
dimmingView.layer.opacity = 1
|
||||||
|
|
||||||
to.view.layer.opacity = 1
|
to.view.layer.opacity = 1
|
||||||
|
|
||||||
content.view.frame = destFrameInContainer
|
content.view.frame = destFrameInContainer
|
||||||
|
@ -90,6 +102,8 @@ class GalleryPresentationAnimationController: NSObject, UIViewControllerAnimated
|
||||||
}
|
}
|
||||||
|
|
||||||
animator.addCompletion { _ in
|
animator.addCompletion { _ in
|
||||||
|
to.view.backgroundColor = .black
|
||||||
|
|
||||||
if sourceToDestTransform != nil {
|
if sourceToDestTransform != nil {
|
||||||
self.sourceView.transform = origSourceTransform
|
self.sourceView.transform = origSourceTransform
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,7 +57,7 @@ class ImageGalleryContentViewController: UIViewController, GalleryContentViewCon
|
||||||
|
|
||||||
imageView = GIFImageView(image: maybeGrayscaleImage)
|
imageView = GIFImageView(image: maybeGrayscaleImage)
|
||||||
imageView.translatesAutoresizingMaskIntoConstraints = false
|
imageView.translatesAutoresizingMaskIntoConstraints = false
|
||||||
imageView.contentMode = .scaleAspectFit
|
imageView.contentMode = .scaleAspectFill
|
||||||
imageView.isUserInteractionEnabled = true
|
imageView.isUserInteractionEnabled = true
|
||||||
view.addSubview(imageView)
|
view.addSubview(imageView)
|
||||||
NSLayoutConstraint.activate([
|
NSLayoutConstraint.activate([
|
||||||
|
|
|
@ -30,7 +30,7 @@ class StatusAttachmentsGalleryDataSource: GalleryDataSource {
|
||||||
switch attachment.kind {
|
switch attachment.kind {
|
||||||
case .image:
|
case .image:
|
||||||
if let view = attachmentView(for: attachment),
|
if let view = attachmentView(for: attachment),
|
||||||
let image = view.image {
|
let image = view.attachmentImage {
|
||||||
return ImageGalleryContentViewController(
|
return ImageGalleryContentViewController(
|
||||||
url: attachment.url,
|
url: attachment.url,
|
||||||
caption: attachment.description,
|
caption: attachment.description,
|
||||||
|
|
|
@ -32,6 +32,16 @@ class AttachmentView: GIFImageView {
|
||||||
|
|
||||||
private var loadAttachmentTask: Task<Void, Never>?
|
private var loadAttachmentTask: Task<Void, Never>?
|
||||||
private var source: Source?
|
private var source: Source?
|
||||||
|
var attachmentImage: UIImage? {
|
||||||
|
switch source {
|
||||||
|
case .image(_, _, let image):
|
||||||
|
return image
|
||||||
|
case .gifData(_, _, let image):
|
||||||
|
return image
|
||||||
|
case nil:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
var originalData: Data? {
|
var originalData: Data? {
|
||||||
switch source {
|
switch source {
|
||||||
case .image(_, let data, _):
|
case .image(_, let data, _):
|
||||||
|
|
Loading…
Reference in New Issue