From f52accd3c5efb145f35643313c0b52bc17c2af43 Mon Sep 17 00:00:00 2001 From: Nora Trapp Date: Tue, 9 Aug 2022 17:32:08 -0700 Subject: [PATCH] Split group reply sheet into two components --- Signal.xcodeproj/project.pbxproj | 10 ++- .../StoryGroupReplyCell.swift | 0 .../StoryGroupReplyLoader.swift | 0 .../StoryGroupReplySheet.swift | 87 +++++++++++++++++++ .../StoryGroupReplyViewController.swift} | 84 +++--------------- .../StoryGroupReplyViewItem.swift | 0 .../StoryDirectReplySheet.swift | 0 .../StoryReplyInputToolbar.swift | 10 +++ .../StoryReplyPreviewView.swift | 0 .../StoryReplySheet.swift | 4 - 10 files changed, 118 insertions(+), 77 deletions(-) rename Signal/src/ViewControllers/HomeView/Stories/{Reply Sheets => Replies & Views Sheets}/Group Reply Sheet/StoryGroupReplyCell.swift (100%) rename Signal/src/ViewControllers/HomeView/Stories/{Reply Sheets => Replies & Views Sheets}/Group Reply Sheet/StoryGroupReplyLoader.swift (100%) create mode 100644 Signal/src/ViewControllers/HomeView/Stories/Replies & Views Sheets/Group Reply Sheet/StoryGroupReplySheet.swift rename Signal/src/ViewControllers/HomeView/Stories/{Reply Sheets/Group Reply Sheet/StoryGroupReplySheet.swift => Replies & Views Sheets/Group Reply Sheet/StoryGroupReplyViewController.swift} (79%) rename Signal/src/ViewControllers/HomeView/Stories/{Reply Sheets => Replies & Views Sheets}/Group Reply Sheet/StoryGroupReplyViewItem.swift (100%) rename Signal/src/ViewControllers/HomeView/Stories/{Reply Sheets => Replies & Views Sheets}/StoryDirectReplySheet.swift (100%) rename Signal/src/ViewControllers/HomeView/Stories/{Reply Sheets => Replies & Views Sheets}/StoryReplyInputToolbar.swift (97%) rename Signal/src/ViewControllers/HomeView/Stories/{Reply Sheets => Replies & Views Sheets}/StoryReplyPreviewView.swift (100%) rename Signal/src/ViewControllers/HomeView/Stories/{Reply Sheets => Replies & Views Sheets}/StoryReplySheet.swift (97%) diff --git a/Signal.xcodeproj/project.pbxproj b/Signal.xcodeproj/project.pbxproj index 66d1b2d71f..0fa4ee0ffa 100644 --- a/Signal.xcodeproj/project.pbxproj +++ b/Signal.xcodeproj/project.pbxproj @@ -953,6 +953,7 @@ 88ABB8B925349F6C00229EAA /* GroupCallVideoGridLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88ABB8B825349F6C00229EAA /* GroupCallVideoGridLayout.swift */; }; 88ABB8BB2535066100229EAA /* GroupCallVideoOverflow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88ABB8BA2535066000229EAA /* GroupCallVideoOverflow.swift */; }; 88ABB8BD25352B8300229EAA /* GroupCallMemberSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88ABB8BC25352B8200229EAA /* GroupCallMemberSheet.swift */; }; + 88B00D4B28A32DB600BC9CA0 /* StoryGroupReplyViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88B00D4A28A32DB600BC9CA0 /* StoryGroupReplyViewController.swift */; }; 88B2234A283F290400A25048 /* StoryPrivacySettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88B22349283F290400A25048 /* StoryPrivacySettingsViewController.swift */; }; 88B2234C284FABE600A25048 /* StoryThumbnailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88B2234B284FABE600A25048 /* StoryThumbnailView.swift */; }; 88B688B0238F0D1000286F82 /* ReactionsDetailSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88B688AF238F0D1000286F82 /* ReactionsDetailSheet.swift */; }; @@ -3275,6 +3276,7 @@ 88ABB8B825349F6C00229EAA /* GroupCallVideoGridLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupCallVideoGridLayout.swift; sourceTree = ""; }; 88ABB8BA2535066000229EAA /* GroupCallVideoOverflow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupCallVideoOverflow.swift; sourceTree = ""; }; 88ABB8BC25352B8200229EAA /* GroupCallMemberSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupCallMemberSheet.swift; sourceTree = ""; }; + 88B00D4A28A32DB600BC9CA0 /* StoryGroupReplyViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoryGroupReplyViewController.swift; sourceTree = ""; }; 88B22349283F290400A25048 /* StoryPrivacySettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoryPrivacySettingsViewController.swift; sourceTree = ""; }; 88B2234B284FABE600A25048 /* StoryThumbnailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoryThumbnailView.swift; sourceTree = ""; }; 88B688AF238F0D1000286F82 /* ReactionsDetailSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReactionsDetailSheet.swift; sourceTree = ""; }; @@ -5979,7 +5981,7 @@ path = Avatars; sourceTree = ""; }; - 88423A50280A1703007D2918 /* Reply Sheets */ = { + 88423A50280A1703007D2918 /* Replies & Views Sheets */ = { isa = PBXGroup; children = ( 8864072F27F21AA7009916B6 /* Group Reply Sheet */, @@ -5988,7 +5990,7 @@ 8864073027F21AD7009916B6 /* StoryReplyInputToolbar.swift */, 88423A53280A2675007D2918 /* StoryReplyPreviewView.swift */, ); - path = "Reply Sheets"; + path = "Replies & Views Sheets"; sourceTree = ""; }; 884DB94A27DE66E000C6A309 /* Context View */ = { @@ -6014,7 +6016,7 @@ 886292112835606D00AA0C3B /* MyStoryCell.swift */, 88B2234B284FABE600A25048 /* StoryThumbnailView.swift */, 884DB94A27DE66E000C6A309 /* Context View */, - 88423A50280A1703007D2918 /* Reply Sheets */, + 88423A50280A1703007D2918 /* Replies & Views Sheets */, 88863A4C280CADDC00977F69 /* Transitions */, ); path = Stories; @@ -6096,6 +6098,7 @@ isa = PBXGroup; children = ( 8864072727EEA658009916B6 /* StoryGroupReplySheet.swift */, + 88B00D4A28A32DB600BC9CA0 /* StoryGroupReplyViewController.swift */, 8864072927F0D426009916B6 /* StoryGroupReplyLoader.swift */, 8864072B27F0DA37009916B6 /* StoryGroupReplyViewItem.swift */, 8864072D27F0E8DF009916B6 /* StoryGroupReplyCell.swift */, @@ -10083,6 +10086,7 @@ 88423A52280A171E007D2918 /* StoryDirectReplySheet.swift in Sources */, 34ACA7E42733159600E47AD4 /* OnboardingPermissionsViewController.swift in Sources */, 8871B16F25F007DE00D4E070 /* ProfileSettingsViewController.swift in Sources */, + 88B00D4B28A32DB600BC9CA0 /* StoryGroupReplyViewController.swift in Sources */, 4CC1ECFB211A553000CC13BE /* AppUpdateNag.swift in Sources */, 4C30E226234FB033009558B7 /* SecondaryLinkingQRCodeViewController.swift in Sources */, 88ABB8BB2535066100229EAA /* GroupCallVideoOverflow.swift in Sources */, diff --git a/Signal/src/ViewControllers/HomeView/Stories/Reply Sheets/Group Reply Sheet/StoryGroupReplyCell.swift b/Signal/src/ViewControllers/HomeView/Stories/Replies & Views Sheets/Group Reply Sheet/StoryGroupReplyCell.swift similarity index 100% rename from Signal/src/ViewControllers/HomeView/Stories/Reply Sheets/Group Reply Sheet/StoryGroupReplyCell.swift rename to Signal/src/ViewControllers/HomeView/Stories/Replies & Views Sheets/Group Reply Sheet/StoryGroupReplyCell.swift diff --git a/Signal/src/ViewControllers/HomeView/Stories/Reply Sheets/Group Reply Sheet/StoryGroupReplyLoader.swift b/Signal/src/ViewControllers/HomeView/Stories/Replies & Views Sheets/Group Reply Sheet/StoryGroupReplyLoader.swift similarity index 100% rename from Signal/src/ViewControllers/HomeView/Stories/Reply Sheets/Group Reply Sheet/StoryGroupReplyLoader.swift rename to Signal/src/ViewControllers/HomeView/Stories/Replies & Views Sheets/Group Reply Sheet/StoryGroupReplyLoader.swift diff --git a/Signal/src/ViewControllers/HomeView/Stories/Replies & Views Sheets/Group Reply Sheet/StoryGroupReplySheet.swift b/Signal/src/ViewControllers/HomeView/Stories/Replies & Views Sheets/Group Reply Sheet/StoryGroupReplySheet.swift new file mode 100644 index 0000000000..05a6193f49 --- /dev/null +++ b/Signal/src/ViewControllers/HomeView/Stories/Replies & Views Sheets/Group Reply Sheet/StoryGroupReplySheet.swift @@ -0,0 +1,87 @@ +// +// Copyright (c) 2022 Open Whisper Systems. All rights reserved. +// + +import Foundation +import UIKit +import SignalServiceKit + +class StoryGroupReplySheet: InteractiveSheetViewController { + override var interactiveScrollViews: [UIScrollView] { [groupReplyViewController.tableView] } + override var minHeight: CGFloat { maximizedHeight } + override var sheetBackgroundColor: UIColor { .ows_gray90 } + + weak var interactiveTransitionCoordinator: StoryInteractiveTransitionCoordinator? + private let groupReplyViewController: StoryGroupReplyViewController + + var dismissHandler: (() -> Void)? + + init(storyMessage: StoryMessage) { + self.groupReplyViewController = StoryGroupReplyViewController(storyMessage: storyMessage) + + super.init() + } + + public required init() { + fatalError("init() has not been implemented") + } + + override func viewDidLoad() { + super.viewDidLoad() + + addChild(groupReplyViewController) + contentView.addSubview(groupReplyViewController.view) + groupReplyViewController.view.autoPinEdgesToSuperviewEdges() + } + + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + groupReplyViewController.inputToolbar.becomeFirstResponder() + } + + override func dismiss(animated flag: Bool, completion: (() -> Void)? = nil) { + super.dismiss(animated: flag) { [dismissHandler] in + completion?() + dismissHandler?() + } + } +} + +extension StoryGroupReplySheet { + override func presentationController( + forPresented presented: UIViewController, + presenting: UIViewController?, + source: UIViewController + ) -> UIPresentationController? { + return nil + } + + public func animationController( + forPresented presented: UIViewController, + presenting: UIViewController, + source: UIViewController + ) -> UIViewControllerAnimatedTransitioning? { + return StoryReplySheetAnimator( + isPresenting: true, + isInteractive: interactiveTransitionCoordinator != nil, + backdropView: backdropView + ) + } + + public func animationController( + forDismissed dismissed: UIViewController + ) -> UIViewControllerAnimatedTransitioning? { + return StoryReplySheetAnimator( + isPresenting: false, + isInteractive: false, + backdropView: backdropView + ) + } + + public func interactionControllerForPresentation( + using animator: UIViewControllerAnimatedTransitioning + ) -> UIViewControllerInteractiveTransitioning? { + interactiveTransitionCoordinator?.mode = .reply + return interactiveTransitionCoordinator + } +} diff --git a/Signal/src/ViewControllers/HomeView/Stories/Reply Sheets/Group Reply Sheet/StoryGroupReplySheet.swift b/Signal/src/ViewControllers/HomeView/Stories/Replies & Views Sheets/Group Reply Sheet/StoryGroupReplyViewController.swift similarity index 79% rename from Signal/src/ViewControllers/HomeView/Stories/Reply Sheets/Group Reply Sheet/StoryGroupReplySheet.swift rename to Signal/src/ViewControllers/HomeView/Stories/Replies & Views Sheets/Group Reply Sheet/StoryGroupReplyViewController.swift index 30a8539375..fe55511653 100644 --- a/Signal/src/ViewControllers/HomeView/Stories/Reply Sheets/Group Reply Sheet/StoryGroupReplySheet.swift +++ b/Signal/src/ViewControllers/HomeView/Stories/Replies & Views Sheets/Group Reply Sheet/StoryGroupReplyViewController.swift @@ -6,13 +6,9 @@ import Foundation import UIKit import SignalServiceKit -class StoryGroupReplySheet: InteractiveSheetViewController, StoryReplySheet { - override var interactiveScrollViews: [UIScrollView] { [tableView] } - override var minHeight: CGFloat { CurrentAppContext().frame.height * 0.6 } - override var sheetBackgroundColor: UIColor { .ows_gray90 } - - private lazy var tableView = UITableView() - lazy var inputToolbar = StoryReplyInputToolbar() +class StoryGroupReplyViewController: OWSViewController, StoryReplySheet { + private(set) lazy var tableView = UITableView() + private(set) lazy var inputToolbar = StoryReplyInputToolbar() private lazy var inputToolbarBottomConstraint = inputToolbar.autoPinEdge(toSuperviewEdge: .bottom) private lazy var contextMenu = ContextMenuInteraction(delegate: self) @@ -36,13 +32,10 @@ class StoryGroupReplySheet: InteractiveSheetViewController, StoryReplySheet { let storyMessage: StoryMessage lazy var thread: TSThread? = databaseStorage.read { storyMessage.context.thread(transaction: $0) } - weak var interactiveTransitionCoordinator: StoryInteractiveTransitionCoordinator? var reactionPickerBackdrop: UIView? var reactionPicker: MessageReactionPicker? - var dismissHandler: (() -> Void)? - init(storyMessage: StoryMessage) { self.storyMessage = storyMessage @@ -54,10 +47,6 @@ class StoryGroupReplySheet: InteractiveSheetViewController, StoryReplySheet { } } - public required init() { - fatalError("init() has not been implemented") - } - fileprivate var replyLoader: StoryGroupReplyLoader? override func viewDidLoad() { super.viewDidLoad() @@ -70,11 +59,11 @@ class StoryGroupReplySheet: InteractiveSheetViewController, StoryReplySheet { tableView.backgroundColor = .ows_gray90 tableView.addInteraction(contextMenu) - contentView.addSubview(tableView) + view.addSubview(tableView) tableView.autoPinEdgesToSuperviewEdges() inputToolbar.delegate = self - contentView.addSubview(inputToolbar) + view.addSubview(inputToolbar) inputToolbar.autoPinWidthToSuperview() inputToolbarBottomConstraint.isActive = true @@ -84,7 +73,7 @@ class StoryGroupReplySheet: InteractiveSheetViewController, StoryReplySheet { replyLoader = StoryGroupReplyLoader(storyMessage: storyMessage, threadUniqueId: thread?.uniqueId, tableView: tableView) - contentView.addSubview(emptyStateView) + view.addSubview(emptyStateView) emptyStateView.autoPinWidthToSuperview() emptyStateView.autoPinEdge(toSuperviewEdge: .top) emptyStateView.autoPinEdge(.bottom, to: .top, of: inputToolbar) @@ -92,20 +81,13 @@ class StoryGroupReplySheet: InteractiveSheetViewController, StoryReplySheet { public override var inputAccessoryView: UIView? { inputAccessoryPlaceholder } - override func dismiss(animated flag: Bool, completion: (() -> Void)? = nil) { - super.dismiss(animated: flag) { [dismissHandler] in - completion?() - dismissHandler?() - } - } - func didSendMessage() { replyLoader?.reload() inputToolbar.messageBody = nil } } -extension StoryGroupReplySheet: UIScrollViewDelegate { +extension StoryGroupReplyViewController: UIScrollViewDelegate { func scrollViewDidScroll(_ scrollView: UIScrollView) { guard let visibleRows = tableView.indexPathsForVisibleRows?.map({ $0.row }), !visibleRows.isEmpty, @@ -125,11 +107,11 @@ extension StoryGroupReplySheet: UIScrollViewDelegate { } } -extension StoryGroupReplySheet: UITableViewDelegate { +extension StoryGroupReplyViewController: UITableViewDelegate { } -extension StoryGroupReplySheet: UITableViewDataSource { +extension StoryGroupReplyViewController: UITableViewDataSource { func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { guard let item = replyLoader?.replyItem(for: indexPath) else { owsFailDebug("Missing item for cell at indexPath \(indexPath)") @@ -153,7 +135,7 @@ extension StoryGroupReplySheet: UITableViewDataSource { } } -extension StoryGroupReplySheet: InputAccessoryViewPlaceholderDelegate { +extension StoryGroupReplyViewController: InputAccessoryViewPlaceholderDelegate { public func inputAccessoryPlaceholderKeyboardIsPresenting(animationDuration: TimeInterval, animationCurve: UIView.AnimationCurve) { handleKeyboardStateChange(animationDuration: animationDuration, animationCurve: animationCurve) } @@ -209,9 +191,10 @@ extension StoryGroupReplySheet: InputAccessoryViewPlaceholderDelegate { } } -extension StoryGroupReplySheet: StoryReplyInputToolbarDelegate { +extension StoryGroupReplyViewController: StoryReplyInputToolbarDelegate { func storyReplyInputToolbarDidBeginEditing(_ storyReplyInputToolbar: StoryReplyInputToolbar) { - maximizeHeight() +// maximizeHeight() + // TODO: } func storyReplyInputToolbarHeightDidChange(_ storyReplyInputToolbar: StoryReplyInputToolbar) { @@ -219,7 +202,7 @@ extension StoryGroupReplySheet: StoryReplyInputToolbarDelegate { } } -extension StoryGroupReplySheet: ContextMenuInteractionDelegate { +extension StoryGroupReplyViewController: ContextMenuInteractionDelegate { func contextMenuInteraction(_ interaction: ContextMenuInteraction, configurationForMenuAtLocation location: CGPoint) -> ContextMenuConfiguration? { guard let indexPath = tableView.indexPathForRow(at: location), let item = replyLoader?.replyItem(for: indexPath) else { return nil } @@ -279,42 +262,3 @@ extension StoryGroupReplySheet: ContextMenuInteractionDelegate { func contextMenuInteraction(_ interaction: ContextMenuInteraction, didEndForConfiguration configuration: ContextMenuConfiguration) {} } - -extension StoryGroupReplySheet { - override func presentationController( - forPresented presented: UIViewController, - presenting: UIViewController?, - source: UIViewController - ) -> UIPresentationController? { - return nil - } - - public func animationController( - forPresented presented: UIViewController, - presenting: UIViewController, - source: UIViewController - ) -> UIViewControllerAnimatedTransitioning? { - return StoryReplySheetAnimator( - isPresenting: true, - isInteractive: interactiveTransitionCoordinator != nil, - backdropView: backdropView - ) - } - - public func animationController( - forDismissed dismissed: UIViewController - ) -> UIViewControllerAnimatedTransitioning? { - return StoryReplySheetAnimator( - isPresenting: false, - isInteractive: false, - backdropView: backdropView - ) - } - - public func interactionControllerForPresentation( - using animator: UIViewControllerAnimatedTransitioning - ) -> UIViewControllerInteractiveTransitioning? { - interactiveTransitionCoordinator?.mode = .reply - return interactiveTransitionCoordinator - } -} diff --git a/Signal/src/ViewControllers/HomeView/Stories/Reply Sheets/Group Reply Sheet/StoryGroupReplyViewItem.swift b/Signal/src/ViewControllers/HomeView/Stories/Replies & Views Sheets/Group Reply Sheet/StoryGroupReplyViewItem.swift similarity index 100% rename from Signal/src/ViewControllers/HomeView/Stories/Reply Sheets/Group Reply Sheet/StoryGroupReplyViewItem.swift rename to Signal/src/ViewControllers/HomeView/Stories/Replies & Views Sheets/Group Reply Sheet/StoryGroupReplyViewItem.swift diff --git a/Signal/src/ViewControllers/HomeView/Stories/Reply Sheets/StoryDirectReplySheet.swift b/Signal/src/ViewControllers/HomeView/Stories/Replies & Views Sheets/StoryDirectReplySheet.swift similarity index 100% rename from Signal/src/ViewControllers/HomeView/Stories/Reply Sheets/StoryDirectReplySheet.swift rename to Signal/src/ViewControllers/HomeView/Stories/Replies & Views Sheets/StoryDirectReplySheet.swift diff --git a/Signal/src/ViewControllers/HomeView/Stories/Reply Sheets/StoryReplyInputToolbar.swift b/Signal/src/ViewControllers/HomeView/Stories/Replies & Views Sheets/StoryReplyInputToolbar.swift similarity index 97% rename from Signal/src/ViewControllers/HomeView/Stories/Reply Sheets/StoryReplyInputToolbar.swift rename to Signal/src/ViewControllers/HomeView/Stories/Replies & Views Sheets/StoryReplyInputToolbar.swift index 77b3e54f72..b23bc2f16f 100644 --- a/Signal/src/ViewControllers/HomeView/Stories/Reply Sheets/StoryReplyInputToolbar.swift +++ b/Signal/src/ViewControllers/HomeView/Stories/Replies & Views Sheets/StoryReplyInputToolbar.swift @@ -152,6 +152,16 @@ class StoryReplyInputToolbar: UIView { return textView }() + @discardableResult + override func becomeFirstResponder() -> Bool { + textView.becomeFirstResponder() + } + + @discardableResult + override func resignFirstResponder() -> Bool { + textView.resignFirstResponder() + } + private let placeholderText = OWSLocalizedString( "STORY_REPLY_TEXT_FIELD_PLACEHOLDER", comment: "placeholder text for replying to a story" diff --git a/Signal/src/ViewControllers/HomeView/Stories/Reply Sheets/StoryReplyPreviewView.swift b/Signal/src/ViewControllers/HomeView/Stories/Replies & Views Sheets/StoryReplyPreviewView.swift similarity index 100% rename from Signal/src/ViewControllers/HomeView/Stories/Reply Sheets/StoryReplyPreviewView.swift rename to Signal/src/ViewControllers/HomeView/Stories/Replies & Views Sheets/StoryReplyPreviewView.swift diff --git a/Signal/src/ViewControllers/HomeView/Stories/Reply Sheets/StoryReplySheet.swift b/Signal/src/ViewControllers/HomeView/Stories/Replies & Views Sheets/StoryReplySheet.swift similarity index 97% rename from Signal/src/ViewControllers/HomeView/Stories/Reply Sheets/StoryReplySheet.swift rename to Signal/src/ViewControllers/HomeView/Stories/Replies & Views Sheets/StoryReplySheet.swift index 97a8254b80..c2ed89a37f 100644 --- a/Signal/src/ViewControllers/HomeView/Stories/Reply Sheets/StoryReplySheet.swift +++ b/Signal/src/ViewControllers/HomeView/Stories/Replies & Views Sheets/StoryReplySheet.swift @@ -11,10 +11,6 @@ protocol StoryReplySheet: OWSViewController, StoryReplyInputToolbarDelegate, Mes var inputToolbar: StoryReplyInputToolbar { get } var storyMessage: StoryMessage { get } var thread: TSThread? { get } - var interactiveTransitionCoordinator: StoryInteractiveTransitionCoordinator? { get set } - var backdropView: UIView? { get } - - var dismissHandler: (() -> Void)? { get set } var reactionPickerBackdrop: UIView? { get set } var reactionPicker: MessageReactionPicker? { get set }