Split group reply sheet into two components
This commit is contained in:
parent
43943ca621
commit
f52accd3c5
@ -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 = "<group>"; };
|
||||
88ABB8BA2535066000229EAA /* GroupCallVideoOverflow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupCallVideoOverflow.swift; sourceTree = "<group>"; };
|
||||
88ABB8BC25352B8200229EAA /* GroupCallMemberSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupCallMemberSheet.swift; sourceTree = "<group>"; };
|
||||
88B00D4A28A32DB600BC9CA0 /* StoryGroupReplyViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoryGroupReplyViewController.swift; sourceTree = "<group>"; };
|
||||
88B22349283F290400A25048 /* StoryPrivacySettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoryPrivacySettingsViewController.swift; sourceTree = "<group>"; };
|
||||
88B2234B284FABE600A25048 /* StoryThumbnailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoryThumbnailView.swift; sourceTree = "<group>"; };
|
||||
88B688AF238F0D1000286F82 /* ReactionsDetailSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReactionsDetailSheet.swift; sourceTree = "<group>"; };
|
||||
@ -5979,7 +5981,7 @@
|
||||
path = Avatars;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
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 = "<group>";
|
||||
};
|
||||
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 */,
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
@ -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"
|
||||
@ -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 }
|
||||
Loading…
Reference in New Issue
Block a user