Pin details polish
This commit is contained in:
parent
1db9e435cf
commit
6fb8b566b9
@ -144,11 +144,15 @@ public class CVComponentDateHeader: CVComponentBase, CVRootComponent {
|
||||
return contentView.rootView
|
||||
}
|
||||
|
||||
let isStandaloneRenderItem = conversationStyle.isStandaloneRenderItem
|
||||
|
||||
// On iOS 26 always use `visual effect` content view for the sticky header.
|
||||
if componentDelegate.isConversationPreview {
|
||||
return buildVisualEffectContentView()
|
||||
} else if hasWallpaper, #unavailable(iOS 26) {
|
||||
return buildPlainContentView()
|
||||
} else if isStandaloneRenderItem {
|
||||
return buildPlainContentView()
|
||||
} else {
|
||||
let plainContentView = buildPlainContentView()
|
||||
let visualEffectContentView = buildVisualEffectContentView()
|
||||
|
||||
@ -127,7 +127,7 @@ extension ConversationViewController {
|
||||
|
||||
private class ConversationBannerView: UIView {
|
||||
internal var contentView: UIView & UIContentView
|
||||
private var blurBackgroundView: UIVisualEffectView?
|
||||
var blurBackgroundView: UIVisualEffectView?
|
||||
|
||||
public static func fadeInAnimator() -> UIViewPropertyAnimator {
|
||||
return UIViewPropertyAnimator(
|
||||
@ -1111,8 +1111,9 @@ internal extension ConversationViewController {
|
||||
)
|
||||
|
||||
let banner = ConversationBannerView(configuration: bannerConfiguration)
|
||||
|
||||
let longPressInteraction = UIContextMenuInteraction(delegate: self)
|
||||
banner.addInteraction(longPressInteraction)
|
||||
banner.blurBackgroundView?.addInteraction(longPressInteraction)
|
||||
|
||||
// Set up interaction delegate for pin icon menu
|
||||
banner.pinnedMessageDelegate = self
|
||||
|
||||
@ -484,6 +484,30 @@ extension ConversationViewController: MessageActionsDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
public func handleActionUnpinAsync(message: TSMessage) async {
|
||||
let pinnedMessageManager = DependenciesBridge.shared.pinnedMessageManager
|
||||
let db = DependenciesBridge.shared.db
|
||||
|
||||
let unpinMessage = db.write { tx in
|
||||
pinnedMessageManager.getOutgoingUnpinMessage(
|
||||
interaction: message,
|
||||
thread: thread,
|
||||
expiresAt: nil,
|
||||
tx: tx
|
||||
)
|
||||
}
|
||||
guard let unpinMessage else {
|
||||
return
|
||||
}
|
||||
|
||||
await queuePinMessageChangeWithModal(
|
||||
message: message,
|
||||
pinMessage: unpinMessage,
|
||||
completion: nil
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
func messageActionsChangePinStatus(_ itemViewModel: CVItemViewModelImpl, pin: Bool) {
|
||||
guard let message = itemViewModel.renderItem.interaction as? TSMessage else {
|
||||
return
|
||||
|
||||
@ -18,6 +18,9 @@ protocol PinnedMessageInteractionManagerDelegate: AnyObject {
|
||||
|
||||
/// Presents the "see all messages" details view.
|
||||
func presentSeeAllMessages()
|
||||
|
||||
/// Unpins all messages
|
||||
func unpinAllMessages()
|
||||
}
|
||||
|
||||
public struct PinnedMessageBannerData {
|
||||
@ -355,4 +358,18 @@ extension ConversationViewController: PinnedMessageInteractionManagerDelegate {
|
||||
pmDetailsController.modalPresentationStyle = .pageSheet
|
||||
present(pmDetailsController, animated: true)
|
||||
}
|
||||
|
||||
func unpinAllMessages() {
|
||||
Task {
|
||||
for message in threadViewModel.pinnedMessages {
|
||||
await handleActionUnpinAsync(message: message)
|
||||
}
|
||||
presentToast(
|
||||
text: OWSLocalizedString(
|
||||
"PINNED_MESSAGE_TOAST",
|
||||
comment: "Text to show on a toast when someone unpins a message"
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -57,6 +57,7 @@ class PinnedMessagesDetailsViewController: OWSViewController, DatabaseChangeDele
|
||||
titleStackView.spacing = 4
|
||||
|
||||
navigationItem.titleView = titleStackView
|
||||
navigationItem.rightBarButtonItem = .doneButton(dismissingFrom: self)
|
||||
}
|
||||
|
||||
private func layoutPinnedMessages(tx: DBReadTransaction) {
|
||||
@ -112,7 +113,8 @@ class PinnedMessagesDetailsViewController: OWSViewController, DatabaseChangeDele
|
||||
|
||||
scrollView.autoPinEdgesToSuperviewEdges()
|
||||
paddedContainerView.autoPinEdgesToSuperviewEdges()
|
||||
stack.autoPinEdgesToSuperviewEdges(with: UIEdgeInsets(top: 16, left: 16, bottom: 16, right: 16))
|
||||
|
||||
stack.autoPinEdgesToSuperviewEdges(with: UIEdgeInsets(top: 16, left: 16, bottom: 64, right: 16))
|
||||
paddedContainerView.autoMatch(.width, to: .width, of: scrollView)
|
||||
|
||||
}
|
||||
@ -134,6 +136,23 @@ class PinnedMessagesDetailsViewController: OWSViewController, DatabaseChangeDele
|
||||
db.read { tx in
|
||||
layoutPinnedMessages(tx: tx)
|
||||
}
|
||||
|
||||
let unpinAllButton = UIButton(
|
||||
configuration: .largeSecondary(title: OWSLocalizedString(
|
||||
"PINNED_MESSAGES_UNPIN_ALL",
|
||||
comment: "Title for a button to unpin all pinned messages."
|
||||
)),
|
||||
primaryAction: UIAction { [weak self] _ in
|
||||
self?.dismiss(animated: true)
|
||||
self?.delegate?.unpinAllMessages()
|
||||
},
|
||||
)
|
||||
view.addSubview(unpinAllButton)
|
||||
unpinAllButton.translatesAutoresizingMaskIntoConstraints = false
|
||||
NSLayoutConstraint.activate([
|
||||
unpinAllButton.bottomAnchor.constraint(equalTo: contentLayoutGuide.bottomAnchor),
|
||||
unpinAllButton.centerXAnchor.constraint(equalTo: contentLayoutGuide.centerXAnchor),
|
||||
])
|
||||
}
|
||||
|
||||
private func buildButtonAndCellStack(renderItem: CVRenderItem, message: TSMessage, reversedIndex: Int) -> UIStackView {
|
||||
@ -192,7 +211,8 @@ class PinnedMessagesDetailsViewController: OWSViewController, DatabaseChangeDele
|
||||
chatColor: DependenciesBridge.shared.chatColorSettingStore.resolvedChatColor(
|
||||
for: threadViewModel.threadRecord,
|
||||
tx: tx
|
||||
)
|
||||
),
|
||||
isStandaloneRenderItem: true
|
||||
)
|
||||
|
||||
return CVLoader.buildStandaloneRenderItem(
|
||||
@ -521,7 +541,7 @@ extension PinnedMessagesDetailsViewController: CVComponentDelegate {
|
||||
return {}
|
||||
}
|
||||
|
||||
var isConversationPreview: Bool { true }
|
||||
var isConversationPreview: Bool { false }
|
||||
|
||||
var wallpaperBlurProvider: WallpaperBlurProvider? { nil }
|
||||
|
||||
|
||||
@ -6616,6 +6616,9 @@
|
||||
/* Action menu item to unpin a message */
|
||||
"PINNED_MESSAGES_UNPIN" = "Unpin";
|
||||
|
||||
/* Title for a button to unpin all pinned messages. */
|
||||
"PINNED_MESSAGES_UNPIN_ALL" = "Unpin All";
|
||||
|
||||
/* The title for pinned conversation section on the conversation list */
|
||||
"PINNED_SECTION_TITLE" = "Pinned";
|
||||
|
||||
|
||||
@ -38,6 +38,8 @@ public struct ConversationStyle {
|
||||
|
||||
public let isWallpaperPhoto: Bool
|
||||
|
||||
public let isStandaloneRenderItem: Bool
|
||||
|
||||
private let dynamicBodyTypePointSize: CGFloat
|
||||
private let primaryTextColor: UIColor
|
||||
|
||||
@ -109,7 +111,8 @@ public struct ConversationStyle {
|
||||
viewWidth: CGFloat,
|
||||
hasWallpaper: Bool,
|
||||
isWallpaperPhoto: Bool,
|
||||
chatColor: ColorOrGradientSetting
|
||||
chatColor: ColorOrGradientSetting,
|
||||
isStandaloneRenderItem: Bool = false
|
||||
) {
|
||||
self.type = type
|
||||
self.viewWidth = viewWidth
|
||||
@ -169,6 +172,8 @@ public struct ConversationStyle {
|
||||
|
||||
let kMaxAudioMessageWidth: CGFloat = 244
|
||||
maxAudioMessageWidth = floor(min(maxMessageWidth, kMaxAudioMessageWidth))
|
||||
|
||||
self.isStandaloneRenderItem = isStandaloneRenderItem
|
||||
}
|
||||
|
||||
// MARK: Colors
|
||||
|
||||
Loading…
Reference in New Issue
Block a user