Present "New Story" creation options via a popup menu.

Instead of a customized action sheet.
This commit is contained in:
Igor Solomennikov 2026-05-26 16:45:15 -07:00 committed by GitHub
parent 732d375c82
commit ec69b9425f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 54 additions and 153 deletions

View File

@ -1626,7 +1626,6 @@
8864072C27F0DA38009916B6 /* StoryGroupReplyViewItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8864072B27F0DA37009916B6 /* StoryGroupReplyViewItem.swift */; };
8864072E27F0E8DF009916B6 /* StoryGroupReplyCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8864072D27F0E8DF009916B6 /* StoryGroupReplyCell.swift */; };
8864073127F21AD7009916B6 /* StoryReplyInputToolbar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8864073027F21AD7009916B6 /* StoryReplyInputToolbar.swift */; };
8868A089287F4514000E74A5 /* NewStorySheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8868A088287F4514000E74A5 /* NewStorySheet.swift */; };
8868A08A287F4551000E74A5 /* InteractiveSheetViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 880C2E01262A19DE006650B6 /* InteractiveSheetViewController.swift */; };
8868A08C287F4F81000E74A5 /* OWSTableSheetViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8868A08B287F4F81000E74A5 /* OWSTableSheetViewController.swift */; };
886BB3D225BA0C9D00079781 /* PreviewWallpaperViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88ABAB8E25B8BE3F0008C78A /* PreviewWallpaperViewController.swift */; };
@ -5838,7 +5837,6 @@
8864072B27F0DA37009916B6 /* StoryGroupReplyViewItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoryGroupReplyViewItem.swift; sourceTree = "<group>"; };
8864072D27F0E8DF009916B6 /* StoryGroupReplyCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoryGroupReplyCell.swift; sourceTree = "<group>"; };
8864073027F21AD7009916B6 /* StoryReplyInputToolbar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoryReplyInputToolbar.swift; sourceTree = "<group>"; };
8868A088287F4514000E74A5 /* NewStorySheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewStorySheet.swift; sourceTree = "<group>"; };
8868A08B287F4F81000E74A5 /* OWSTableSheetViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OWSTableSheetViewController.swift; sourceTree = "<group>"; };
886A58C8276A760600A1099B /* DonationSubscriptionManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DonationSubscriptionManager.swift; sourceTree = "<group>"; };
886A58C9276A760600A1099B /* DonationReceiptCredentialRedemptionJobQueue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DonationReceiptCredentialRedemptionJobQueue.swift; sourceTree = "<group>"; };
@ -11796,7 +11794,6 @@
88F5D78B2880ABF900CE4D2D /* NewPrivateStoryConfirmViewController.swift */,
88F5D7892880A55E00CE4D2D /* NewPrivateStoryRecipientsViewController.swift */,
880FB3F228CC161800FA1C10 /* NewStoryHeaderView.swift */,
8868A088287F4514000E74A5 /* NewStorySheet.swift */,
66FBC4E228DA82AA00BD9E8B /* SelectMyStoryRecipientsViewController.swift */,
B99B155C2A71BA5200E26DAC /* StoryContextViewState.swift */,
88B6D67128076F37005D86EC /* StoryMessage+SignalUI.swift */,
@ -17855,7 +17852,6 @@
88F5D78C2880ABF900CE4D2D /* NewPrivateStoryConfirmViewController.swift in Sources */,
88F5D78A2880A55E00CE4D2D /* NewPrivateStoryRecipientsViewController.swift in Sources */,
880FB3F328CC161800FA1C10 /* NewStoryHeaderView.swift in Sources */,
8868A089287F4514000E74A5 /* NewStorySheet.swift in Sources */,
3402AAAC271D9E180084CBAE /* NonContactTableViewCell.swift in Sources */,
507C07402F116E9200ECFEFA /* NormalizedImage.swift in Sources */,
3402AAAB271D9E180084CBAE /* OWSActionSheets.swift in Sources */,

View File

@ -5878,9 +5878,6 @@
/* Title for create group story row on the 'new story sheet' */
"NEW_STORY_SHEET_GROUP_STORY_TITLE" = "New Group Story";
/* Title for the new story sheet */
"NEW_STORY_SHEET_TITLE" = "Choose Story Type";
/* Title for the table cell in conversation settings for presenting the profile nickname editor. */
"NICKNAME_BUTTON_TITLE" = "Nickname";

View File

@ -40,25 +40,51 @@ public class NewStoryHeaderView: UIStackView {
addArrangedSubview(textView)
addArrangedSubview(.hStretchingSpacer())
// TODO: Replace with ContextMenuButton
let newStoryButton = UIButton(
configuration: .bordered(),
primaryAction: UIAction { [weak self] _ in
self?.didTapNewStory()
},
)
newStoryButton.configuration?.image = UIImage(imageLiteralResourceName: "plus-extra-small")
newStoryButton.configuration?.imagePlacement = .leading
newStoryButton.configuration?.imagePadding = 6
newStoryButton.configuration?.title = OWSLocalizedString(
var configuration = UIButton.Configuration.bordered()
configuration.image = UIImage(imageLiteralResourceName: "plus-extra-small")
configuration.imagePlacement = .leading
configuration.imagePadding = 6
configuration.title = OWSLocalizedString(
"NEW_STORY_HEADER_VIEW_ADD_NEW_STORY_BUTTON",
comment: "table section header button to add a new story",
)
newStoryButton.configuration?.titleTextAttributesTransformer = .defaultFont(.dynamicTypeFootnoteClamped.semibold())
newStoryButton.configuration?.contentInsets = .init(hMargin: 12, vMargin: 6)
newStoryButton.configuration?.baseForegroundColor = .Signal.label
newStoryButton.configuration?.baseBackgroundColor = delegate.cellBackgroundColor
newStoryButton.configuration?.cornerStyle = .capsule
configuration.titleTextAttributesTransformer = .defaultFont(.dynamicTypeFootnoteClamped.semibold())
configuration.contentInsets = .init(hMargin: 12, vMargin: 6)
configuration.baseForegroundColor = .Signal.label
configuration.baseBackgroundColor = delegate.cellBackgroundColor
configuration.cornerStyle = .capsule
let newStoryButton = UIButton(configuration: configuration)
newStoryButton.showsMenuAsPrimaryAction = true
newStoryButton.menu = UIMenu(children: [
UIAction(
title: OWSLocalizedString(
"NEW_STORY_SHEET_CUSTOM_STORY_TITLE",
comment: "Title for create custom story row on the 'new story sheet'",
),
subtitle: OWSLocalizedString(
"NEW_STORY_SHEET_CUSTOM_STORY_SUBTITLE",
comment: "Subtitle for create custom story row on the 'new story sheet'",
),
image: Theme.iconImage(.genericStories),
handler: { [weak self] _ in
self?.didTapNewCustomStory()
},
),
UIAction(
title: OWSLocalizedString(
"NEW_STORY_SHEET_GROUP_STORY_TITLE",
comment: "Title for create group story row on the 'new story sheet'",
),
subtitle: OWSLocalizedString(
"NEW_STORY_SHEET_GROUP_STORY_SUBTITLE",
comment: "Subtitle for create group story row on the 'new story sheet'",
),
image: Theme.iconImage(.genericGroup),
handler: { [weak self] _ in
self?.didTapNewGroupStory()
},
),
])
addArrangedSubview(newStoryButton)
}
@ -66,11 +92,20 @@ public class NewStoryHeaderView: UIStackView {
fatalError("init(coder:) has not been implemented")
}
private func didTapNewStory() {
let vc = NewStorySheet { [weak self] items in
private func didTapNewCustomStory() {
let vc = NewPrivateStoryRecipientsViewController { [weak self] items in
guard let self else { return }
self.delegate.newStoryHeaderView(self, didCreateNewStoryItems: items)
}
delegate.present(vc, animated: true)
delegate.presentFormSheet(OWSNavigationController(rootViewController: vc), animated: true)
}
private func didTapNewGroupStory() {
let vc = NewGroupStoryViewController { [weak self] items in
guard let self else { return }
self.delegate.newStoryHeaderView(self, didCreateNewStoryItems: items)
}
delegate.presentFormSheet(OWSNavigationController(rootViewController: vc), animated: true)
}
}

View File

@ -1,127 +0,0 @@
//
// Copyright 2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
//
import Foundation
import SignalServiceKit
import UIKit
public class NewStorySheet: OWSTableSheetViewController {
let selectItemsInParent: (([StoryConversationItem]) -> Void)?
public init(selectItemsInParent: (([StoryConversationItem]) -> Void)?) {
self.selectItemsInParent = selectItemsInParent
super.init()
tableViewController.defaultSeparatorInsetLeading =
OWSTableViewController2.cellHInnerMargin + 48 + OWSTableItem.iconSpacing
}
override public func updateTableContents(shouldReload: Bool = true) {
let contents = OWSTableContents()
defer { tableViewController.setContents(contents, shouldReload: shouldReload) }
let headerSection = OWSTableSection()
headerSection.customHeaderHeight = 2
headerSection.hasBackground = false
contents.add(headerSection)
headerSection.add(.init(customCellBlock: {
let label = UILabel()
label.font = UIFont.dynamicTypeHeadlineClamped
label.textColor = Theme.primaryTextColor
label.text = OWSLocalizedString("NEW_STORY_SHEET_TITLE", comment: "Title for the new story sheet")
label.textAlignment = .center
let cell = OWSTableItem.newCell()
cell.contentView.addSubview(label)
label.autoPinEdgesToSuperviewEdges()
return cell
}))
let optionsSection = OWSTableSection()
optionsSection.customHeaderHeight = 28
contents.add(optionsSection)
optionsSection.add(buildOptionItem(
icon: .genericStories,
title: OWSLocalizedString(
"NEW_STORY_SHEET_CUSTOM_STORY_TITLE",
comment: "Title for create custom story row on the 'new story sheet'",
),
subtitle: OWSLocalizedString(
"NEW_STORY_SHEET_CUSTOM_STORY_SUBTITLE",
comment: "Subtitle for create custom story row on the 'new story sheet'",
),
action: { [weak self] in
guard let self else { return }
let presentingViewController = self.presentingViewController
self.dismiss(animated: true) {
let vc = NewPrivateStoryRecipientsViewController(selectItemsInParent: self.selectItemsInParent)
presentingViewController?.presentFormSheet(OWSNavigationController(rootViewController: vc), animated: true)
}
},
))
optionsSection.add(buildOptionItem(
icon: .genericGroup,
title: OWSLocalizedString(
"NEW_STORY_SHEET_GROUP_STORY_TITLE",
comment: "Title for create group story row on the 'new story sheet'",
),
subtitle: OWSLocalizedString(
"NEW_STORY_SHEET_GROUP_STORY_SUBTITLE",
comment: "Subtitle for create group story row on the 'new story sheet'",
),
action: { [weak self] in
guard let self else { return }
let presentingViewController = self.presentingViewController
self.dismiss(animated: true) {
let vc = NewGroupStoryViewController(selectItemsInParent: self.selectItemsInParent)
presentingViewController?.presentFormSheet(OWSNavigationController(rootViewController: vc), animated: true)
}
},
))
}
func buildOptionItem(icon: ThemeIcon, title: String, subtitle: String, action: @escaping () -> Void) -> OWSTableItem {
.init {
let cell = OWSTableItem.newCell()
cell.preservesSuperviewLayoutMargins = true
cell.contentView.preservesSuperviewLayoutMargins = true
let iconView = OWSTableItem.buildIconInCircleView(
icon: icon,
iconSize: AvatarBuilder.standardAvatarSizePoints,
innerIconSize: 24,
iconTintColor: Theme.primaryTextColor,
)
let rowTitleLabel = UILabel()
rowTitleLabel.text = title
rowTitleLabel.textColor = Theme.primaryTextColor
rowTitleLabel.font = .dynamicTypeBodyClamped
rowTitleLabel.numberOfLines = 0
let rowSubtitleLabel = UILabel()
rowSubtitleLabel.text = subtitle
rowSubtitleLabel.textColor = Theme.secondaryTextAndIconColor
rowSubtitleLabel.font = .dynamicTypeSubheadlineClamped
rowSubtitleLabel.numberOfLines = 0
let titleStack = UIStackView(arrangedSubviews: [rowTitleLabel, rowSubtitleLabel])
titleStack.axis = .vertical
titleStack.alignment = .leading
let contentRow = UIStackView(arrangedSubviews: [iconView, titleStack])
contentRow.spacing = ContactCellView.avatarTextHSpacing
contentRow.alignment = .center
cell.contentView.addSubview(contentRow)
contentRow.autoPinWidthToSuperviewMargins()
contentRow.autoPinHeightToSuperview(withMargin: 7)
return cell
} actionBlock: { action() }
}
}