diff --git a/Session/Conversations/Context Menu/ContextMenuVC+Action.swift b/Session/Conversations/Context Menu/ContextMenuVC+Action.swift index 747306fd3..cecf409e3 100644 --- a/Session/Conversations/Context Menu/ContextMenuVC+Action.swift +++ b/Session/Conversations/Context Menu/ContextMenuVC+Action.swift @@ -2,45 +2,72 @@ extension ContextMenuVC { struct Action { - let icon: UIImage + let icon: UIImage? let title: String + let tag: String let work: () -> Void static func reply(_ viewItem: ConversationViewItem, _ delegate: ContextMenuActionDelegate?) -> Action { let title = "Reply" - return Action(icon: UIImage(named: "ic_reply")!, title: title) { delegate?.reply(viewItem) } + let tag = "reply" + return Action(icon: UIImage(named: "ic_reply")!, title: title, tag: tag) { delegate?.reply(viewItem) } } static func copy(_ viewItem: ConversationViewItem, _ delegate: ContextMenuActionDelegate?) -> Action { let title = "Copy" - return Action(icon: UIImage(named: "ic_copy")!, title: title) { delegate?.copy(viewItem) } + let tag = "copy" + return Action(icon: UIImage(named: "ic_copy")!, title: title, tag: tag) { delegate?.copy(viewItem) } } static func copySessionID(_ viewItem: ConversationViewItem, _ delegate: ContextMenuActionDelegate?) -> Action { let title = "Copy Session ID" - return Action(icon: UIImage(named: "ic_copy")!, title: title) { delegate?.copySessionID(viewItem) } + let tag = "copySessionID" + return Action(icon: UIImage(named: "ic_copy")!, title: title, tag: tag) { delegate?.copySessionID(viewItem) } } static func delete(_ viewItem: ConversationViewItem, _ delegate: ContextMenuActionDelegate?) -> Action { let title = "Delete" - return Action(icon: UIImage(named: "ic_trash")!, title: title) { delegate?.delete(viewItem) } + let tag = "delete" + return Action(icon: UIImage(named: "ic_trash")!, title: title, tag: tag) { delegate?.delete(viewItem) } + } + + static func deleteLocally(_ viewItem: ConversationViewItem, _ delegate: ContextMenuActionDelegate?) -> Action { + let title = "Delete for me" + let tag = "deleteforme" + return Action(icon: nil, title: title, tag: tag) { delegate?.deleteLocally(viewItem) } + } + + static func deleteForEveryone(_ viewItem: ConversationViewItem, _ delegate: ContextMenuActionDelegate?) -> Action { + let tag = "deleteforeveryone" + var title = "Delete for everyone" + if !viewItem.isGroupThread { + title = "Delete for me and \(viewItem.interaction.thread.name())" + } + return Action(icon: nil, title: title, tag: tag) { delegate?.deleteForEveryone(viewItem) } } static func save(_ viewItem: ConversationViewItem, _ delegate: ContextMenuActionDelegate?) -> Action { let title = "Save" - return Action(icon: UIImage(named: "ic_download")!, title: title) { delegate?.save(viewItem) } + let tag = "save" + return Action(icon: UIImage(named: "ic_download")!, title: title, tag: tag) { delegate?.save(viewItem) } } static func ban(_ viewItem: ConversationViewItem, _ delegate: ContextMenuActionDelegate?) -> Action { let title = "Ban User" - return Action(icon: UIImage(named: "ic_block")!, title: title) { delegate?.ban(viewItem) } + let tag = "banUser" + return Action(icon: UIImage(named: "ic_block")!, title: title, tag: tag) { delegate?.ban(viewItem) } } static func banAndDeleteAllMessages(_ viewItem: ConversationViewItem, _ delegate: ContextMenuActionDelegate?) -> Action { let title = "Ban and Delete All" - return Action(icon: UIImage(named: "ic_block")!, title: title) { delegate?.banAndDeleteAllMessages(viewItem) } + let tag = "banAndDeleteAll" + return Action(icon: UIImage(named: "ic_block")!, title: title, tag: tag) { delegate?.banAndDeleteAllMessages(viewItem) } } } + + static func deleteActions(for viewItem: ConversationViewItem, delegate: ContextMenuActionDelegate?) -> [Action] { + return [Action.deleteForEveryone(viewItem, delegate), Action.deleteLocally(viewItem, delegate)] + } static func actions(for viewItem: ConversationViewItem, delegate: ContextMenuActionDelegate?) -> [Action] { func isReplyingAllowed() -> Bool { @@ -88,6 +115,8 @@ protocol ContextMenuActionDelegate : class { func copy(_ viewItem: ConversationViewItem) func copySessionID(_ viewItem: ConversationViewItem) func delete(_ viewItem: ConversationViewItem) + func deleteLocally(_ viewItem: ConversationViewItem) + func deleteForEveryone(_ viewItem: ConversationViewItem) func save(_ viewItem: ConversationViewItem) func ban(_ viewItem: ConversationViewItem) func banAndDeleteAllMessages(_ viewItem: ConversationViewItem) diff --git a/Session/Conversations/Context Menu/ContextMenuVC+ActionView.swift b/Session/Conversations/Context Menu/ContextMenuVC+ActionView.swift index 0f0e99ffc..1ff6b8ab6 100644 --- a/Session/Conversations/Context Menu/ContextMenuVC+ActionView.swift +++ b/Session/Conversations/Context Menu/ContextMenuVC+ActionView.swift @@ -26,20 +26,25 @@ extension ContextMenuVC { } private func setUpViewHierarchy() { + var subviews: [UIView] = [] // Icon - let iconSize = ActionView.iconSize - let iconImageView = UIImageView(image: action.icon.resizedImage(to: CGSize(width: iconSize, height: iconSize))!.withTint(Colors.text)) - let iconImageViewSize = ActionView.iconImageViewSize - iconImageView.set(.width, to: iconImageViewSize) - iconImageView.set(.height, to: iconImageViewSize) - iconImageView.contentMode = .center + if let icon = action.icon { + let iconSize = ActionView.iconSize + let iconImageView = UIImageView(image: icon.resizedImage(to: CGSize(width: iconSize, height: iconSize))!.withTint(Colors.text)) + let iconImageViewSize = ActionView.iconImageViewSize + iconImageView.set(.width, to: iconImageViewSize) + iconImageView.set(.height, to: iconImageViewSize) + iconImageView.contentMode = .center + subviews.append(iconImageView) + } // Title let titleLabel = UILabel() titleLabel.text = action.title titleLabel.textColor = Colors.text titleLabel.font = .systemFont(ofSize: Values.mediumFontSize) + subviews.append(titleLabel) // Stack view - let stackView = UIStackView(arrangedSubviews: [ iconImageView, titleLabel ]) + let stackView = UIStackView(arrangedSubviews: subviews) stackView.axis = .horizontal stackView.spacing = Values.smallSpacing stackView.alignment = .center @@ -56,6 +61,7 @@ extension ContextMenuVC { // MARK: Interaction @objc private func handleTap() { action.work() + guard action.tag != "delete" else { return } dismiss() } } diff --git a/Session/Conversations/Context Menu/ContextMenuVC.swift b/Session/Conversations/Context Menu/ContextMenuVC.swift index 66cf13925..fa8c6d9c3 100644 --- a/Session/Conversations/Context Menu/ContextMenuVC.swift +++ b/Session/Conversations/Context Menu/ContextMenuVC.swift @@ -75,14 +75,37 @@ final class ContextMenuVC : UIViewController { } else { timestampLabel.pin(.left, to: .right, of: snapshot, withInset: Values.smallSpacing) } + self.updateMenu() + // Tap gesture + let mainTapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleTap)) + view.addGestureRecognizer(mainTapGestureRecognizer) + } + + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + UIView.animate(withDuration: 0.25) { + self.blurView.effect = UIBlurEffect(style: .regular) + self.menuView.alpha = 1 + } + } + + // MARK: Updating + override func viewDidLayoutSubviews() { + super.viewDidLayoutSubviews() + menuView.layer.shadowPath = UIBezierPath(roundedRect: menuView.bounds, cornerRadius: ContextMenuVC.menuCornerRadius).cgPath + } + + func updateMenu(forDelete: Bool = false) { // Menu + menuView.subviews.forEach({ $0.removeFromSuperview() }) let menuBackgroundView = UIView() menuBackgroundView.backgroundColor = Colors.receivedMessageBackground menuBackgroundView.layer.cornerRadius = ContextMenuVC.menuCornerRadius menuBackgroundView.layer.masksToBounds = true menuView.addSubview(menuBackgroundView) menuBackgroundView.pin(to: menuView) - let actionViews = ContextMenuVC.actions(for: viewItem, delegate: delegate).map { ActionView(for: $0, dismiss: snDismiss) } + let actions = forDelete ? ContextMenuVC.deleteActions(for: viewItem, delegate: delegate) : ContextMenuVC.actions(for: viewItem, delegate: delegate) + let actionViews = actions.map { ActionView(for: $0, dismiss: snDismiss) } let menuStackView = UIStackView(arrangedSubviews: actionViews) menuStackView.axis = .vertical menuView.addSubview(menuStackView) @@ -101,23 +124,6 @@ final class ContextMenuVC : UIViewController { case .incomingMessage: menuView.pin(.left, to: .left, of: snapshot) default: break // Should never occur } - // Tap gesture - let mainTapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleTap)) - view.addGestureRecognizer(mainTapGestureRecognizer) - } - - override func viewDidAppear(_ animated: Bool) { - super.viewDidAppear(animated) - UIView.animate(withDuration: 0.25) { - self.blurView.effect = UIBlurEffect(style: .regular) - self.menuView.alpha = 1 - } - } - - // MARK: Updating - override func viewDidLayoutSubviews() { - super.viewDidLayoutSubviews() - menuView.layer.shadowPath = UIBezierPath(roundedRect: menuView.bounds, cornerRadius: ContextMenuVC.menuCornerRadius).cgPath } // MARK: Interaction diff --git a/Session/Conversations/ConversationVC+Interaction.swift b/Session/Conversations/ConversationVC+Interaction.swift index 89ae4dc4e..3694d1fdc 100644 --- a/Session/Conversations/ConversationVC+Interaction.swift +++ b/Session/Conversations/ConversationVC+Interaction.swift @@ -546,7 +546,15 @@ extension ConversationVC : InputViewDelegate, MessageCellDelegate, ContextMenuAc } func delete(_ viewItem: ConversationViewItem) { - viewItem.deleteAction() + self.contextMenuVC?.updateMenu(forDelete: true) + } + + func deleteLocally(_ viewItem: ConversationViewItem) { + // TODO: delete locally + } + + func deleteForEveryone(_ viewItem: ConversationViewItem) { + // TODO: delete for everyone } func save(_ viewItem: ConversationViewItem) {