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
pull/1/head
Michael Kirk 7 years ago
parent e751bbfbbd
commit 6e20f5b654

@ -17,7 +17,9 @@ typedef NS_OPTIONS(NSInteger, MediaGalleryOption) {
@protocol MediaDetailViewControllerDelegate <NSObject> @protocol MediaDetailViewControllerDelegate <NSObject>
- (void)dismissSelfAnimated:(BOOL)isAnimated completion:(void (^_Nullable)(void))completionBlock; - (void)mediaDetailViewController:(MediaDetailViewController *)mediaDetailViewController
requestDeleteConversationViewItem:(ConversationViewItem *)conversationViewItem;
- (void)mediaDetailViewController:(MediaDetailViewController *)mediaDetailViewController - (void)mediaDetailViewController:(MediaDetailViewController *)mediaDetailViewController
isPlayingVideo:(BOOL)isPlayingVideo; isPlayingVideo:(BOOL)isPlayingVideo;

@ -411,35 +411,27 @@ NS_ASSUME_NONNULL_BEGIN
[UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet]; [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet];
[actionSheet [actionSheet
addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"TXT_DELETE_TITLE", nil) addAction:[UIAlertAction
style:UIAlertActionStyleDestructive actionWithTitle:NSLocalizedString(@"TXT_DELETE_TITLE", nil)
handler:^(UIAlertAction *action) { style:UIAlertActionStyleDestructive
OWSAssert([self.presentingViewController handler:^(UIAlertAction *action) {
isKindOfClass:[UINavigationController class]]); [self.delegate mediaDetailViewController:self
UINavigationController *navController requestDeleteConversationViewItem:self.viewItem];
= (UINavigationController *)self.presentingViewController;
// TODO maybe this would be more straight forward if the MessageDetailVC was the
if ([navController.topViewController // deleteDelegate
isKindOfClass:[ConversationViewController class]]) { if ([self.presentingViewController isKindOfClass:[UINavigationController class]]) {
[self.delegate dismissSelfAnimated:YES UINavigationController *navController
completion:^{ = (UINavigationController *)self.presentingViewController;
[self.viewItem deleteAction]; if ([navController.topViewController
}]; isKindOfClass:[MessageDetailViewController class]]) {
} else if ([navController.topViewController MessageDetailViewController *messageDetailViewController
isKindOfClass:[MessageDetailViewController class]]) { = (MessageDetailViewController *)navController.topViewController;
[self.delegate dismissSelfAnimated:YES messageDetailViewController.wasDeleted = YES;
completion:^{ [navController popViewControllerAnimated:YES];
[self.viewItem deleteAction]; }
}]; }
[navController popViewControllerAnimated:YES]; }]];
} else {
OWSFail(@"Unexpected presentation context.");
[self.delegate dismissSelfAnimated:YES
completion:^{
[self.viewItem deleteAction];
}];
}
}]];
[actionSheet addAction:[OWSAlerts cancelAction]]; [actionSheet addAction:[OWSAlerts cancelAction]];

@ -175,6 +175,8 @@ protocol MediaGalleryDataSource: class {
func showAllMedia(focusedItem: MediaGalleryItem) func showAllMedia(focusedItem: MediaGalleryItem)
func dismissMediaDetailViewController(_ mediaDetailViewController: MediaPageViewController, animated isAnimated: Bool, completion: (() -> Void)?) func dismissMediaDetailViewController(_ mediaDetailViewController: MediaPageViewController, animated isAnimated: Bool, completion: (() -> Void)?)
func delete(message: TSMessage)
} }
class MediaGalleryViewController: UINavigationController, MediaGalleryDataSource, MediaTileViewControllerDelegate { class MediaGalleryViewController: UINavigationController, MediaGalleryDataSource, MediaTileViewControllerDelegate {
@ -182,6 +184,7 @@ class MediaGalleryViewController: UINavigationController, MediaGalleryDataSource
private var pageViewController: MediaPageViewController? private var pageViewController: MediaPageViewController?
private let uiDatabaseConnection: YapDatabaseConnection private let uiDatabaseConnection: YapDatabaseConnection
private let editingDatabaseConnection: YapDatabaseConnection
private let mediaGalleryFinder: OWSMediaGalleryFinder private let mediaGalleryFinder: OWSMediaGalleryFinder
private var initialDetailItem: MediaGalleryItem? private var initialDetailItem: MediaGalleryItem?
@ -199,6 +202,9 @@ class MediaGalleryViewController: UINavigationController, MediaGalleryDataSource
self.thread = thread self.thread = thread
assert(uiDatabaseConnection.isInLongLivedReadTransaction()) assert(uiDatabaseConnection.isInLongLivedReadTransaction())
self.uiDatabaseConnection = uiDatabaseConnection self.uiDatabaseConnection = uiDatabaseConnection
self.editingDatabaseConnection = OWSPrimaryStorage.shared().newDatabaseConnection()
self.options = options self.options = options
self.mediaGalleryFinder = OWSMediaGalleryFinder(thread: thread) self.mediaGalleryFinder = OWSMediaGalleryFinder(thread: thread)
@ -631,6 +637,12 @@ class MediaGalleryViewController: UINavigationController, MediaGalleryDataSource
Logger.debug("\(self.logTag) in \(#function) fetching set: \(unfetchedSet)") Logger.debug("\(self.logTag) in \(#function) fetching set: \(unfetchedSet)")
let nsRange: NSRange = NSRange(location: unfetchedSet.min()!, length: unfetchedSet.count) let nsRange: NSRange = NSRange(location: unfetchedSet.min()!, length: unfetchedSet.count)
self.mediaGalleryFinder.enumerateMediaMessages(range: nsRange, transaction: transaction) { (message: TSMessage) in 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 { guard let item: MediaGalleryItem = self.buildGalleryItem(message: message, transaction: transaction) else {
owsFail("\(self.logTag) in \(#function) unexpectedly failed to buildGalleryItem") owsFail("\(self.logTag) in \(#function) unexpectedly failed to buildGalleryItem")
return 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 let kGallerySwipeLoadBatchSize: UInt = 5
internal func galleryItem(after currentItem: MediaGalleryItem) -> MediaGalleryItem? { internal func galleryItem(after currentItem: MediaGalleryItem) -> MediaGalleryItem? {

@ -440,8 +440,6 @@ class MediaPageViewController: UIPageViewController, UIPageViewControllerDataSou
return viewController return viewController
} }
// MARK: MediaDetailViewControllerDelegate
public func dismissSelf(animated isAnimated: Bool, completion: (() -> Void)? = nil) { 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. // Swapping mediaView for presentationView will be perceptible if we're not zoomed out all the way.
// currentVC // currentVC
@ -457,6 +455,28 @@ class MediaPageViewController: UIPageViewController, UIPageViewControllerDataSou
mediaGalleryDataSource.dismissMediaDetailViewController(self, animated: isAnimated, completion: completion) 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) { public func mediaDetailViewController(_ mediaDetailViewController: MediaDetailViewController, isPlayingVideo: Bool) {
guard mediaDetailViewController == currentViewController else { guard mediaDetailViewController == currentViewController else {
Logger.verbose("\(logTag) in \(#function) ignoring stale delegate.") Logger.verbose("\(logTag) in \(#function) ignoring stale delegate.")

@ -145,6 +145,19 @@ public class MediaTileViewController: UICollectionViewController, MediaGalleryCe
// MARK: UIColletionViewDataSource // 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 { override public func numberOfSections(in collectionView: UICollectionView) -> Int {
guard galleryDates.count > 0 else { guard galleryDates.count > 0 else {
// empty gallery // empty gallery

@ -29,6 +29,7 @@ class MessageDetailViewController: OWSViewController, UIScrollViewDelegate, Medi
let mode: MessageMetadataViewMode let mode: MessageMetadataViewMode
let viewItem: ConversationViewItem let viewItem: ConversationViewItem
var message: TSMessage var message: TSMessage
var wasDeleted: Bool = false
var mediaMessageView: MediaMessageView? var mediaMessageView: MediaMessageView?
@ -622,6 +623,10 @@ class MessageDetailViewController: OWSViewController, UIScrollViewDelegate, Medi
updateDBConnectionAndMessageToLatest() updateDBConnectionAndMessageToLatest()
guard !wasDeleted else {
// Item was deleted. Don't bother re-rendering, it will fail and we'll soon be dismissed.
return
}
updateContent() updateContent()
} }

Loading…
Cancel
Save