Remove stories code that’s no longer necessary

This commit is contained in:
Max Radermacher
2025-12-02 12:07:07 -06:00
committed by GitHub
parent d6ac807f06
commit 019c9e61f6
8 changed files with 22 additions and 267 deletions

View File

@@ -892,7 +892,6 @@
663D02DD2C06717900350632 /* UInt64SafeRecord.swift in Sources */ = {isa = PBXBuildFile; fileRef = 663D02DC2C06717900350632 /* UInt64SafeRecord.swift */; };
663D02DF2C069AB600350632 /* OrphanedAttachmentCleanerTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 663D02DE2C069AB600350632 /* OrphanedAttachmentCleanerTest.swift */; };
663D02E12C06E2F400350632 /* MockAttachmentReference.swift in Sources */ = {isa = PBXBuildFile; fileRef = 663D02E02C06E2F400350632 /* MockAttachmentReference.swift */; };
663D6A7C292319BC00CABC49 /* ConversationPickerFailedRecipientsSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 663D6A7B292319BC00CABC49 /* ConversationPickerFailedRecipientsSheet.swift */; };
663F81D32E789E240033D2AE /* BackupAttachmentCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 663F81D22E789E0D0033D2AE /* BackupAttachmentCoordinator.swift */; };
663F81D52E78A70C0033D2AE /* BackupAttachmentDownloadScheduler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 663F81D42E78A6F10033D2AE /* BackupAttachmentDownloadScheduler.swift */; };
663F81D72E78BB9C0033D2AE /* BackupListMediaStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 663F81D62E78B5950033D2AE /* BackupListMediaStore.swift */; };
@@ -4874,7 +4873,6 @@
663D02DC2C06717900350632 /* UInt64SafeRecord.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UInt64SafeRecord.swift; sourceTree = "<group>"; };
663D02DE2C069AB600350632 /* OrphanedAttachmentCleanerTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OrphanedAttachmentCleanerTest.swift; sourceTree = "<group>"; };
663D02E02C06E2F400350632 /* MockAttachmentReference.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockAttachmentReference.swift; sourceTree = "<group>"; };
663D6A7B292319BC00CABC49 /* ConversationPickerFailedRecipientsSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConversationPickerFailedRecipientsSheet.swift; sourceTree = "<group>"; };
663F81D22E789E0D0033D2AE /* BackupAttachmentCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackupAttachmentCoordinator.swift; sourceTree = "<group>"; };
663F81D42E78A6F10033D2AE /* BackupAttachmentDownloadScheduler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackupAttachmentDownloadScheduler.swift; sourceTree = "<group>"; };
663F81D62E78B5950033D2AE /* BackupListMediaStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackupListMediaStore.swift; sourceTree = "<group>"; };
@@ -10987,7 +10985,6 @@
34A95536271B510400B05242 /* ContactTableViewCell.swift */,
34A9557C271B510500B05242 /* ConversationItem.swift */,
34A9557B271B510500B05242 /* ConversationPicker.swift */,
663D6A7B292319BC00CABC49 /* ConversationPickerFailedRecipientsSheet.swift */,
34ACA7F52733183000E47AD4 /* CountryCodeViewController.swift */,
E1C2A54A2A8FCB0D00AEC4DA /* DeleteSystemContactViewController.swift */,
34A9557D271B510500B05242 /* FindByPhoneNumberViewController.swift */,
@@ -16601,7 +16598,6 @@
3402AA75271D9E180084CBAE /* ConversationAvatarView.swift in Sources */,
3402AA37271D9DCD0084CBAE /* ConversationItem.swift in Sources */,
3402AA33271D9DCD0084CBAE /* ConversationPicker.swift in Sources */,
663D6A7C292319BC00CABC49 /* ConversationPickerFailedRecipientsSheet.swift in Sources */,
3402AA03271D9DB50084CBAE /* ConversationStyle.swift in Sources */,
34ACA7F72733183000E47AD4 /* CountryCodeViewController.swift in Sources */,
508F0346296F72F4001D88D0 /* CustomCellBackgroundColor.swift in Sources */,

View File

@@ -8911,21 +8911,6 @@
/* Context menu action to share the selected story */
"STORIES_SHARE_STORY_ACTION" = "Share";
/* Section title shown when sending to non-story conversations but failing to send the file to stories. */
"STORIES_SHARESHEET_PARTIAL_SEND_REMAINING_SECTION_TITLE" = "Sent To";
/* Section title shown when failing to send an incompatible file to stories, but still sending to non-story conversations. */
"STORIES_SHARESHEET_PARTIAL_SEND_STORIES_SECTION_TITLE" = "Not Sent To";
/* Title shown when failing to send an incompatible file to stories, but still sending to non-story conversations. */
"STORIES_SHARESHEET_PARTIAL_SEND_TITLE" = "Partially Sent";
/* Subtitle shown when failing to send an incompatible file to stories via the sharesheet. */
"STORIES_SHARESHEET_UNABLE_TO_SEND_SEND_SUBTITLE" = "The file type selected is not supported.";
/* Title shown when failing to send an incompatible file to stories via the sharesheet. */
"STORIES_SHARESHEET_UNABLE_TO_SEND_SEND_TITLE" = "Unable To Send";
/* Title for the stories view. */
"STORIES_TITLE" = "Stories";

View File

@@ -1448,22 +1448,6 @@
<string>%d attempts</string>
</dict>
</dict>
<key>STORIES_SHARESHEET_PARTIAL_SEND_SUBTITLE_%d</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%1$#@text@</string>
<key>text</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>Not all items could be sent to the story you selected because the file type is not supported.</string>
<key>other</key>
<string>Not all items could be sent to the stories you selected because the file type is not supported.</string>
</dict>
</dict>
<key>STORY_REPLIES_COUNT_%d</key>
<dict>
<key>NSStringLocalizedFormatKey</key>

View File

@@ -381,6 +381,10 @@ public class SignalAttachment: CustomDebugStringConvertible {
return self.isVideo ? (self.dataSource as! DataSourcePath) : nil
}
public var isVisualMedia: Bool {
return self.isImage || self.isVideo
}
public var isAudio: Bool {
return SignalAttachment.audioUTISet.contains(dataUTI)
}

View File

@@ -388,10 +388,7 @@ public class ShareViewController: OWSNavigationController, ShareViewDelegate, SA
setProgress(progress)
let typedItems = try await self.buildAttachments(
for: itemsAndProgresses,
mustBeVisualMedia: itemsAndProgresses.count >= 2,
)
let typedItems = try await self.buildAttachments(for: itemsAndProgresses)
try Task.checkCancellation()
// Make sure the user is not trying to share more than our attachment limit.
@@ -456,14 +453,11 @@ public class ShareViewController: OWSNavigationController, ShareViewDelegate, SA
throw ShareViewControllerError.noConformingInputItem
}
private nonisolated func buildAttachments(
for itemsAndProgresses: [(TypedItemProvider, Progress)],
mustBeVisualMedia: Bool,
) async throws -> [TypedItem] {
private nonisolated func buildAttachments(for itemsAndProgresses: [(TypedItemProvider, Progress)]) async throws -> [TypedItem] {
// FIXME: does not use a task group because SignalAttachment likes to load things into RAM and resize them; doing this in parallel can exhaust available RAM
var result: [TypedItem] = []
for (typedItemProvider, progress) in itemsAndProgresses {
result.append(try await typedItemProvider.buildAttachment(mustBeVisualMedia: mustBeVisualMedia, progress: progress))
result.append(try await typedItemProvider.buildAttachment(progress: progress))
}
return result
}

View File

@@ -554,31 +554,6 @@ extension SharingThreadPickerViewController: ConversationPickerDelegate {
}
func conversationPickerDidCompleteSelection(_ conversationPickerViewController: ConversationPickerViewController) {
// Check if the attachments are compatible with sending to stories.
let storySelections = selection.conversations.compactMap({ $0 as? StoryConversationItem })
if !storySelections.isEmpty {
if !self.canSendTypedItemsToStory() {
// Can't send to stories!
storySelections.forEach { self.selection.remove($0) }
self.updateUIForCurrentSelection(animated: false)
self.tableView.reloadData()
let vc = ConversationPickerFailedRecipientsSheet(
failedStoryConversationItems: storySelections,
remainingConversationItems: self.selection.conversations,
onApprove: { [weak self] in
guard
let strongSelf = self,
strongSelf.selection.conversations.isEmpty.negated
else {
return
}
strongSelf.conversationPickerDidCompleteSelection(strongSelf)
})
self.present(vc, animated: true)
return
}
}
approve()
}

View File

@@ -43,17 +43,15 @@ public enum TypedItem {
public var isVisualMedia: Bool {
switch self {
case .text, .contact: false
case .other(let attachment): attachment.isImage || attachment.isVideo
case .other(let attachment): attachment.isVisualMedia
}
}
public var isStoriesCompatible: Bool {
switch self {
case .text: return true
case .contact: return false
case .other(let attachment):
// TODO: Consolidate with isVisualMedia after fixing validity checks.
return attachment.isImage || attachment.isVideo
case .text: true
case .contact: false
case .other(let attachment): attachment.isVisualMedia
}
}
}
@@ -153,12 +151,12 @@ public struct TypedItemProvider {
private static let itemTypeOrder: [TypedItemProvider.ItemType] = [.movie, .image, .contact, .json, .plainText, .text, .pdf, .pkPass, .fileUrl, .webUrl, .data]
public static func buildVisualMediaAttachment(forItemProvider itemProvider: NSItemProvider) async throws -> SignalAttachment {
let typedItem = try await make(for: itemProvider).buildAttachment(mustBeVisualMedia: true)
let typedItem = try await make(for: itemProvider).buildAttachment()
switch typedItem {
case .text, .contact:
owsFail("not possible because mustBeVisualMedia is true")
case .other(let attachment):
case .other(let attachment) where attachment.isVisualMedia:
return attachment
case .text, .contact, .other:
throw SignalAttachmentError.invalidFileFormat
}
}
@@ -181,7 +179,7 @@ public struct TypedItemProvider {
// MARK: Methods
public nonisolated func buildAttachment(mustBeVisualMedia: Bool, progress: Progress? = nil) async throws -> TypedItem {
public nonisolated func buildAttachment(progress: Progress? = nil) async throws -> TypedItem {
// Whenever this finishes, mark its progress as fully complete. This
// handles item providers that can't provide partial progress updates.
defer {
@@ -200,7 +198,7 @@ public struct TypedItemProvider {
// 2) try to load a UIImage directly in the case that is what was sent over
// 3) try to NSKeyedUnarchive NSData directly into a UIImage
do {
attachment = try await buildFileAttachment(mustBeVisualMedia: mustBeVisualMedia, progress: progress)
attachment = try await buildFileAttachment(mustBeVisualMedia: true, progress: progress)
} catch SignalAttachmentError.couldNotParseImage, ItemProviderError.fileUrlWasBplist {
Logger.warn("failed to parse image directly from file; checking for loading UIImage directly")
let image: UIImage = try await loadObjectWithKeyedUnarchiverFallback(
@@ -209,8 +207,10 @@ public struct TypedItemProvider {
)
attachment = try Self.createAttachment(withImage: image)
}
case .movie, .pdf, .data:
attachment = try await self.buildFileAttachment(mustBeVisualMedia: mustBeVisualMedia, progress: progress)
case .movie:
attachment = try await self.buildFileAttachment(mustBeVisualMedia: true, progress: progress)
case .pdf, .data:
attachment = try await self.buildFileAttachment(mustBeVisualMedia: false, progress: progress)
case .fileUrl, .json:
let url: NSURL = try await loadObjectWithKeyedUnarchiverFallback(
overrideTypeIdentifier: TypedItemProvider.ItemType.fileUrl.typeIdentifier,
@@ -224,37 +224,25 @@ public struct TypedItemProvider {
attachment = try await _buildFileAttachment(
dataSource: dataSource,
dataUTI: dataUTI,
mustBeVisualMedia: mustBeVisualMedia,
mustBeVisualMedia: false,
progress: progress,
)
case .webUrl:
if mustBeVisualMedia {
throw SignalAttachmentError.invalidFileFormat
}
let url: NSURL = try await loadObjectWithKeyedUnarchiverFallback(
cannotLoadError: .cannotLoadURLObject,
failedLoadError: .loadURLObjectFailed
)
return try Self.createAttachment(withText: (url as URL).absoluteString)
case .contact:
if mustBeVisualMedia {
throw SignalAttachmentError.invalidFileFormat
}
let contactData = try await loadDataRepresentation()
return .contact(contactData)
case .plainText, .text:
if mustBeVisualMedia {
throw SignalAttachmentError.invalidFileFormat
}
let text: NSString = try await loadObjectWithKeyedUnarchiverFallback(
cannotLoadError: .cannotLoadStringObject,
failedLoadError: .loadStringObjectFailed
)
return try Self.createAttachment(withText: text as String)
case .pkPass:
if mustBeVisualMedia {
throw SignalAttachmentError.invalidFileFormat
}
let pkPass = try await loadDataRepresentation()
let dataSource = DataSourceValue(pkPass, utiType: itemType.typeIdentifier)
guard let dataSource else {

View File

@@ -1,171 +0,0 @@
//
// Copyright 2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
//
import Foundation
import SignalServiceKit
public class ConversationPickerFailedRecipientsSheet: OWSTableSheetViewController {
let failedStoryConversationItems: [StoryConversationItem]
let remainingConversationItems: [ConversationItem]
let onApprove: () -> Void
public init(
failedStoryConversationItems: [StoryConversationItem],
remainingConversationItems: [ConversationItem],
onApprove: @escaping () -> Void
) {
assert(!failedStoryConversationItems.isEmpty)
self.failedStoryConversationItems = failedStoryConversationItems
self.remainingConversationItems = remainingConversationItems
self.onApprove = onApprove
super.init()
tableViewController.bottomFooter = tableFooterView()
}
public override func viewDidLoad() {
super.viewDidLoad()
tableViewController.tableView.register(
ConversationPickerCell.self,
forCellReuseIdentifier: ConversationPickerCell.reuseIdentifier
)
}
private func tableFooterView() -> UIView? {
let doneButton = UIButton(
configuration: .largePrimary(title: CommonStrings.okayButton),
primaryAction: UIAction { [weak self] _ in
self?.dismiss(animated: true) {
self?.onApprove()
}
}
)
let stackView = doneButton.enclosedInVerticalStackView(isFullWidthButton: true)
stackView.directionalLayoutMargins.leading = 48
stackView.directionalLayoutMargins.trailing = 48
return stackView
}
public override func tableContents() -> OWSTableContents {
let contents = OWSTableContents()
let headerSection = OWSTableSection()
headerSection.separatorInsetLeading = OWSTableViewController2.cellHInnerMargin + 32
let headerTitle: String
let headerSubtitle: String
if remainingConversationItems.isEmpty {
headerTitle = OWSLocalizedString(
"STORIES_SHARESHEET_UNABLE_TO_SEND_SEND_TITLE",
comment: "Title shown when failing to send an incompatible file to stories via the sharesheet."
)
headerSubtitle = OWSLocalizedString(
"STORIES_SHARESHEET_UNABLE_TO_SEND_SEND_SUBTITLE",
comment: "Subtitle shown when failing to send an incompatible file to stories via the sharesheet."
)
} else {
headerTitle = OWSLocalizedString(
"STORIES_SHARESHEET_PARTIAL_SEND_TITLE",
comment: "Title shown when failing to send an incompatible file to stories, but still sending to non-story conversations."
)
let subtitleFormat = OWSLocalizedString(
"STORIES_SHARESHEET_PARTIAL_SEND_SUBTITLE_%d",
tableName: "PluralAware",
comment: "Subtitle shown when failing to send a single incompatible file to stories via the sharesheet."
)
headerSubtitle = String.localizedStringWithFormat(
subtitleFormat,
failedStoryConversationItems.count
)
}
let headerView = SheetHeaderView(
title: headerTitle,
subtitle: headerSubtitle
)
headerSection.customHeaderView = headerView
contents.add(headerSection)
let failedStoriesSection = OWSTableSection()
failedStoriesSection.headerTitle = OWSLocalizedString(
"STORIES_SHARESHEET_PARTIAL_SEND_STORIES_SECTION_TITLE",
comment: "Section title shown when failing to send an incompatible file to stories, but still sending to non-story conversations."
)
for item in failedStoryConversationItems {
failedStoriesSection.add(OWSTableItem(dequeueCellBlock: { tableView in
guard let cell = tableView.dequeueReusableCell(withIdentifier: ConversationPickerCell.reuseIdentifier) as? ConversationPickerCell else {
return UITableViewCell()
}
SSKEnvironment.shared.databaseStorageRef.read {
cell.configure(conversationItem: item, transaction: $0)
}
cell.showsSelectionUI = false
return cell
}))
}
contents.add(failedStoriesSection)
if !remainingConversationItems.isEmpty {
let remainingConversationsSection = OWSTableSection()
remainingConversationsSection.headerTitle = OWSLocalizedString(
"STORIES_SHARESHEET_PARTIAL_SEND_REMAINING_SECTION_TITLE",
comment: "Section title shown when sending to non-story conversations but failing to send the file to stories."
)
for item in remainingConversationItems {
remainingConversationsSection.add(OWSTableItem(dequeueCellBlock: { tableView in
guard let cell = tableView.dequeueReusableCell(withIdentifier: ConversationPickerCell.reuseIdentifier) as? ConversationPickerCell else {
return UITableViewCell()
}
SSKEnvironment.shared.databaseStorageRef.read {
cell.configure(conversationItem: item, transaction: $0)
}
cell.showsSelectionUI = false
return cell
}))
}
contents.add(remainingConversationsSection)
}
return contents
}
private class SheetHeaderView: UIView {
let titleLabel = UILabel()
let subtitleLabel = UILabel()
init(title: String, subtitle: String) {
super.init(frame: .zero)
titleLabel.text = title
titleLabel.textAlignment = .center
titleLabel.font = .dynamicTypeTitle2.semibold()
titleLabel.textColor = Theme.primaryTextColor
addSubview(titleLabel)
subtitleLabel.numberOfLines = 0
subtitleLabel.text = subtitle
subtitleLabel.textAlignment = .center
subtitleLabel.font = .dynamicTypeSubheadline
subtitleLabel.textColor = Theme.primaryTextColor
addSubview(subtitleLabel)
titleLabel.autoPinWidthToSuperview(withMargin: 24)
titleLabel.autoPinTopToSuperviewMargin()
subtitleLabel.autoHCenterInSuperview()
subtitleLabel.autoPinWidthToSuperview(withMargin: 24)
subtitleLabel.autoPinBottomToSuperviewMargin()
subtitleLabel.autoPinEdge(.top, to: .bottom, of: titleLabel, withOffset: 8)
}
@available(*, unavailable)
required init?(coder: NSCoder) {
return nil
}
}
}