mirror of
https://github.com/signalapp/Signal-iOS.git
synced 2025-12-05 01:10:41 +00:00
Remove stories code that’s no longer necessary
This commit is contained in:
@@ -892,7 +892,6 @@
|
|||||||
663D02DD2C06717900350632 /* UInt64SafeRecord.swift in Sources */ = {isa = PBXBuildFile; fileRef = 663D02DC2C06717900350632 /* UInt64SafeRecord.swift */; };
|
663D02DD2C06717900350632 /* UInt64SafeRecord.swift in Sources */ = {isa = PBXBuildFile; fileRef = 663D02DC2C06717900350632 /* UInt64SafeRecord.swift */; };
|
||||||
663D02DF2C069AB600350632 /* OrphanedAttachmentCleanerTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 663D02DE2C069AB600350632 /* OrphanedAttachmentCleanerTest.swift */; };
|
663D02DF2C069AB600350632 /* OrphanedAttachmentCleanerTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 663D02DE2C069AB600350632 /* OrphanedAttachmentCleanerTest.swift */; };
|
||||||
663D02E12C06E2F400350632 /* MockAttachmentReference.swift in Sources */ = {isa = PBXBuildFile; fileRef = 663D02E02C06E2F400350632 /* MockAttachmentReference.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 */; };
|
663F81D32E789E240033D2AE /* BackupAttachmentCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 663F81D22E789E0D0033D2AE /* BackupAttachmentCoordinator.swift */; };
|
||||||
663F81D52E78A70C0033D2AE /* BackupAttachmentDownloadScheduler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 663F81D42E78A6F10033D2AE /* BackupAttachmentDownloadScheduler.swift */; };
|
663F81D52E78A70C0033D2AE /* BackupAttachmentDownloadScheduler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 663F81D42E78A6F10033D2AE /* BackupAttachmentDownloadScheduler.swift */; };
|
||||||
663F81D72E78BB9C0033D2AE /* BackupListMediaStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 663F81D62E78B5950033D2AE /* BackupListMediaStore.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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
663F81D62E78B5950033D2AE /* BackupListMediaStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackupListMediaStore.swift; sourceTree = "<group>"; };
|
||||||
@@ -10987,7 +10985,6 @@
|
|||||||
34A95536271B510400B05242 /* ContactTableViewCell.swift */,
|
34A95536271B510400B05242 /* ContactTableViewCell.swift */,
|
||||||
34A9557C271B510500B05242 /* ConversationItem.swift */,
|
34A9557C271B510500B05242 /* ConversationItem.swift */,
|
||||||
34A9557B271B510500B05242 /* ConversationPicker.swift */,
|
34A9557B271B510500B05242 /* ConversationPicker.swift */,
|
||||||
663D6A7B292319BC00CABC49 /* ConversationPickerFailedRecipientsSheet.swift */,
|
|
||||||
34ACA7F52733183000E47AD4 /* CountryCodeViewController.swift */,
|
34ACA7F52733183000E47AD4 /* CountryCodeViewController.swift */,
|
||||||
E1C2A54A2A8FCB0D00AEC4DA /* DeleteSystemContactViewController.swift */,
|
E1C2A54A2A8FCB0D00AEC4DA /* DeleteSystemContactViewController.swift */,
|
||||||
34A9557D271B510500B05242 /* FindByPhoneNumberViewController.swift */,
|
34A9557D271B510500B05242 /* FindByPhoneNumberViewController.swift */,
|
||||||
@@ -16601,7 +16598,6 @@
|
|||||||
3402AA75271D9E180084CBAE /* ConversationAvatarView.swift in Sources */,
|
3402AA75271D9E180084CBAE /* ConversationAvatarView.swift in Sources */,
|
||||||
3402AA37271D9DCD0084CBAE /* ConversationItem.swift in Sources */,
|
3402AA37271D9DCD0084CBAE /* ConversationItem.swift in Sources */,
|
||||||
3402AA33271D9DCD0084CBAE /* ConversationPicker.swift in Sources */,
|
3402AA33271D9DCD0084CBAE /* ConversationPicker.swift in Sources */,
|
||||||
663D6A7C292319BC00CABC49 /* ConversationPickerFailedRecipientsSheet.swift in Sources */,
|
|
||||||
3402AA03271D9DB50084CBAE /* ConversationStyle.swift in Sources */,
|
3402AA03271D9DB50084CBAE /* ConversationStyle.swift in Sources */,
|
||||||
34ACA7F72733183000E47AD4 /* CountryCodeViewController.swift in Sources */,
|
34ACA7F72733183000E47AD4 /* CountryCodeViewController.swift in Sources */,
|
||||||
508F0346296F72F4001D88D0 /* CustomCellBackgroundColor.swift in Sources */,
|
508F0346296F72F4001D88D0 /* CustomCellBackgroundColor.swift in Sources */,
|
||||||
|
|||||||
@@ -8911,21 +8911,6 @@
|
|||||||
/* Context menu action to share the selected story */
|
/* Context menu action to share the selected story */
|
||||||
"STORIES_SHARE_STORY_ACTION" = "Share";
|
"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. */
|
/* Title for the stories view. */
|
||||||
"STORIES_TITLE" = "Stories";
|
"STORIES_TITLE" = "Stories";
|
||||||
|
|
||||||
|
|||||||
@@ -1448,22 +1448,6 @@
|
|||||||
<string>%d attempts</string>
|
<string>%d attempts</string>
|
||||||
</dict>
|
</dict>
|
||||||
</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>
|
<key>STORY_REPLIES_COUNT_%d</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>NSStringLocalizedFormatKey</key>
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
|||||||
@@ -381,6 +381,10 @@ public class SignalAttachment: CustomDebugStringConvertible {
|
|||||||
return self.isVideo ? (self.dataSource as! DataSourcePath) : nil
|
return self.isVideo ? (self.dataSource as! DataSourcePath) : nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public var isVisualMedia: Bool {
|
||||||
|
return self.isImage || self.isVideo
|
||||||
|
}
|
||||||
|
|
||||||
public var isAudio: Bool {
|
public var isAudio: Bool {
|
||||||
return SignalAttachment.audioUTISet.contains(dataUTI)
|
return SignalAttachment.audioUTISet.contains(dataUTI)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -388,10 +388,7 @@ public class ShareViewController: OWSNavigationController, ShareViewDelegate, SA
|
|||||||
|
|
||||||
setProgress(progress)
|
setProgress(progress)
|
||||||
|
|
||||||
let typedItems = try await self.buildAttachments(
|
let typedItems = try await self.buildAttachments(for: itemsAndProgresses)
|
||||||
for: itemsAndProgresses,
|
|
||||||
mustBeVisualMedia: itemsAndProgresses.count >= 2,
|
|
||||||
)
|
|
||||||
try Task.checkCancellation()
|
try Task.checkCancellation()
|
||||||
|
|
||||||
// Make sure the user is not trying to share more than our attachment limit.
|
// 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
|
throw ShareViewControllerError.noConformingInputItem
|
||||||
}
|
}
|
||||||
|
|
||||||
private nonisolated func buildAttachments(
|
private nonisolated func buildAttachments(for itemsAndProgresses: [(TypedItemProvider, Progress)]) async throws -> [TypedItem] {
|
||||||
for itemsAndProgresses: [(TypedItemProvider, Progress)],
|
|
||||||
mustBeVisualMedia: Bool,
|
|
||||||
) 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
|
// 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] = []
|
var result: [TypedItem] = []
|
||||||
for (typedItemProvider, progress) in itemsAndProgresses {
|
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
|
return result
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -554,31 +554,6 @@ extension SharingThreadPickerViewController: ConversationPickerDelegate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func conversationPickerDidCompleteSelection(_ conversationPickerViewController: ConversationPickerViewController) {
|
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()
|
approve()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -43,17 +43,15 @@ public enum TypedItem {
|
|||||||
public var isVisualMedia: Bool {
|
public var isVisualMedia: Bool {
|
||||||
switch self {
|
switch self {
|
||||||
case .text, .contact: false
|
case .text, .contact: false
|
||||||
case .other(let attachment): attachment.isImage || attachment.isVideo
|
case .other(let attachment): attachment.isVisualMedia
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public var isStoriesCompatible: Bool {
|
public var isStoriesCompatible: Bool {
|
||||||
switch self {
|
switch self {
|
||||||
case .text: return true
|
case .text: true
|
||||||
case .contact: return false
|
case .contact: false
|
||||||
case .other(let attachment):
|
case .other(let attachment): attachment.isVisualMedia
|
||||||
// TODO: Consolidate with isVisualMedia after fixing validity checks.
|
|
||||||
return attachment.isImage || attachment.isVideo
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -153,12 +151,12 @@ public struct TypedItemProvider {
|
|||||||
private static let itemTypeOrder: [TypedItemProvider.ItemType] = [.movie, .image, .contact, .json, .plainText, .text, .pdf, .pkPass, .fileUrl, .webUrl, .data]
|
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 {
|
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 {
|
switch typedItem {
|
||||||
case .text, .contact:
|
case .other(let attachment) where attachment.isVisualMedia:
|
||||||
owsFail("not possible because mustBeVisualMedia is true")
|
|
||||||
case .other(let attachment):
|
|
||||||
return attachment
|
return attachment
|
||||||
|
case .text, .contact, .other:
|
||||||
|
throw SignalAttachmentError.invalidFileFormat
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,7 +179,7 @@ public struct TypedItemProvider {
|
|||||||
|
|
||||||
// MARK: Methods
|
// 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
|
// Whenever this finishes, mark its progress as fully complete. This
|
||||||
// handles item providers that can't provide partial progress updates.
|
// handles item providers that can't provide partial progress updates.
|
||||||
defer {
|
defer {
|
||||||
@@ -200,7 +198,7 @@ public struct TypedItemProvider {
|
|||||||
// 2) try to load a UIImage directly in the case that is what was sent over
|
// 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
|
// 3) try to NSKeyedUnarchive NSData directly into a UIImage
|
||||||
do {
|
do {
|
||||||
attachment = try await buildFileAttachment(mustBeVisualMedia: mustBeVisualMedia, progress: progress)
|
attachment = try await buildFileAttachment(mustBeVisualMedia: true, progress: progress)
|
||||||
} catch SignalAttachmentError.couldNotParseImage, ItemProviderError.fileUrlWasBplist {
|
} catch SignalAttachmentError.couldNotParseImage, ItemProviderError.fileUrlWasBplist {
|
||||||
Logger.warn("failed to parse image directly from file; checking for loading UIImage directly")
|
Logger.warn("failed to parse image directly from file; checking for loading UIImage directly")
|
||||||
let image: UIImage = try await loadObjectWithKeyedUnarchiverFallback(
|
let image: UIImage = try await loadObjectWithKeyedUnarchiverFallback(
|
||||||
@@ -209,8 +207,10 @@ public struct TypedItemProvider {
|
|||||||
)
|
)
|
||||||
attachment = try Self.createAttachment(withImage: image)
|
attachment = try Self.createAttachment(withImage: image)
|
||||||
}
|
}
|
||||||
case .movie, .pdf, .data:
|
case .movie:
|
||||||
attachment = try await self.buildFileAttachment(mustBeVisualMedia: mustBeVisualMedia, progress: progress)
|
attachment = try await self.buildFileAttachment(mustBeVisualMedia: true, progress: progress)
|
||||||
|
case .pdf, .data:
|
||||||
|
attachment = try await self.buildFileAttachment(mustBeVisualMedia: false, progress: progress)
|
||||||
case .fileUrl, .json:
|
case .fileUrl, .json:
|
||||||
let url: NSURL = try await loadObjectWithKeyedUnarchiverFallback(
|
let url: NSURL = try await loadObjectWithKeyedUnarchiverFallback(
|
||||||
overrideTypeIdentifier: TypedItemProvider.ItemType.fileUrl.typeIdentifier,
|
overrideTypeIdentifier: TypedItemProvider.ItemType.fileUrl.typeIdentifier,
|
||||||
@@ -224,37 +224,25 @@ public struct TypedItemProvider {
|
|||||||
attachment = try await _buildFileAttachment(
|
attachment = try await _buildFileAttachment(
|
||||||
dataSource: dataSource,
|
dataSource: dataSource,
|
||||||
dataUTI: dataUTI,
|
dataUTI: dataUTI,
|
||||||
mustBeVisualMedia: mustBeVisualMedia,
|
mustBeVisualMedia: false,
|
||||||
progress: progress,
|
progress: progress,
|
||||||
)
|
)
|
||||||
case .webUrl:
|
case .webUrl:
|
||||||
if mustBeVisualMedia {
|
|
||||||
throw SignalAttachmentError.invalidFileFormat
|
|
||||||
}
|
|
||||||
let url: NSURL = try await loadObjectWithKeyedUnarchiverFallback(
|
let url: NSURL = try await loadObjectWithKeyedUnarchiverFallback(
|
||||||
cannotLoadError: .cannotLoadURLObject,
|
cannotLoadError: .cannotLoadURLObject,
|
||||||
failedLoadError: .loadURLObjectFailed
|
failedLoadError: .loadURLObjectFailed
|
||||||
)
|
)
|
||||||
return try Self.createAttachment(withText: (url as URL).absoluteString)
|
return try Self.createAttachment(withText: (url as URL).absoluteString)
|
||||||
case .contact:
|
case .contact:
|
||||||
if mustBeVisualMedia {
|
|
||||||
throw SignalAttachmentError.invalidFileFormat
|
|
||||||
}
|
|
||||||
let contactData = try await loadDataRepresentation()
|
let contactData = try await loadDataRepresentation()
|
||||||
return .contact(contactData)
|
return .contact(contactData)
|
||||||
case .plainText, .text:
|
case .plainText, .text:
|
||||||
if mustBeVisualMedia {
|
|
||||||
throw SignalAttachmentError.invalidFileFormat
|
|
||||||
}
|
|
||||||
let text: NSString = try await loadObjectWithKeyedUnarchiverFallback(
|
let text: NSString = try await loadObjectWithKeyedUnarchiverFallback(
|
||||||
cannotLoadError: .cannotLoadStringObject,
|
cannotLoadError: .cannotLoadStringObject,
|
||||||
failedLoadError: .loadStringObjectFailed
|
failedLoadError: .loadStringObjectFailed
|
||||||
)
|
)
|
||||||
return try Self.createAttachment(withText: text as String)
|
return try Self.createAttachment(withText: text as String)
|
||||||
case .pkPass:
|
case .pkPass:
|
||||||
if mustBeVisualMedia {
|
|
||||||
throw SignalAttachmentError.invalidFileFormat
|
|
||||||
}
|
|
||||||
let pkPass = try await loadDataRepresentation()
|
let pkPass = try await loadDataRepresentation()
|
||||||
let dataSource = DataSourceValue(pkPass, utiType: itemType.typeIdentifier)
|
let dataSource = DataSourceValue(pkPass, utiType: itemType.typeIdentifier)
|
||||||
guard let dataSource else {
|
guard let dataSource else {
|
||||||
|
|||||||
@@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user