Fix Delete
from conversation settings > tile > tap for details > delete TODO: - Don't dismiss pager, show next item - dismiss pager if deleting last media // FREEBIE
This commit is contained in:
parent
e751bbfbbd
commit
6e20f5b654
|
@ -17,7 +17,9 @@ typedef NS_OPTIONS(NSInteger, MediaGalleryOption) {
|
|||
|
||||
@protocol MediaDetailViewControllerDelegate <NSObject>
|
||||
|
||||
- (void)dismissSelfAnimated:(BOOL)isAnimated completion:(void (^_Nullable)(void))completionBlock;
|
||||
- (void)mediaDetailViewController:(MediaDetailViewController *)mediaDetailViewController
|
||||
requestDeleteConversationViewItem:(ConversationViewItem *)conversationViewItem;
|
||||
|
||||
- (void)mediaDetailViewController:(MediaDetailViewController *)mediaDetailViewController
|
||||
isPlayingVideo:(BOOL)isPlayingVideo;
|
||||
|
||||
|
|
|
@ -411,35 +411,27 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
[UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet];
|
||||
|
||||
[actionSheet
|
||||
addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"TXT_DELETE_TITLE", nil)
|
||||
style:UIAlertActionStyleDestructive
|
||||
handler:^(UIAlertAction *action) {
|
||||
OWSAssert([self.presentingViewController
|
||||
isKindOfClass:[UINavigationController class]]);
|
||||
UINavigationController *navController
|
||||
= (UINavigationController *)self.presentingViewController;
|
||||
addAction:[UIAlertAction
|
||||
actionWithTitle:NSLocalizedString(@"TXT_DELETE_TITLE", nil)
|
||||
style:UIAlertActionStyleDestructive
|
||||
handler:^(UIAlertAction *action) {
|
||||
[self.delegate mediaDetailViewController:self
|
||||
requestDeleteConversationViewItem:self.viewItem];
|
||||
|
||||
if ([navController.topViewController
|
||||
isKindOfClass:[ConversationViewController class]]) {
|
||||
[self.delegate dismissSelfAnimated:YES
|
||||
completion:^{
|
||||
[self.viewItem deleteAction];
|
||||
}];
|
||||
} else if ([navController.topViewController
|
||||
isKindOfClass:[MessageDetailViewController class]]) {
|
||||
[self.delegate dismissSelfAnimated:YES
|
||||
completion:^{
|
||||
[self.viewItem deleteAction];
|
||||
}];
|
||||
[navController popViewControllerAnimated:YES];
|
||||
} else {
|
||||
OWSFail(@"Unexpected presentation context.");
|
||||
[self.delegate dismissSelfAnimated:YES
|
||||
completion:^{
|
||||
[self.viewItem deleteAction];
|
||||
}];
|
||||
}
|
||||
}]];
|
||||
// TODO maybe this would be more straight forward if the MessageDetailVC was the
|
||||
// deleteDelegate
|
||||
if ([self.presentingViewController isKindOfClass:[UINavigationController class]]) {
|
||||
UINavigationController *navController
|
||||
= (UINavigationController *)self.presentingViewController;
|
||||
if ([navController.topViewController
|
||||
isKindOfClass:[MessageDetailViewController class]]) {
|
||||
MessageDetailViewController *messageDetailViewController
|
||||
= (MessageDetailViewController *)navController.topViewController;
|
||||
messageDetailViewController.wasDeleted = YES;
|
||||
[navController popViewControllerAnimated:YES];
|
||||
}
|
||||
}
|
||||
}]];
|
||||
|
||||
[actionSheet addAction:[OWSAlerts cancelAction]];
|
||||
|
||||
|
|
|
@ -175,6 +175,8 @@ protocol MediaGalleryDataSource: class {
|
|||
|
||||
func showAllMedia(focusedItem: MediaGalleryItem)
|
||||
func dismissMediaDetailViewController(_ mediaDetailViewController: MediaPageViewController, animated isAnimated: Bool, completion: (() -> Void)?)
|
||||
|
||||
func delete(message: TSMessage)
|
||||
}
|
||||
|
||||
class MediaGalleryViewController: UINavigationController, MediaGalleryDataSource, MediaTileViewControllerDelegate {
|
||||
|
@ -182,6 +184,7 @@ class MediaGalleryViewController: UINavigationController, MediaGalleryDataSource
|
|||
private var pageViewController: MediaPageViewController?
|
||||
|
||||
private let uiDatabaseConnection: YapDatabaseConnection
|
||||
private let editingDatabaseConnection: YapDatabaseConnection
|
||||
private let mediaGalleryFinder: OWSMediaGalleryFinder
|
||||
|
||||
private var initialDetailItem: MediaGalleryItem?
|
||||
|
@ -199,6 +202,9 @@ class MediaGalleryViewController: UINavigationController, MediaGalleryDataSource
|
|||
self.thread = thread
|
||||
assert(uiDatabaseConnection.isInLongLivedReadTransaction())
|
||||
self.uiDatabaseConnection = uiDatabaseConnection
|
||||
|
||||
self.editingDatabaseConnection = OWSPrimaryStorage.shared().newDatabaseConnection()
|
||||
|
||||
self.options = options
|
||||
self.mediaGalleryFinder = OWSMediaGalleryFinder(thread: thread)
|
||||
|
||||
|
@ -631,6 +637,12 @@ class MediaGalleryViewController: UINavigationController, MediaGalleryDataSource
|
|||
Logger.debug("\(self.logTag) in \(#function) fetching set: \(unfetchedSet)")
|
||||
let nsRange: NSRange = NSRange(location: unfetchedSet.min()!, length: unfetchedSet.count)
|
||||
self.mediaGalleryFinder.enumerateMediaMessages(range: nsRange, transaction: transaction) { (message: TSMessage) in
|
||||
|
||||
guard !self.deletedMessages.contains(message) else {
|
||||
Logger.debug("\(self.logTag) skipping \(message) which has been deleted.")
|
||||
return
|
||||
}
|
||||
|
||||
guard let item: MediaGalleryItem = self.buildGalleryItem(message: message, transaction: transaction) else {
|
||||
owsFail("\(self.logTag) in \(#function) unexpectedly failed to buildGalleryItem")
|
||||
return
|
||||
|
@ -700,6 +712,65 @@ class MediaGalleryViewController: UINavigationController, MediaGalleryDataSource
|
|||
}
|
||||
}
|
||||
|
||||
var deletedMessages: Set<TSMessage> = Set()
|
||||
func delete(message: TSMessage) {
|
||||
Logger.info("\(logTag) in \(#function) with message: \(String(describing: message.uniqueId)) attachmentId: \(String(describing: message.attachmentIds.firstObject))")
|
||||
|
||||
// TODO put this somewhere reasonable...
|
||||
self.mediaTileViewController.collectionView!.layoutIfNeeded()
|
||||
|
||||
self.editingDatabaseConnection.asyncReadWrite { transaction in
|
||||
message.remove(with: transaction)
|
||||
}
|
||||
|
||||
self.deletedMessages.insert(message)
|
||||
|
||||
var deletedSections: IndexSet = IndexSet()
|
||||
var deletedIndexPaths: [IndexPath] = []
|
||||
|
||||
guard let itemIndex = galleryItems.index(where: { $0.message == message }) else {
|
||||
owsFail("\(logTag) in \(#function) removing unknown item.")
|
||||
return
|
||||
}
|
||||
let item: MediaGalleryItem = galleryItems[itemIndex]
|
||||
|
||||
self.galleryItems.remove(at: itemIndex)
|
||||
|
||||
guard let sectionIndex = sectionDates.index(where: { $0 == item.galleryDate }) else {
|
||||
owsFail("\(logTag) in \(#function) item with unknown date.")
|
||||
return
|
||||
}
|
||||
|
||||
guard var sectionItems = self.sections[item.galleryDate] else {
|
||||
owsFail("\(logTag) in \(#function) item with unknown section")
|
||||
return
|
||||
}
|
||||
|
||||
if sectionItems == [item] {
|
||||
// Last item in section. Delete section.
|
||||
self.sections[item.galleryDate] = nil
|
||||
self.sectionDates.remove(at: sectionIndex)
|
||||
|
||||
deletedSections.insert(sectionIndex + 1)
|
||||
deletedIndexPaths.append(IndexPath(row: 0, section: sectionIndex + 1))
|
||||
} else {
|
||||
guard let sectionRowIndex = sectionItems.index(of: item) else {
|
||||
owsFail("\(logTag) in \(#function) item with unknown sectionRowIndex")
|
||||
return
|
||||
}
|
||||
|
||||
sectionItems.remove(at: sectionRowIndex)
|
||||
self.sections[item.galleryDate] = sectionItems
|
||||
|
||||
deletedIndexPaths.append(IndexPath(row: sectionRowIndex, section: sectionIndex + 1))
|
||||
}
|
||||
|
||||
// TODO? notify pager view
|
||||
|
||||
// notify tile view
|
||||
self.mediaTileViewController.updatedDataSource(deletedSections: deletedSections, deletedItems: deletedIndexPaths)
|
||||
}
|
||||
|
||||
let kGallerySwipeLoadBatchSize: UInt = 5
|
||||
|
||||
internal func galleryItem(after currentItem: MediaGalleryItem) -> MediaGalleryItem? {
|
||||
|
|
|
@ -440,8 +440,6 @@ class MediaPageViewController: UIPageViewController, UIPageViewControllerDataSou
|
|||
return viewController
|
||||
}
|
||||
|
||||
// MARK: MediaDetailViewControllerDelegate
|
||||
|
||||
public func dismissSelf(animated isAnimated: Bool, completion: (() -> Void)? = nil) {
|
||||
// Swapping mediaView for presentationView will be perceptible if we're not zoomed out all the way.
|
||||
// currentVC
|
||||
|
@ -457,6 +455,28 @@ class MediaPageViewController: UIPageViewController, UIPageViewControllerDataSou
|
|||
mediaGalleryDataSource.dismissMediaDetailViewController(self, animated: isAnimated, completion: completion)
|
||||
}
|
||||
|
||||
// MARK: MediaDetailViewControllerDelegate
|
||||
|
||||
public func mediaDetailViewController(_ mediaDetailViewController: MediaDetailViewController, requestDelete conversationViewItem: ConversationViewItem) {
|
||||
guard let mediaGalleryDataSource = self.mediaGalleryDataSource else {
|
||||
owsFail("\(logTag) in \(#function) mediaGalleryDataSource was unexpectedly nil")
|
||||
self.presentingViewController?.dismiss(animated: true)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
guard let message = conversationViewItem.interaction as? TSMessage else {
|
||||
owsFail("\(logTag) in \(#function) unexpected interaction: \(type(of: conversationViewItem))")
|
||||
self.presentingViewController?.dismiss(animated: true)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
dismissSelf(animated: true) {
|
||||
mediaGalleryDataSource.delete(message: message)
|
||||
}
|
||||
}
|
||||
|
||||
public func mediaDetailViewController(_ mediaDetailViewController: MediaDetailViewController, isPlayingVideo: Bool) {
|
||||
guard mediaDetailViewController == currentViewController else {
|
||||
Logger.verbose("\(logTag) in \(#function) ignoring stale delegate.")
|
||||
|
|
|
@ -145,6 +145,19 @@ public class MediaTileViewController: UICollectionViewController, MediaGalleryCe
|
|||
|
||||
// MARK: UIColletionViewDataSource
|
||||
|
||||
public func updatedDataSource(deletedSections: IndexSet, deletedItems: [IndexPath]) {
|
||||
guard let collectionView = self.collectionView else {
|
||||
owsFail("\(logTag) in \(#function) collectionView was unexpetedly nil")
|
||||
return
|
||||
}
|
||||
|
||||
// If collectionView hasn't been laid out yet, it won't have the sections/rows to remove.
|
||||
collectionView.performBatchUpdates({
|
||||
collectionView.deleteSections(deletedSections)
|
||||
collectionView.deleteItems(at: deletedItems)
|
||||
})
|
||||
}
|
||||
|
||||
override public func numberOfSections(in collectionView: UICollectionView) -> Int {
|
||||
guard galleryDates.count > 0 else {
|
||||
// empty gallery
|
||||
|
|
|
@ -29,6 +29,7 @@ class MessageDetailViewController: OWSViewController, UIScrollViewDelegate, Medi
|
|||
let mode: MessageMetadataViewMode
|
||||
let viewItem: ConversationViewItem
|
||||
var message: TSMessage
|
||||
var wasDeleted: Bool = false
|
||||
|
||||
var mediaMessageView: MediaMessageView?
|
||||
|
||||
|
@ -622,6 +623,10 @@ class MessageDetailViewController: OWSViewController, UIScrollViewDelegate, Medi
|
|||
|
||||
updateDBConnectionAndMessageToLatest()
|
||||
|
||||
guard !wasDeleted else {
|
||||
// Item was deleted. Don't bother re-rendering, it will fail and we'll soon be dismissed.
|
||||
return
|
||||
}
|
||||
updateContent()
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue