|
|
@ -168,42 +168,7 @@ protocol MediaGalleryDataSourceDelegate: class {
|
|
|
|
func mediaGalleryDataSource(_ mediaGalleryDataSource: MediaGalleryDataSource, deletedSections: IndexSet, deletedItems: [IndexPath])
|
|
|
|
func mediaGalleryDataSource(_ mediaGalleryDataSource: MediaGalleryDataSource, deletedSections: IndexSet, deletedItems: [IndexPath])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
class MediaGalleryViewController: OWSNavigationController, MediaGalleryDataSource, MediaTileViewControllerDelegate {
|
|
|
|
class MediaGalleryNavigationController: OWSNavigationController {
|
|
|
|
|
|
|
|
|
|
|
|
private var pageViewController: MediaPageViewController?
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private let uiDatabaseConnection: YapDatabaseConnection
|
|
|
|
|
|
|
|
private let editingDatabaseConnection: YapDatabaseConnection
|
|
|
|
|
|
|
|
private let mediaGalleryFinder: OWSMediaGalleryFinder
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private var initialDetailItem: MediaGalleryItem?
|
|
|
|
|
|
|
|
private let thread: TSThread
|
|
|
|
|
|
|
|
private let options: MediaGalleryOption
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// we start with a small range size for quick loading.
|
|
|
|
|
|
|
|
private let fetchRangeSize: UInt = 10
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
deinit {
|
|
|
|
|
|
|
|
Logger.debug("deinit")
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@objc
|
|
|
|
|
|
|
|
init(thread: TSThread, uiDatabaseConnection: YapDatabaseConnection, options: MediaGalleryOption = []) {
|
|
|
|
|
|
|
|
self.thread = thread
|
|
|
|
|
|
|
|
assert(uiDatabaseConnection.isInLongLivedReadTransaction())
|
|
|
|
|
|
|
|
self.uiDatabaseConnection = uiDatabaseConnection
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
self.editingDatabaseConnection = OWSPrimaryStorage.shared().newDatabaseConnection()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
self.options = options
|
|
|
|
|
|
|
|
self.mediaGalleryFinder = OWSMediaGalleryFinder(thread: thread)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
super.init(nibName: nil, bundle: nil)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
required init?(coder aDecoder: NSCoder) {
|
|
|
|
|
|
|
|
notImplemented()
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// MARK: View LifeCycle
|
|
|
|
// MARK: View LifeCycle
|
|
|
|
|
|
|
|
|
|
|
@ -213,6 +178,9 @@ class MediaGalleryViewController: OWSNavigationController, MediaGalleryDataSourc
|
|
|
|
UIViewController.attemptRotationToDeviceOrientation()
|
|
|
|
UIViewController.attemptRotationToDeviceOrientation()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var presentationView: UIImageView!
|
|
|
|
|
|
|
|
var retainUntilDismissed: MediaGallery?
|
|
|
|
|
|
|
|
|
|
|
|
// HACK: Though we don't have an input accessory view, the VC we are presented above (ConversationVC) does.
|
|
|
|
// HACK: Though we don't have an input accessory view, the VC we are presented above (ConversationVC) does.
|
|
|
|
// If the app is backgrounded and then foregrounded, when OWSWindowManager calls mainWindow.makeKeyAndVisible
|
|
|
|
// If the app is backgrounded and then foregrounded, when OWSWindowManager calls mainWindow.makeKeyAndVisible
|
|
|
|
// the ConversationVC's inputAccessoryView will appear *above* us unless we'd previously become first responder.
|
|
|
|
// the ConversationVC's inputAccessoryView will appear *above* us unless we'd previously become first responder.
|
|
|
@ -254,6 +222,52 @@ class MediaGalleryViewController: OWSNavigationController, MediaGalleryDataSourc
|
|
|
|
presentationView.contentMode = .scaleAspectFit
|
|
|
|
presentationView.contentMode = .scaleAspectFit
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// MARK: Orientation
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
|
|
|
|
|
|
|
|
return .allButUpsideDown
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@objc
|
|
|
|
|
|
|
|
class MediaGallery: NSObject, MediaGalleryDataSource, MediaTileViewControllerDelegate {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@objc
|
|
|
|
|
|
|
|
weak public var navigationController: MediaGalleryNavigationController!
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private var pageViewController: MediaPageViewController?
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private let uiDatabaseConnection: YapDatabaseConnection
|
|
|
|
|
|
|
|
private let editingDatabaseConnection: YapDatabaseConnection
|
|
|
|
|
|
|
|
private let mediaGalleryFinder: OWSMediaGalleryFinder
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private var initialDetailItem: MediaGalleryItem?
|
|
|
|
|
|
|
|
private let thread: TSThread
|
|
|
|
|
|
|
|
private let options: MediaGalleryOption
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// we start with a small range size for quick loading.
|
|
|
|
|
|
|
|
private let fetchRangeSize: UInt = 10
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
deinit {
|
|
|
|
|
|
|
|
Logger.debug("")
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@objc
|
|
|
|
|
|
|
|
init(thread: TSThread, uiDatabaseConnection: YapDatabaseConnection, options: MediaGalleryOption = []) {
|
|
|
|
|
|
|
|
self.thread = thread
|
|
|
|
|
|
|
|
assert(uiDatabaseConnection.isInLongLivedReadTransaction())
|
|
|
|
|
|
|
|
self.uiDatabaseConnection = uiDatabaseConnection
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
self.editingDatabaseConnection = OWSPrimaryStorage.shared().newDatabaseConnection()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
self.options = options
|
|
|
|
|
|
|
|
self.mediaGalleryFinder = OWSMediaGalleryFinder(thread: thread)
|
|
|
|
|
|
|
|
let navController = MediaGalleryNavigationController()
|
|
|
|
|
|
|
|
self.navigationController = navController
|
|
|
|
|
|
|
|
super.init()
|
|
|
|
|
|
|
|
navController.retainUntilDismissed = self
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// MARK: Present/Dismiss
|
|
|
|
// MARK: Present/Dismiss
|
|
|
|
|
|
|
|
|
|
|
|
private var currentItem: MediaGalleryItem {
|
|
|
|
private var currentItem: MediaGalleryItem {
|
|
|
@ -261,7 +275,6 @@ class MediaGalleryViewController: OWSNavigationController, MediaGalleryDataSourc
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private var replacingView: UIView?
|
|
|
|
private var replacingView: UIView?
|
|
|
|
private var presentationView: UIImageView!
|
|
|
|
|
|
|
|
private var presentationViewConstraints: [NSLayoutConstraint] = []
|
|
|
|
private var presentationViewConstraints: [NSLayoutConstraint] = []
|
|
|
|
|
|
|
|
|
|
|
|
// TODO rename to replacingOriginRect
|
|
|
|
// TODO rename to replacingOriginRect
|
|
|
@ -292,7 +305,7 @@ class MediaGalleryViewController: OWSNavigationController, MediaGalleryDataSourc
|
|
|
|
self.addDataSourceDelegate(pageViewController)
|
|
|
|
self.addDataSourceDelegate(pageViewController)
|
|
|
|
|
|
|
|
|
|
|
|
self.pageViewController = pageViewController
|
|
|
|
self.pageViewController = pageViewController
|
|
|
|
self.setViewControllers([pageViewController], animated: false)
|
|
|
|
navigationController.setViewControllers([pageViewController], animated: false)
|
|
|
|
|
|
|
|
|
|
|
|
self.replacingView = replacingView
|
|
|
|
self.replacingView = replacingView
|
|
|
|
|
|
|
|
|
|
|
@ -300,13 +313,13 @@ class MediaGalleryViewController: OWSNavigationController, MediaGalleryDataSourc
|
|
|
|
self.originRect = convertedRect
|
|
|
|
self.originRect = convertedRect
|
|
|
|
|
|
|
|
|
|
|
|
// loadView hasn't necessarily been called yet.
|
|
|
|
// loadView hasn't necessarily been called yet.
|
|
|
|
self.loadViewIfNeeded()
|
|
|
|
navigationController.loadViewIfNeeded()
|
|
|
|
|
|
|
|
|
|
|
|
self.presentationView.image = initialDetailItem.attachmentStream.thumbnailImageLarge(success: { [weak self] (image) in
|
|
|
|
navigationController.presentationView.image = initialDetailItem.attachmentStream.thumbnailImageLarge(success: { [weak self] (image) in
|
|
|
|
guard let strongSelf = self else {
|
|
|
|
guard let strongSelf = self else {
|
|
|
|
return
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
strongSelf.presentationView.image = image
|
|
|
|
strongSelf.navigationController.presentationView.image = image
|
|
|
|
}, failure: {
|
|
|
|
}, failure: {
|
|
|
|
Logger.warn("Could not load presentation image.")
|
|
|
|
Logger.warn("Could not load presentation image.")
|
|
|
|
})
|
|
|
|
})
|
|
|
@ -314,8 +327,8 @@ class MediaGalleryViewController: OWSNavigationController, MediaGalleryDataSourc
|
|
|
|
self.applyInitialMediaViewConstraints()
|
|
|
|
self.applyInitialMediaViewConstraints()
|
|
|
|
|
|
|
|
|
|
|
|
// Restore presentationView.alpha in case a previous dismiss left us in a bad state.
|
|
|
|
// Restore presentationView.alpha in case a previous dismiss left us in a bad state.
|
|
|
|
self.setNavigationBarHidden(false, animated: false)
|
|
|
|
navigationController.setNavigationBarHidden(false, animated: false)
|
|
|
|
self.presentationView.alpha = 1
|
|
|
|
navigationController.presentationView.alpha = 1
|
|
|
|
|
|
|
|
|
|
|
|
// We want to animate the tapped media from it's position in the previous VC
|
|
|
|
// We want to animate the tapped media from it's position in the previous VC
|
|
|
|
// to it's resting place in the center of this view controller.
|
|
|
|
// to it's resting place in the center of this view controller.
|
|
|
@ -328,7 +341,7 @@ class MediaGalleryViewController: OWSNavigationController, MediaGalleryDataSourc
|
|
|
|
// 2. For Video views, the AVPlayerLayer content does not scale with the presentation animation. So you instead get a full scale
|
|
|
|
// 2. For Video views, the AVPlayerLayer content does not scale with the presentation animation. So you instead get a full scale
|
|
|
|
// video, wherein only the cropping is animated.
|
|
|
|
// video, wherein only the cropping is animated.
|
|
|
|
// Using a simple image view allows us to address both these problems relatively easily.
|
|
|
|
// Using a simple image view allows us to address both these problems relatively easily.
|
|
|
|
self.view.alpha = 0.0
|
|
|
|
navigationController.view.alpha = 0.0
|
|
|
|
|
|
|
|
|
|
|
|
guard let detailView = pageViewController.view else {
|
|
|
|
guard let detailView = pageViewController.view else {
|
|
|
|
owsFailDebug("detailView was unexpectedly nil")
|
|
|
|
owsFailDebug("detailView was unexpectedly nil")
|
|
|
@ -337,23 +350,23 @@ class MediaGalleryViewController: OWSNavigationController, MediaGalleryDataSourc
|
|
|
|
|
|
|
|
|
|
|
|
// At this point our media view should be overlayed perfectly
|
|
|
|
// At this point our media view should be overlayed perfectly
|
|
|
|
// by our presentationView. Swapping them out should be imperceptible.
|
|
|
|
// by our presentationView. Swapping them out should be imperceptible.
|
|
|
|
self.presentationView.isHidden = false
|
|
|
|
navigationController.presentationView.isHidden = false
|
|
|
|
// We don't hide the pageViewController entirely - e.g. we want the toolbars to fade in.
|
|
|
|
// We don't hide the pageViewController entirely - e.g. we want the toolbars to fade in.
|
|
|
|
pageViewController.currentViewController.view.isHidden = true
|
|
|
|
pageViewController.currentViewController.view.isHidden = true
|
|
|
|
detailView.backgroundColor = .clear
|
|
|
|
detailView.backgroundColor = .clear
|
|
|
|
self.view.backgroundColor = .clear
|
|
|
|
navigationController.view.backgroundColor = .clear
|
|
|
|
|
|
|
|
|
|
|
|
self.presentationView.layer.cornerRadius = kOWSMessageCellCornerRadius_Small
|
|
|
|
navigationController.presentationView.layer.cornerRadius = kOWSMessageCellCornerRadius_Small
|
|
|
|
|
|
|
|
|
|
|
|
fromViewController.present(self, animated: false) {
|
|
|
|
fromViewController.present(navigationController, animated: false) {
|
|
|
|
|
|
|
|
|
|
|
|
// 1. Fade in the entire view.
|
|
|
|
// 1. Fade in the entire view.
|
|
|
|
UIView.animate(withDuration: 0.1) {
|
|
|
|
UIView.animate(withDuration: 0.1) {
|
|
|
|
self.replacingView?.alpha = 0.0
|
|
|
|
self.replacingView?.alpha = 0.0
|
|
|
|
self.view.alpha = 1.0
|
|
|
|
self.navigationController.view.alpha = 1.0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
self.presentationView.superview?.layoutIfNeeded()
|
|
|
|
self.navigationController.presentationView.superview?.layoutIfNeeded()
|
|
|
|
self.applyFinalMediaViewConstraints()
|
|
|
|
self.applyFinalMediaViewConstraints()
|
|
|
|
|
|
|
|
|
|
|
|
// 2. Animate imageView from it's initial position, which should match where it was
|
|
|
|
// 2. Animate imageView from it's initial position, which should match where it was
|
|
|
@ -364,20 +377,20 @@ class MediaGalleryViewController: OWSNavigationController, MediaGalleryDataSourc
|
|
|
|
options: .curveEaseOut,
|
|
|
|
options: .curveEaseOut,
|
|
|
|
animations: {
|
|
|
|
animations: {
|
|
|
|
|
|
|
|
|
|
|
|
self.presentationView.layer.cornerRadius = 0
|
|
|
|
self.navigationController.presentationView.layer.cornerRadius = 0
|
|
|
|
self.presentationView.superview?.layoutIfNeeded()
|
|
|
|
self.navigationController.presentationView.superview?.layoutIfNeeded()
|
|
|
|
|
|
|
|
|
|
|
|
// fade out content behind the pageViewController
|
|
|
|
// fade out content behind the pageViewController
|
|
|
|
// and behind the presentation view
|
|
|
|
// and behind the presentation view
|
|
|
|
self.view.backgroundColor = Theme.backgroundColor
|
|
|
|
self.navigationController.view.backgroundColor = Theme.backgroundColor
|
|
|
|
},
|
|
|
|
},
|
|
|
|
completion: { (_: Bool) in
|
|
|
|
completion: { (_: Bool) in
|
|
|
|
// At this point our presentation view should be overlayed perfectly
|
|
|
|
// At this point our presentation view should be overlayed perfectly
|
|
|
|
// with our media view. Swapping them out should be imperceptible.
|
|
|
|
// with our media view. Swapping them out should be imperceptible.
|
|
|
|
pageViewController.currentViewController.view.isHidden = false
|
|
|
|
pageViewController.currentViewController.view.isHidden = false
|
|
|
|
self.presentationView.isHidden = true
|
|
|
|
self.navigationController.presentationView.isHidden = true
|
|
|
|
|
|
|
|
|
|
|
|
self.view.isUserInteractionEnabled = true
|
|
|
|
self.navigationController.view.isUserInteractionEnabled = true
|
|
|
|
|
|
|
|
|
|
|
|
pageViewController.wasPresented()
|
|
|
|
pageViewController.wasPresented()
|
|
|
|
|
|
|
|
|
|
|
@ -388,7 +401,7 @@ class MediaGalleryViewController: OWSNavigationController, MediaGalleryDataSourc
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// We don't need to do this when pushing VCs onto the SignalsNavigationController - only when
|
|
|
|
// We don't need to do this when pushing VCs onto the SignalsNavigationController - only when
|
|
|
|
// presenting directly from ConversationVC.
|
|
|
|
// presenting directly from ConversationVC.
|
|
|
|
_ = self.becomeFirstResponder()
|
|
|
|
_ = self.navigationController.becomeFirstResponder()
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -424,7 +437,7 @@ class MediaGalleryViewController: OWSNavigationController, MediaGalleryDataSourc
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
// If from conversation view
|
|
|
|
// If from conversation view
|
|
|
|
mediaTileViewController.focusedItem = focusedItem
|
|
|
|
mediaTileViewController.focusedItem = focusedItem
|
|
|
|
self.pushViewController(mediaTileViewController, animated: true)
|
|
|
|
navigationController.pushViewController(mediaTileViewController, animated: true)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -457,7 +470,7 @@ class MediaGalleryViewController: OWSNavigationController, MediaGalleryDataSourc
|
|
|
|
|
|
|
|
|
|
|
|
guard let pageViewController = self.pageViewController else {
|
|
|
|
guard let pageViewController = self.pageViewController else {
|
|
|
|
owsFailDebug("pageViewController was unexpectedly nil")
|
|
|
|
owsFailDebug("pageViewController was unexpectedly nil")
|
|
|
|
self.dismiss(animated: true)
|
|
|
|
self.navigationController.dismiss(animated: true)
|
|
|
|
|
|
|
|
|
|
|
|
return
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -466,32 +479,32 @@ class MediaGalleryViewController: OWSNavigationController, MediaGalleryDataSourc
|
|
|
|
pageViewController.willBePresentedAgain()
|
|
|
|
pageViewController.willBePresentedAgain()
|
|
|
|
|
|
|
|
|
|
|
|
// TODO fancy zoom animation
|
|
|
|
// TODO fancy zoom animation
|
|
|
|
self.popViewController(animated: true)
|
|
|
|
self.navigationController.popViewController(animated: true)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public func dismissMediaDetailViewController(_ mediaPageViewController: MediaPageViewController, animated isAnimated: Bool, completion: (() -> Void)?) {
|
|
|
|
public func dismissMediaDetailViewController(_ mediaPageViewController: MediaPageViewController, animated isAnimated: Bool, completion: (() -> Void)?) {
|
|
|
|
self.view.isUserInteractionEnabled = false
|
|
|
|
navigationController.view.isUserInteractionEnabled = false
|
|
|
|
UIApplication.shared.isStatusBarHidden = false
|
|
|
|
UIApplication.shared.isStatusBarHidden = false
|
|
|
|
|
|
|
|
|
|
|
|
guard let detailView = mediaPageViewController.view else {
|
|
|
|
guard let detailView = mediaPageViewController.view else {
|
|
|
|
owsFailDebug("detailView was unexpectedly nil")
|
|
|
|
owsFailDebug("detailView was unexpectedly nil")
|
|
|
|
self.presentingViewController?.dismiss(animated: false, completion: completion)
|
|
|
|
self.navigationController.presentingViewController?.dismiss(animated: false, completion: completion)
|
|
|
|
return
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
mediaPageViewController.currentViewController.view.isHidden = true
|
|
|
|
mediaPageViewController.currentViewController.view.isHidden = true
|
|
|
|
self.presentationView.isHidden = false
|
|
|
|
navigationController.presentationView.isHidden = false
|
|
|
|
|
|
|
|
|
|
|
|
// Move the presentationView back to it's initial position, i.e. where
|
|
|
|
// Move the presentationView back to it's initial position, i.e. where
|
|
|
|
// it sits on the screen in the conversation view.
|
|
|
|
// it sits on the screen in the conversation view.
|
|
|
|
let changedItems = currentItem != self.initialDetailItem
|
|
|
|
let changedItems = currentItem != self.initialDetailItem
|
|
|
|
if changedItems {
|
|
|
|
if changedItems {
|
|
|
|
self.presentationView.image = currentItem.attachmentStream.thumbnailImageLarge(success: { [weak self] (image) in
|
|
|
|
navigationController.presentationView.image = currentItem.attachmentStream.thumbnailImageLarge(success: { [weak self] (image) in
|
|
|
|
guard let strongSelf = self else {
|
|
|
|
guard let strongSelf = self else {
|
|
|
|
return
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
strongSelf.presentationView.image = image
|
|
|
|
strongSelf.navigationController.presentationView.image = image
|
|
|
|
}, failure: {
|
|
|
|
}, failure: {
|
|
|
|
Logger.warn("Could not load presentation image.")
|
|
|
|
Logger.warn("Could not load presentation image.")
|
|
|
|
})
|
|
|
|
})
|
|
|
@ -506,14 +519,14 @@ class MediaGalleryViewController: OWSNavigationController, MediaGalleryDataSourc
|
|
|
|
options: .curveEaseOut,
|
|
|
|
options: .curveEaseOut,
|
|
|
|
animations: {
|
|
|
|
animations: {
|
|
|
|
// Move back over it's original location
|
|
|
|
// Move back over it's original location
|
|
|
|
self.presentationView.superview?.layoutIfNeeded()
|
|
|
|
self.navigationController.presentationView.superview?.layoutIfNeeded()
|
|
|
|
|
|
|
|
|
|
|
|
detailView.alpha = 0
|
|
|
|
detailView.alpha = 0
|
|
|
|
|
|
|
|
|
|
|
|
if changedItems {
|
|
|
|
if changedItems {
|
|
|
|
self.presentationView.alpha = 0
|
|
|
|
self.navigationController.presentationView.alpha = 0
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
self.presentationView.layer.cornerRadius = kOWSMessageCellCornerRadius_Small
|
|
|
|
self.navigationController.presentationView.layer.cornerRadius = kOWSMessageCellCornerRadius_Small
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
},
|
|
|
|
completion: { (_: Bool) in
|
|
|
|
completion: { (_: Bool) in
|
|
|
@ -530,24 +543,24 @@ class MediaGalleryViewController: OWSNavigationController, MediaGalleryDataSourc
|
|
|
|
animations: {
|
|
|
|
animations: {
|
|
|
|
guard let replacingView = self.replacingView else {
|
|
|
|
guard let replacingView = self.replacingView else {
|
|
|
|
owsFailDebug("replacingView was unexpectedly nil")
|
|
|
|
owsFailDebug("replacingView was unexpectedly nil")
|
|
|
|
self.presentingViewController?.dismiss(animated: false, completion: completion)
|
|
|
|
self.navigationController.presentingViewController?.dismiss(animated: false, completion: completion)
|
|
|
|
return
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// fade out content and toolbars
|
|
|
|
// fade out content and toolbars
|
|
|
|
self.view.alpha = 0.0
|
|
|
|
self.navigationController.view.alpha = 0.0
|
|
|
|
replacingView.alpha = 1.0
|
|
|
|
replacingView.alpha = 1.0
|
|
|
|
},
|
|
|
|
},
|
|
|
|
completion: { (_: Bool) in
|
|
|
|
completion: { (_: Bool) in
|
|
|
|
self.presentingViewController?.dismiss(animated: false, completion: completion)
|
|
|
|
self.navigationController.presentingViewController?.dismiss(animated: false, completion: completion)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
guard let replacingView = self.replacingView else {
|
|
|
|
guard let replacingView = self.replacingView else {
|
|
|
|
owsFailDebug("replacingView was unexpectedly nil")
|
|
|
|
owsFailDebug("replacingView was unexpectedly nil")
|
|
|
|
self.presentingViewController?.dismiss(animated: false, completion: completion)
|
|
|
|
navigationController.presentingViewController?.dismiss(animated: false, completion: completion)
|
|
|
|
return
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
replacingView.alpha = 1.0
|
|
|
|
replacingView.alpha = 1.0
|
|
|
|
self.presentingViewController?.dismiss(animated: false, completion: completion)
|
|
|
|
navigationController.presentingViewController?.dismiss(animated: false, completion: completion)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -562,17 +575,17 @@ class MediaGalleryViewController: OWSNavigationController, MediaGalleryDataSourc
|
|
|
|
return
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
guard let presentationSuperview = self.presentationView.superview else {
|
|
|
|
guard let presentationSuperview = navigationController.presentationView.superview else {
|
|
|
|
owsFailDebug("presentationView.superview was unexpectedly nil")
|
|
|
|
owsFailDebug("presentationView.superview was unexpectedly nil")
|
|
|
|
return
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
let convertedRect: CGRect = presentationSuperview.convert(originRect, from: UIApplication.shared.keyWindow)
|
|
|
|
let convertedRect: CGRect = presentationSuperview.convert(originRect, from: UIApplication.shared.keyWindow)
|
|
|
|
|
|
|
|
|
|
|
|
self.presentationViewConstraints += self.presentationView.autoSetDimensions(to: convertedRect.size)
|
|
|
|
self.presentationViewConstraints += navigationController.presentationView.autoSetDimensions(to: convertedRect.size)
|
|
|
|
self.presentationViewConstraints += [
|
|
|
|
self.presentationViewConstraints += [
|
|
|
|
self.presentationView.autoPinEdge(toSuperviewEdge: .top, withInset: convertedRect.origin.y),
|
|
|
|
navigationController.presentationView.autoPinEdge(toSuperviewEdge: .top, withInset: convertedRect.origin.y),
|
|
|
|
self.presentationView.autoPinEdge(toSuperviewEdge: .left, withInset: convertedRect.origin.x)
|
|
|
|
navigationController.presentationView.autoPinEdge(toSuperviewEdge: .left, withInset: convertedRect.origin.x)
|
|
|
|
]
|
|
|
|
]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -583,10 +596,10 @@ class MediaGalleryViewController: OWSNavigationController, MediaGalleryDataSourc
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
self.presentationViewConstraints = [
|
|
|
|
self.presentationViewConstraints = [
|
|
|
|
self.presentationView.autoPinEdge(toSuperviewEdge: .leading),
|
|
|
|
navigationController.presentationView.autoPinEdge(toSuperviewEdge: .leading),
|
|
|
|
self.presentationView.autoPinEdge(toSuperviewEdge: .top),
|
|
|
|
navigationController.presentationView.autoPinEdge(toSuperviewEdge: .top),
|
|
|
|
self.presentationView.autoPinEdge(toSuperviewEdge: .trailing),
|
|
|
|
navigationController.presentationView.autoPinEdge(toSuperviewEdge: .trailing),
|
|
|
|
self.presentationView.autoPinEdge(toSuperviewEdge: .bottom)
|
|
|
|
navigationController.presentationView.autoPinEdge(toSuperviewEdge: .bottom)
|
|
|
|
]
|
|
|
|
]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -597,9 +610,9 @@ class MediaGalleryViewController: OWSNavigationController, MediaGalleryDataSourc
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
self.presentationViewConstraints += [
|
|
|
|
self.presentationViewConstraints += [
|
|
|
|
self.presentationView.autoPinEdge(toSuperviewEdge: .leading),
|
|
|
|
navigationController.presentationView.autoPinEdge(toSuperviewEdge: .leading),
|
|
|
|
self.presentationView.autoPinEdge(toSuperviewEdge: .trailing),
|
|
|
|
navigationController.presentationView.autoPinEdge(toSuperviewEdge: .trailing),
|
|
|
|
self.presentationView.autoPinEdge(.top, to: .bottom, of: self.view)
|
|
|
|
navigationController.presentationView.autoPinEdge(.top, to: .bottom, of: self.navigationController.view)
|
|
|
|
]
|
|
|
|
]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -916,10 +929,4 @@ class MediaGalleryViewController: OWSNavigationController, MediaGalleryDataSourc
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return Int(count) - deletedMessages.count
|
|
|
|
return Int(count) - deletedMessages.count
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// MARK: Orientation
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
|
|
|
|
|
|
|
|
return .allButUpsideDown
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|