diff --git a/Mixin.xcodeproj/project.pbxproj b/Mixin.xcodeproj/project.pbxproj index db78a072b6..0cfd3852bd 100644 --- a/Mixin.xcodeproj/project.pbxproj +++ b/Mixin.xcodeproj/project.pbxproj @@ -625,7 +625,7 @@ 7CF9503F277D8839000AECC7 /* MediasPreviewViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CF9503E277D8839000AECC7 /* MediasPreviewViewController.swift */; }; 7CF95041277D8904000AECC7 /* SelectedMediaCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CF95040277D8904000AECC7 /* SelectedMediaCell.swift */; }; 7CFF1387277D5C3400FA745D /* MediasPreviewWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CFF1386277D5C3400FA745D /* MediasPreviewWindow.swift */; }; - 7CFF1389277D5C6600FA745D /* MediaPreviewWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7CFF1388277D5C6600FA745D /* MediaPreviewWindow.xib */; }; + 7CFF1389277D5C6600FA745D /* MediasPreviewWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7CFF1388277D5C6600FA745D /* MediasPreviewWindow.xib */; }; 811C8154F03C8CBB72DBA1F4 /* Pods_MixinShare.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 67A8E0E9B65F16ADB27E6F25 /* Pods_MixinShare.framework */; }; 842347EE2695BA6400009A39 /* InitializeBotJob.swift in Sources */ = {isa = PBXBuildFile; fileRef = 842347ED2695BA6400009A39 /* InitializeBotJob.swift */; }; 94046B91272DC265007C1D4A /* GroupCallMembersDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94046B90272DC265007C1D4A /* GroupCallMembersDataSource.swift */; }; @@ -1619,7 +1619,7 @@ 7CF9503E277D8839000AECC7 /* MediasPreviewViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediasPreviewViewController.swift; sourceTree = ""; }; 7CF95040277D8904000AECC7 /* SelectedMediaCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectedMediaCell.swift; sourceTree = ""; }; 7CFF1386277D5C3400FA745D /* MediasPreviewWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediasPreviewWindow.swift; sourceTree = ""; }; - 7CFF1388277D5C6600FA745D /* MediaPreviewWindow.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MediaPreviewWindow.xib; sourceTree = ""; }; + 7CFF1388277D5C6600FA745D /* MediasPreviewWindow.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MediasPreviewWindow.xib; sourceTree = ""; }; 842347ED2695BA6400009A39 /* InitializeBotJob.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InitializeBotJob.swift; sourceTree = ""; }; 8C43D9D96FCB101481DFD90F /* Pods-Mixin.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Mixin.release.xcconfig"; path = "Pods/Target Support Files/Pods-Mixin/Pods-Mixin.release.xcconfig"; sourceTree = ""; }; 94046B90272DC265007C1D4A /* GroupCallMembersDataSource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GroupCallMembersDataSource.swift; sourceTree = ""; }; @@ -2177,7 +2177,6 @@ 94D63DD52646C29100FD7EE8 /* MessageViewModelFactory.swift */, 7CC7304F2745F95D002780F5 /* StickerStore.swift */, 7CF7416D27DAD93000DA0004 /* SnapCenterFlowLayout.swift */, - 7C247AA6277AEDD100112A30 /* StackedPhotoLayout.swift */, ); path = Model; sourceTree = ""; @@ -2568,13 +2567,6 @@ path = ReCaptcha; sourceTree = ""; }; - 7C0E1D0B2786E9F400762FBE /* Model */ = { - isa = PBXGroup; - children = ( - ); - path = Model; - sourceTree = ""; - }; 7C35D1CF2689C04F002B5BBC /* Cells */ = { isa = PBXGroup; children = ( @@ -2933,7 +2925,6 @@ DF016B2C2098B35F00B8FFDE /* Windows */ = { isa = PBXGroup; children = ( - 7C0E1D0B2786E9F400762FBE /* Model */, DF53BB6D202362A9002BF028 /* Cells */, DF53BB6620233647002BF028 /* Views */, DF43304422648B32006D971D /* AssetInfoWindow.swift */, @@ -2973,7 +2964,7 @@ 7C6132B527953B15002777EE /* DeleteAccountAbortWindow.swift */, 7C6132B727953B4F002777EE /* DeleteAccountAbortWindow.xib */, 7CFF1386277D5C3400FA745D /* MediasPreviewWindow.swift */, - 7CFF1388277D5C6600FA745D /* MediaPreviewWindow.xib */, + 7CFF1388277D5C6600FA745D /* MediasPreviewWindow.xib */, ); path = Windows; sourceTree = ""; @@ -3933,7 +3924,7 @@ DF44B0CE20C6897D00A099B6 /* EmptyView.xib in Resources */, 277FF70C1F909A1200DBB2EB /* Assets.xcassets in Resources */, 7BF19C20241D40FA00B192D5 /* LocationSearchView.xib in Resources */, - 7CFF1389277D5C6600FA745D /* MediaPreviewWindow.xib in Resources */, + 7CFF1389277D5C6600FA745D /* MediasPreviewWindow.xib in Resources */, 7B8BB590234F36C000991ACB /* Colors.xcassets in Resources */, 94B8D18A266E41D300F43CBB /* DatabaseDiagnosticView.xib in Resources */, 7BFCB7762419FC5B00E7BC43 /* LocationCell.xib in Resources */, diff --git a/Mixin/UserInterface/Controllers/Chat/Cells/PhotoInputGridCell.swift b/Mixin/UserInterface/Controllers/Chat/Cells/PhotoInputGridCell.swift index a25f70462c..fa5d6ab36e 100644 --- a/Mixin/UserInterface/Controllers/Chat/Cells/PhotoInputGridCell.swift +++ b/Mixin/UserInterface/Controllers/Chat/Cells/PhotoInputGridCell.swift @@ -35,7 +35,7 @@ class PhotoInputGridCell: UICollectionViewCell { overlayView.isHidden = true } - func updateSelectedIndex(_ index: Int?) { + func updateBadge(with index: Int?) { if let index = index { badge.text = "\(index + 1)" badge.borderWidth = 0 diff --git a/Mixin/UserInterface/Controllers/Chat/Cells/SelectedMediaCell.swift b/Mixin/UserInterface/Controllers/Chat/Cells/SelectedMediaCell.swift index e0ce2c4985..46800da456 100644 --- a/Mixin/UserInterface/Controllers/Chat/Cells/SelectedMediaCell.swift +++ b/Mixin/UserInterface/Controllers/Chat/Cells/SelectedMediaCell.swift @@ -9,7 +9,7 @@ class SelectedMediaCell: UICollectionViewCell { @IBOutlet weak var imageView: SDAnimatedImageView! @IBOutlet weak var mediaTypeView: MediaTypeOverlayView! - var onRemove: (() -> Void)? + var deselectAsset: (() -> Void)? private lazy var imageRequestOptions: PHImageRequestOptions = { let options = PHImageRequestOptions() @@ -43,7 +43,7 @@ class SelectedMediaCell: UICollectionViewCell { } @IBAction func closeAction(_ sender: Any) { - onRemove?() + deselectAsset?() } } diff --git a/Mixin/UserInterface/Controllers/Chat/ConversationViewController.swift b/Mixin/UserInterface/Controllers/Chat/ConversationViewController.swift index f3147802b3..7fdff4b870 100644 --- a/Mixin/UserInterface/Controllers/Chat/ConversationViewController.swift +++ b/Mixin/UserInterface/Controllers/Chat/ConversationViewController.swift @@ -105,12 +105,7 @@ class ConversationViewController: UIViewController { private(set) lazy var imagePickerController = ImagePickerController(initialCameraPosition: .rear, cropImageAfterPicked: false, parent: self, delegate: self) private lazy var userHandleViewController = R.storyboard.chat.user_handle()! - private lazy var multipleSelectionActionView: MultipleSelectionActionView = { - let view = R.nib.multipleSelectionActionView(owner: self)! - view.delegate = self - view.showCancelButton = false - return view - }() + private lazy var multipleSelectionActionView = R.nib.multipleSelectionActionView(owner: self)! private lazy var announcementBadgeContentView = R.nib.announcementBadgeContentView(owner: self)! private lazy var strangerHintView: StrangerHintView = { @@ -521,6 +516,51 @@ class ConversationViewController: UIViewController { } } + @IBAction func multipleSelectionAction(_ sender: Any) { + switch multipleSelectionActionView.intent { + case .forward: + let messages = dataSource.selectedViewModels.values + .map({ $0.message }) + .sorted(by: { $0.createdAt < $1.createdAt }) + let containsTranscriptMessage = messages.contains { + $0.category.hasSuffix("_TRANSCRIPT") + } + if messages.count == 1 || containsTranscriptMessage { + let vc = MessageReceiverViewController.instance(content: .messages(messages)) + navigationController?.pushViewController(vc, animated: true) + } else { + let alert = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet) + alert.addAction(UIAlertAction(title: R.string.localizable.chat_forward_one_by_one(), style: .default, handler: { (_) in + let vc = MessageReceiverViewController.instance(content: .messages(messages)) + self.navigationController?.pushViewController(vc, animated: true) + })) + alert.addAction(UIAlertAction(title: R.string.localizable.chat_forward_combined(), style: .default, handler: { (_) in + let vc = MessageReceiverViewController.instance(content: .transcript(messages)) + self.navigationController?.pushViewController(vc, animated: true) + })) + alert.addAction(UIAlertAction(title: R.string.localizable.dialog_button_cancel(), style: .cancel, handler: nil)) + present(alert, animated: true, completion: nil) + } + case .delete: + let viewModels = dataSource.selectedViewModels.values.map({ $0 }) + let controller = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet) + if !viewModels.contains(where: { $0.message.userId != myUserId || !$0.message.canRecall }) { + controller.addAction(UIAlertAction(title: Localized.ACTION_DELETE_EVERYONE, style: .destructive, handler: { (_) in + if AppGroupUserDefaults.User.hasShownRecallTips { + self.deleteForEveryone(viewModels: viewModels) + } else { + self.showRecallTips(viewModels: viewModels) + } + })) + } + controller.addAction(UIAlertAction(title: Localized.ACTION_DELETE_ME, style: .destructive, handler: { (_) in + self.deleteForMe(viewModels: viewModels) + })) + controller.addAction(UIAlertAction(title: Localized.DIALOG_BUTTON_CANCEL, style: .cancel, handler: nil)) + self.present(controller, animated: true, completion: nil) + } + } + @IBAction func dismissAnnouncementBadgeAction(_ sender: Any) { if dataSource.category == .group { AppGroupUserDefaults.User.hasUnreadAnnouncement.removeValue(forKey: conversationId) @@ -1299,55 +1339,6 @@ class ConversationViewController: UIViewController { } -extension ConversationViewController: MultipleSelectionActionViewDelegate { - - func multipleSelectionActionViewDidTapAction(_ view: MultipleSelectionActionView) { - switch view.intent { - case .forward: - let messages = dataSource.selectedViewModels.values - .map({ $0.message }) - .sorted(by: { $0.createdAt < $1.createdAt }) - let containsTranscriptMessage = messages.contains { - $0.category.hasSuffix("_TRANSCRIPT") - } - if messages.count == 1 || containsTranscriptMessage { - let vc = MessageReceiverViewController.instance(content: .messages(messages)) - navigationController?.pushViewController(vc, animated: true) - } else { - let alert = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet) - alert.addAction(UIAlertAction(title: R.string.localizable.chat_forward_one_by_one(), style: .default, handler: { (_) in - let vc = MessageReceiverViewController.instance(content: .messages(messages)) - self.navigationController?.pushViewController(vc, animated: true) - })) - alert.addAction(UIAlertAction(title: R.string.localizable.chat_forward_combined(), style: .default, handler: { (_) in - let vc = MessageReceiverViewController.instance(content: .transcript(messages)) - self.navigationController?.pushViewController(vc, animated: true) - })) - alert.addAction(UIAlertAction(title: R.string.localizable.dialog_button_cancel(), style: .cancel, handler: nil)) - present(alert, animated: true, completion: nil) - } - case .delete: - let viewModels = dataSource.selectedViewModels.values.map({ $0 }) - let controller = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet) - if !viewModels.contains(where: { $0.message.userId != myUserId || !$0.message.canRecall }) { - controller.addAction(UIAlertAction(title: Localized.ACTION_DELETE_EVERYONE, style: .destructive, handler: { (_) in - if AppGroupUserDefaults.User.hasShownRecallTips { - self.deleteForEveryone(viewModels: viewModels) - } else { - self.showRecallTips(viewModels: viewModels) - } - })) - } - controller.addAction(UIAlertAction(title: Localized.ACTION_DELETE_ME, style: .destructive, handler: { (_) in - self.deleteForMe(viewModels: self.dataSource.selectedViewModels.values.map({ $0 })) - })) - controller.addAction(UIAlertAction(title: Localized.DIALOG_BUTTON_CANCEL, style: .cancel, handler: nil)) - self.present(controller, animated: true, completion: nil) - } - } - -} - // MARK: - UIGestureRecognizerDelegate extension ConversationViewController: UIGestureRecognizerDelegate { @@ -1965,7 +1956,7 @@ extension ConversationViewController { SendMessageService.shared.sendPinMessages(items: [message], conversationId: conversationId, action: .pin) case .unpin: dataSource.postponeMessagePinningUpdate(with: message.messageId) - SendMessageService.shared.sendPinMessages(items: [message], conversationId: conversationId, action: .pin) + SendMessageService.shared.sendPinMessages(items: [message], conversationId: conversationId, action: .unpin) } } diff --git a/Mixin/UserInterface/Controllers/Chat/MediasPreviewViewController.swift b/Mixin/UserInterface/Controllers/Chat/MediasPreviewViewController.swift index 0de6d8e176..60db43b6cc 100644 --- a/Mixin/UserInterface/Controllers/Chat/MediasPreviewViewController.swift +++ b/Mixin/UserInterface/Controllers/Chat/MediasPreviewViewController.swift @@ -37,11 +37,13 @@ final class MediasPreviewViewController: UIViewController { extension MediasPreviewViewController { func add(_ asset: PHAsset) { + guard !assets.contains(asset) else { + return + } assets.append(asset) - collectionView.insertItems(at: [IndexPath(item: assets.count - 1, section: 0)]) - collectionView.scrollToItem(at: IndexPath(item: assets.count - 1, section: 0), - at: .centeredHorizontally, - animated: true) + let index = IndexPath(item: assets.count - 1, section: 0) + collectionView.insertItems(at: [index]) + collectionView.scrollToItem(at: index, at: .centeredHorizontally, animated: true) } func remove(_ asset: PHAsset) { @@ -78,7 +80,7 @@ extension MediasPreviewViewController: UICollectionViewDataSource { if indexPath.item < assets.count { let asset = assets[indexPath.item] cell.load(asset: asset, size: cellSizeForItemAt(indexPath.item)) - cell.onRemove = { [weak self] in + cell.deselectAsset = { [weak self] in guard let self = self else { return } @@ -117,13 +119,13 @@ extension MediasPreviewViewController { let width: CGFloat let ratio = CGFloat(asset.pixelWidth) / CGFloat(asset.pixelHeight) if ratio > 1 { - width = height / 3 * 4 + width = ceil(height / 3 * 4) } else if ratio < 1 { - width = height / 4 * 3 + width = ceil(height / 4 * 3) } else { width = height } - let size = CGSize(width: ceil(width), height: ceil(height)) + let size = CGSize(width: width, height: height) cellSizeCache[asset.localIdentifier] = size return size } diff --git a/Mixin/UserInterface/Controllers/Chat/Model/ConversationDataSource.swift b/Mixin/UserInterface/Controllers/Chat/Model/ConversationDataSource.swift index 8eee4e20e8..cc4ed8590c 100644 --- a/Mixin/UserInterface/Controllers/Chat/Model/ConversationDataSource.swift +++ b/Mixin/UserInterface/Controllers/Chat/Model/ConversationDataSource.swift @@ -47,7 +47,6 @@ class ConversationDataSource { private var messageProcessingIsCancelled = false private var didInitializedData = false private var pendingPinningUpdateMessageId: String? - private var stackedPhotoMessages = [MessageItem]() var layoutSize: CGSize { Queue.main.autoSync { diff --git a/Mixin/UserInterface/Controllers/Chat/PhotoInputGridViewController.swift b/Mixin/UserInterface/Controllers/Chat/PhotoInputGridViewController.swift index 0610a81c0d..b5a55de246 100644 --- a/Mixin/UserInterface/Controllers/Chat/PhotoInputGridViewController.swift +++ b/Mixin/UserInterface/Controllers/Chat/PhotoInputGridViewController.swift @@ -139,7 +139,7 @@ extension PhotoInputGridViewController: UICollectionViewDataSource { cell.imageView.contentMode = .scaleAspectFill cell.imageView.backgroundColor = .background cell.badge.isHidden = false - cell.updateSelectedIndex(selectedAssets.firstIndex(of: asset)) + cell.updateBadge(with: selectedAssets.firstIndex(of: asset)) imageManager.requestImage(for: asset, targetSize: thumbnailSize, contentMode: .aspectFill, options: imageRequestOptions) { [weak cell] (image, _) in guard let cell = cell, cell.identifier == asset.localIdentifier else { return diff --git a/Mixin/UserInterface/Controllers/Chat/PhotoInputViewController.swift b/Mixin/UserInterface/Controllers/Chat/PhotoInputViewController.swift index f98db41145..0362cddb50 100644 --- a/Mixin/UserInterface/Controllers/Chat/PhotoInputViewController.swift +++ b/Mixin/UserInterface/Controllers/Chat/PhotoInputViewController.swift @@ -22,7 +22,7 @@ class PhotoInputViewController: UIViewController, ConversationInputAccessible { } private weak var mediasPreviewControllerIfLoaded: MediasPreviewViewController? - private lazy var mediasPreviewViewController: MediasPreviewViewController = { + private lazy var mediasPreviewController: MediasPreviewViewController = { let controller = R.storyboard.chat.selected_medias()! controller.delegate = self mediasPreviewControllerIfLoaded = controller @@ -235,14 +235,14 @@ extension PhotoInputViewController: PhotoInputGridViewControllerDelegate { if !controller.selectedAssets.isEmpty { presentMediasPreviewControllerAnimated() } - mediasPreviewViewController.add(asset) + mediasPreviewController.add(asset) } func photoInputGridViewController(_ controller: PhotoInputGridViewController, didDeselect asset: PHAsset) { if controller.selectedAssets.isEmpty { dismissMediasPreviewControllerAnimated() } else { - mediasPreviewViewController.remove(asset) + mediasPreviewController.remove(asset) } } @@ -282,21 +282,21 @@ extension PhotoInputViewController: MediasPreviewViewControllerDelegate { extension PhotoInputViewController: MediasPreviewWindowDelegate { - func mediasPreviewWindow(_ window: MediasPreviewWindow, willDismiss assets: [PHAsset]) { + func mediasPreviewWindow(_ window: MediasPreviewWindow, willDismissWindow assets: [PHAsset]) { if assets.isEmpty { gridViewController.deselectAll() dismissMediasPreviewControllerAnimated() } else { gridViewController.updateSelectdAssets(assets) - mediasPreviewViewController.updateAssets(assets) + mediasPreviewController.updateAssets(assets) } } - func mediasPreviewWindow(_ window: MediasPreviewWindow, didSendItems assets: [PHAsset]) { + func mediasPreviewWindow(_ window: MediasPreviewWindow, didTapSendItems assets: [PHAsset]) { sendItems(assets: assets) } - func mediasPreviewWindow(_ window: MediasPreviewWindow, didSendFiles assets: [PHAsset]) { + func mediasPreviewWindow(_ window: MediasPreviewWindow, didTapSendFiles assets: [PHAsset]) { sendAsFiles(assets: assets) } @@ -345,7 +345,7 @@ extension PhotoInputViewController { private func presentMediasPreviewControllerAnimated() { guard - mediasPreviewViewController.parent == nil, + mediasPreviewController.parent == nil, let conversationInputViewController = conversationInputViewController, let inputBarView = conversationInputViewController.inputBarView, let conversationViewController = conversationInputViewController.parent @@ -353,8 +353,8 @@ extension PhotoInputViewController { return } gridViewController.view.isUserInteractionEnabled = false - let previewController = mediasPreviewViewController - let previewViewHeight = mediasPreviewViewController.viewHeight + let previewController = mediasPreviewController + let previewViewHeight = mediasPreviewController.viewHeight addChild(previewController) view.insertSubview(previewController.view, at: 0) previewController.view.snp.makeConstraints({ (make) in @@ -380,15 +380,15 @@ extension PhotoInputViewController { private func dismissMediasPreviewControllerAnimated() { guard - mediasPreviewViewController.parent != nil, + mediasPreviewController.parent != nil, let conversationInputViewController = conversationInputViewController, let inputBarView = conversationInputViewController.inputBarView else { return } gridViewController.view.isUserInteractionEnabled = false - let previewController = mediasPreviewViewController - let previewViewHeight = mediasPreviewViewController.viewHeight + let previewController = mediasPreviewController + let previewViewHeight = mediasPreviewController.viewHeight addChild(previewController) view.insertSubview(previewController.view, at: 0) previewController.view.snp.remakeConstraints({ (make) in diff --git a/Mixin/UserInterface/Controllers/Chat/PinMessagesPreviewViewController.swift b/Mixin/UserInterface/Controllers/Chat/PinMessagesPreviewViewController.swift index 62915067c5..ec2aef51be 100644 --- a/Mixin/UserInterface/Controllers/Chat/PinMessagesPreviewViewController.swift +++ b/Mixin/UserInterface/Controllers/Chat/PinMessagesPreviewViewController.swift @@ -19,6 +19,12 @@ final class PinMessagesPreviewViewController: StaticMessagesViewController { private var ignoresPinMessageChangeNotification = false private var canUnpinMessages = false + private var layoutWidth: CGFloat { + Queue.main.autoSync { + AppDelegate.current.mainWindow.bounds.width + } + } + private weak var bottomBarViewIfAdded: UIView? init(conversationId: String, isGroup: Bool) { diff --git a/Mixin/UserInterface/Controllers/Chat/StaticMessagesViewController.swift b/Mixin/UserInterface/Controllers/Chat/StaticMessagesViewController.swift index c5fd541e21..67aa43585b 100644 --- a/Mixin/UserInterface/Controllers/Chat/StaticMessagesViewController.swift +++ b/Mixin/UserInterface/Controllers/Chat/StaticMessagesViewController.swift @@ -17,11 +17,6 @@ class StaticMessagesViewController: UIViewController { var dates: [String] = [] var viewModels: [String: [MessageViewModel]] = [:] - var layoutWidth: CGFloat { - Queue.main.autoSync { - AppDelegate.current.mainWindow.bounds.width - } - } private let conversationId: String private let audioManager: StaticAudioMessagePlayingManager @@ -184,41 +179,12 @@ class StaticMessagesViewController: UIViewController { } } - func removeViewModel(at indexPath: IndexPath) -> (didRemoveRow: Bool, didRemoveSection: Bool) { - var didRemoveRow = false - var didRemoveSection = false - let date = dates[indexPath.section] - if let _ = viewModels[date]?.remove(at: indexPath.row) { - didRemoveRow = true - } - if let viewModels = viewModels[date], viewModels.isEmpty { - if let index = dates.firstIndex(of: date) { - didRemoveSection = true - dates.remove(at: index) - } - self.viewModels[date] = nil - } - if let viewModels = self.viewModels[date] { - let indexBeforeDeletedMessage = indexPath.row - 1 - let indexAfterDeletedMessage = indexPath.row - if indexBeforeDeletedMessage >= 0 { - let style = factory.style(forIndex: indexBeforeDeletedMessage, viewModels: viewModels) - self.viewModels[date]?[indexBeforeDeletedMessage].style = style - } - if indexAfterDeletedMessage < viewModels.count { - let style = factory.style(forIndex: indexAfterDeletedMessage, viewModels: viewModels) - self.viewModels[date]?[indexAfterDeletedMessage].style = style - } - } - return (didRemoveRow, didRemoveSection) - } - } // MARK: - Actions extension StaticMessagesViewController { - @objc func tapAction(_ recognizer: UIGestureRecognizer) { + @objc private func tapAction(_ recognizer: UIGestureRecognizer) { let tappedIndexPath = tableView.indexPathForRow(at: recognizer.location(in: tableView)) let tappedViewModel: MessageViewModel? = { if let indexPath = tappedIndexPath { @@ -588,9 +554,10 @@ extension StaticMessagesViewController { return } DispatchQueue.main.sync { + let layoutWidth = AppDelegate.current.mainWindow.bounds.width let date = DateFormatter.yyyymmdd.string(from: message.createdAt.toUTCDate()) if let style = self.viewModels[date]?[indexPath.row].style { - let viewModel = self.factory.viewModel(withMessage: message, style: style, fits: self.layoutWidth) + let viewModel = self.factory.viewModel(withMessage: message, style: style, fits: layoutWidth) self.viewModels[date]?[indexPath.row] = viewModel self.tableView.reloadData() } diff --git a/Mixin/UserInterface/Controllers/Chat/TranscriptPreviewViewController.swift b/Mixin/UserInterface/Controllers/Chat/TranscriptPreviewViewController.swift index 14b5fedccb..ae324315c2 100644 --- a/Mixin/UserInterface/Controllers/Chat/TranscriptPreviewViewController.swift +++ b/Mixin/UserInterface/Controllers/Chat/TranscriptPreviewViewController.swift @@ -143,6 +143,7 @@ extension TranscriptPreviewViewController { } private func reloadData() { + let layoutWidth = AppDelegate.current.mainWindow.bounds.width queue.async { [weak self] in guard let self = self else { return @@ -152,7 +153,7 @@ extension TranscriptPreviewViewController { let children = items.compactMap { item in TranscriptMessage(transcriptId: transcriptId, mediaUrl: item.mediaUrl, thumbImage: item.thumbImage, messageItem: item) } - let (dates, viewModels) = self.categorizedViewModels(with: items, fits: self.layoutWidth) + let (dates, viewModels) = self.categorizedViewModels(with: items, fits: layoutWidth) DispatchQueue.main.async { self.childMessages = children self.dates = dates diff --git a/Mixin/UserInterface/Controllers/Chat/Views/MultipleSelectionActionView.swift b/Mixin/UserInterface/Controllers/Chat/Views/MultipleSelectionActionView.swift index d061597166..fc488deb74 100644 --- a/Mixin/UserInterface/Controllers/Chat/Views/MultipleSelectionActionView.swift +++ b/Mixin/UserInterface/Controllers/Chat/Views/MultipleSelectionActionView.swift @@ -1,41 +1,14 @@ import UIKit -@objc protocol MultipleSelectionActionViewDelegate { - @objc optional func multipleSelectionActionViewDidTapCancel(_ view: MultipleSelectionActionView) - @objc optional func multipleSelectionActionViewDidTapAction(_ view: MultipleSelectionActionView) -} - class MultipleSelectionActionView: UIView { @IBOutlet weak var label: UILabel! - @IBOutlet weak var actionButton: UIButton! - @IBOutlet weak var cancelButton: UIButton! - - @IBOutlet weak var hideCancelButtonConstraint: NSLayoutConstraint! - @IBOutlet weak var showCancelButtonConstraint: NSLayoutConstraint! - - weak var delegate: MultipleSelectionActionViewDelegate? + @IBOutlet weak var button: UIButton! var preferredHeight: CGFloat { 50 + safeAreaInsets.bottom } - var showCancelButton: Bool = true { - didSet { - if showCancelButton { - label.textAlignment = .center - cancelButton.isHidden = false - showCancelButtonConstraint.priority = .defaultHigh - hideCancelButtonConstraint.priority = .defaultLow - } else { - label.textAlignment = .left - cancelButton.isHidden = true - showCancelButtonConstraint.priority = .defaultLow - hideCancelButtonConstraint.priority = .defaultHigh - } - } - } - var intent: MultipleSelectionIntent = .forward { didSet { let image: UIImage? @@ -45,7 +18,7 @@ class MultipleSelectionActionView: UIView { case .delete: image = R.image.conversation.ic_selection_action_delete() } - actionButton.setImage(image, for: .normal) + button.setImage(image, for: .normal) updateButtonAvailability() } } @@ -61,24 +34,15 @@ class MultipleSelectionActionView: UIView { super.safeAreaInsetsDidChange() frame.size.height = preferredHeight } - - @IBAction func didTapActionButton(_ sender: Any) { - delegate?.multipleSelectionActionViewDidTapAction?(self) - } - - @IBAction func didTapCancelButton(_ sender: Any) { - delegate?.multipleSelectionActionViewDidTapCancel?(self) - } private func updateButtonAvailability() { switch intent { case .forward: - actionButton.isEnabled = numberOfSelection > 0 + button.isEnabled = numberOfSelection > 0 && numberOfSelection <= maxNumberOfTranscriptChildren case .delete: - actionButton.isEnabled = numberOfSelection > 0 + button.isEnabled = numberOfSelection > 0 } - cancelButton.isEnabled = numberOfSelection > 0 } } diff --git a/Mixin/UserInterface/Controllers/Chat/Views/MultipleSelectionActionView.xib b/Mixin/UserInterface/Controllers/Chat/Views/MultipleSelectionActionView.xib index ccb1c2a343..ac7c5e04b3 100644 --- a/Mixin/UserInterface/Controllers/Chat/Views/MultipleSelectionActionView.xib +++ b/Mixin/UserInterface/Controllers/Chat/Views/MultipleSelectionActionView.xib @@ -1,9 +1,9 @@ - + - + @@ -15,8 +15,8 @@ - - - - - - + + - - + - - - + - @@ -82,10 +62,7 @@ - - - - + diff --git a/Mixin/UserInterface/Windows/Cells/MediaPreviewCell.xib b/Mixin/UserInterface/Windows/Cells/MediaPreviewCell.xib index 3e8d9fd020..87ab4cf355 100644 --- a/Mixin/UserInterface/Windows/Cells/MediaPreviewCell.xib +++ b/Mixin/UserInterface/Windows/Cells/MediaPreviewCell.xib @@ -1,9 +1,9 @@ - + - + @@ -23,11 +23,6 @@ - - - - - diff --git a/Mixin/UserInterface/Windows/MediasPreviewWindow.swift b/Mixin/UserInterface/Windows/MediasPreviewWindow.swift index 91077c1c66..b73977f9c3 100644 --- a/Mixin/UserInterface/Windows/MediasPreviewWindow.swift +++ b/Mixin/UserInterface/Windows/MediasPreviewWindow.swift @@ -2,9 +2,9 @@ import UIKit import Photos protocol MediasPreviewWindowDelegate: AnyObject { - func mediasPreviewWindow(_ window: MediasPreviewWindow, didSendItems assets: [PHAsset]) - func mediasPreviewWindow(_ window: MediasPreviewWindow, didSendFiles assets: [PHAsset]) - func mediasPreviewWindow(_ window: MediasPreviewWindow, willDismiss assets: [PHAsset]) + func mediasPreviewWindow(_ window: MediasPreviewWindow, didTapSendItems assets: [PHAsset]) + func mediasPreviewWindow(_ window: MediasPreviewWindow, didTapSendFiles assets: [PHAsset]) + func mediasPreviewWindow(_ window: MediasPreviewWindow, willDismissWindow assets: [PHAsset]) } final class MediasPreviewWindow: BottomSheetView { @@ -48,7 +48,7 @@ final class MediasPreviewWindow: BottomSheetView { override func dismissPopupControllerAnimated() { if !isSending { - delegate?.mediasPreviewWindow(self, willDismiss: selectedAssets) + delegate?.mediasPreviewWindow(self, willDismissWindow: selectedAssets) } super.dismissPopupControllerAnimated() } @@ -60,14 +60,14 @@ final class MediasPreviewWindow: BottomSheetView { @IBAction func sendPhotosAction(_ sender: Any) { isSending = true + delegate?.mediasPreviewWindow(self, didTapSendItems: selectedAssets) dismissPopupControllerAnimated() - delegate?.mediasPreviewWindow(self, didSendItems: selectedAssets) } @IBAction func sendAsFilesAction(_ sender: Any) { isSending = true + delegate?.mediasPreviewWindow(self, didTapSendFiles: selectedAssets) dismissPopupControllerAnimated() - delegate?.mediasPreviewWindow(self, didSendFiles: selectedAssets) } func load(assets: [PHAsset], initIndex: Int) { @@ -81,7 +81,7 @@ final class MediasPreviewWindow: BottomSheetView { } class func instance() -> MediasPreviewWindow { - R.nib.mediaPreviewWindow(owner: nil)! + R.nib.mediasPreviewWindow(owner: nil)! } } diff --git a/Mixin/UserInterface/Windows/MediaPreviewWindow.xib b/Mixin/UserInterface/Windows/MediasPreviewWindow.xib similarity index 98% rename from Mixin/UserInterface/Windows/MediaPreviewWindow.xib rename to Mixin/UserInterface/Windows/MediasPreviewWindow.xib index 1084ea7f35..0f887296bc 100644 --- a/Mixin/UserInterface/Windows/MediaPreviewWindow.xib +++ b/Mixin/UserInterface/Windows/MediasPreviewWindow.xib @@ -78,7 +78,7 @@ - +