mirror of
https://github.com/Dimillian/IceCubesApp.git
synced 2025-01-24 06:48:10 +00:00
Improve media selection on the status editor. (#1722)
* show menu buttons on media item * fix media preparing logic - not removing photo pickers when removing media on the post editor - pickers don't have identifiers after being selected - preparing tasks (creating containers, uploading media) don't run in parallel - re-preparing the whole media list every time adding new ones * remove measurement code * rename variables * fix MainActor mutation
This commit is contained in:
parent
9fe5994bb2
commit
774ba834bd
4 changed files with 252 additions and 165 deletions
|
@ -57,9 +57,11 @@ struct StatusEditorAccessoryView: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.photosPicker(isPresented: $isPhotosPickerPresented,
|
.photosPicker(isPresented: $isPhotosPickerPresented,
|
||||||
selection: $viewModel.selectedMedias,
|
selection: $viewModel.mediaPickers,
|
||||||
maxSelectionCount: 4,
|
maxSelectionCount: 4,
|
||||||
matching: .any(of: [.images, .videos]))
|
matching: .any(of: [.images, .videos]),
|
||||||
|
photoLibrary: .shared()
|
||||||
|
)
|
||||||
.fileImporter(isPresented: $isFileImporterPresented,
|
.fileImporter(isPresented: $isFileImporterPresented,
|
||||||
allowedContentTypes: [.image, .video],
|
allowedContentTypes: [.image, .video],
|
||||||
allowsMultipleSelection: true)
|
allowsMultipleSelection: true)
|
||||||
|
|
|
@ -5,7 +5,7 @@ import SwiftUI
|
||||||
import UIKit
|
import UIKit
|
||||||
|
|
||||||
struct StatusEditorMediaContainer: Identifiable {
|
struct StatusEditorMediaContainer: Identifiable {
|
||||||
let id = UUID().uuidString
|
let id: String
|
||||||
let image: UIImage?
|
let image: UIImage?
|
||||||
let movieTransferable: MovieFileTranseferable?
|
let movieTransferable: MovieFileTranseferable?
|
||||||
let gifTransferable: GifFileTranseferable?
|
let gifTransferable: GifFileTranseferable?
|
||||||
|
|
|
@ -17,11 +17,10 @@ struct StatusEditorMediaView: View {
|
||||||
var body: some View {
|
var body: some View {
|
||||||
ScrollView(.horizontal, showsIndicators: false) {
|
ScrollView(.horizontal, showsIndicators: false) {
|
||||||
HStack(spacing: 8) {
|
HStack(spacing: 8) {
|
||||||
ForEach(viewModel.mediasImages) { container in
|
ForEach(viewModel.mediaContainers) { container in
|
||||||
Menu {
|
Menu {
|
||||||
makeImageMenu(container: container)
|
makeImageMenu(container: container)
|
||||||
} label: {
|
} label: {
|
||||||
ZStack(alignment: .bottomTrailing) {
|
|
||||||
if let attachement = container.mediaAttachment {
|
if let attachement = container.mediaAttachment {
|
||||||
makeLazyImage(mediaAttachement: attachement)
|
makeLazyImage(mediaAttachement: attachement)
|
||||||
} else if container.image != nil {
|
} else if container.image != nil {
|
||||||
|
@ -31,10 +30,12 @@ struct StatusEditorMediaView: View {
|
||||||
} else if let error = container.error as? ServerError {
|
} else if let error = container.error as? ServerError {
|
||||||
makeErrorView(error: error)
|
makeErrorView(error: error)
|
||||||
}
|
}
|
||||||
if container.mediaAttachment?.description?.isEmpty == false {
|
|
||||||
altMarker
|
|
||||||
}
|
}
|
||||||
|
.overlay(alignment: .bottomTrailing) {
|
||||||
|
makeAltMarker(container: container)
|
||||||
}
|
}
|
||||||
|
.overlay(alignment: .topTrailing) {
|
||||||
|
makeDiscardMarker(container: container)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -122,7 +123,13 @@ struct StatusEditorMediaView: View {
|
||||||
|
|
||||||
Button(role: .destructive) {
|
Button(role: .destructive) {
|
||||||
withAnimation {
|
withAnimation {
|
||||||
viewModel.mediasImages.removeAll(where: { $0.id == container.id })
|
viewModel.mediaPickers.removeAll(where: {
|
||||||
|
if let id = $0.itemIdentifier {
|
||||||
|
return id == container.id
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
} label: {
|
} label: {
|
||||||
Label("action.delete", systemImage: "trash")
|
Label("action.delete", systemImage: "trash")
|
||||||
|
@ -141,14 +148,37 @@ struct StatusEditorMediaView: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private var altMarker: some View {
|
private func makeAltMarker(container: StatusEditorMediaContainer) -> some View {
|
||||||
Button {} label: {
|
Button {
|
||||||
|
editingContainer = container
|
||||||
|
} label: {
|
||||||
Text("status.image.alt-text.abbreviation")
|
Text("status.image.alt-text.abbreviation")
|
||||||
.font(.caption2)
|
.font(.caption2)
|
||||||
}
|
}
|
||||||
.padding(4)
|
.padding(4)
|
||||||
.background(.thinMaterial)
|
.background(.thinMaterial)
|
||||||
.cornerRadius(8)
|
.cornerRadius(8)
|
||||||
|
.padding(4)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func makeDiscardMarker(container: StatusEditorMediaContainer) -> some View {
|
||||||
|
Button(role: .destructive) {
|
||||||
|
withAnimation {
|
||||||
|
viewModel.mediaPickers.removeAll(where: {
|
||||||
|
if let id = $0.itemIdentifier {
|
||||||
|
return id == container.id
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} label: {
|
||||||
|
Image(systemName: "xmark")
|
||||||
|
.font(.caption2)
|
||||||
|
.foregroundStyle(.tint)
|
||||||
|
.padding(4)
|
||||||
|
.background(Circle().fill(.thinMaterial))
|
||||||
|
}
|
||||||
|
.padding(4)
|
||||||
}
|
}
|
||||||
|
|
||||||
private var placeholderView: some View {
|
private var placeholderView: some View {
|
||||||
|
|
|
@ -15,7 +15,7 @@ import SwiftUI
|
||||||
var currentAccount: Account? {
|
var currentAccount: Account? {
|
||||||
didSet {
|
didSet {
|
||||||
if let itemsProvider {
|
if let itemsProvider {
|
||||||
mediasImages = []
|
mediaContainers = []
|
||||||
processItemsProvider(items: itemsProvider)
|
processItemsProvider(items: itemsProvider)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -84,19 +84,30 @@ import SwiftUI
|
||||||
var spoilerText: String = ""
|
var spoilerText: String = ""
|
||||||
|
|
||||||
var isPosting: Bool = false
|
var isPosting: Bool = false
|
||||||
var selectedMedias: [PhotosPickerItem] = [] {
|
var mediaPickers: [PhotosPickerItem] = [] {
|
||||||
didSet {
|
didSet {
|
||||||
if selectedMedias.count > 4 {
|
if mediaPickers.count > 4 {
|
||||||
selectedMedias = selectedMedias.prefix(4).map { $0 }
|
mediaPickers = mediaPickers.prefix(4).map { $0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let removedIDs = oldValue
|
||||||
|
.filter { !mediaPickers.contains($0) }
|
||||||
|
.compactMap { $0.itemIdentifier }
|
||||||
|
mediaContainers.removeAll { removedIDs.contains($0.id) }
|
||||||
|
|
||||||
|
let newPickerItems = mediaPickers.filter { !oldValue.contains($0) }
|
||||||
|
if !newPickerItems.isEmpty {
|
||||||
isMediasLoading = true
|
isMediasLoading = true
|
||||||
inflateSelectedMedias()
|
for item in newPickerItems {
|
||||||
|
prepareToPost(for: item)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var isMediasLoading: Bool = false
|
var isMediasLoading: Bool = false
|
||||||
|
|
||||||
var mediasImages: [StatusEditorMediaContainer] = []
|
private(set) var mediaContainers: [StatusEditorMediaContainer] = []
|
||||||
var replyToStatus: Status?
|
var replyToStatus: Status?
|
||||||
var embeddedStatus: Status?
|
var embeddedStatus: Status?
|
||||||
|
|
||||||
|
@ -106,11 +117,11 @@ import SwiftUI
|
||||||
var showPostingErrorAlert: Bool = false
|
var showPostingErrorAlert: Bool = false
|
||||||
|
|
||||||
var canPost: Bool {
|
var canPost: Bool {
|
||||||
statusText.length > 0 || !mediasImages.isEmpty
|
statusText.length > 0 || !mediaContainers.isEmpty
|
||||||
}
|
}
|
||||||
|
|
||||||
var shouldDisablePollButton: Bool {
|
var shouldDisablePollButton: Bool {
|
||||||
!selectedMedias.isEmpty
|
!mediaPickers.isEmpty
|
||||||
}
|
}
|
||||||
|
|
||||||
var shouldDisplayDismissWarning: Bool {
|
var shouldDisplayDismissWarning: Bool {
|
||||||
|
@ -137,7 +148,6 @@ import SwiftUI
|
||||||
|
|
||||||
private var mentionString: String?
|
private var mentionString: String?
|
||||||
|
|
||||||
private var uploadTask: Task<Void, Never>?
|
|
||||||
private var suggestedTask: Task<Void, Never>?
|
private var suggestedTask: Task<Void, Never>?
|
||||||
|
|
||||||
init(mode: Mode) {
|
init(mode: Mode) {
|
||||||
|
@ -182,7 +192,7 @@ import SwiftUI
|
||||||
visibility: visibility,
|
visibility: visibility,
|
||||||
inReplyToId: mode.replyToStatus?.id,
|
inReplyToId: mode.replyToStatus?.id,
|
||||||
spoilerText: spoilerOn ? spoilerText : nil,
|
spoilerText: spoilerOn ? spoilerText : nil,
|
||||||
mediaIds: mediasImages.compactMap { $0.mediaAttachment?.id },
|
mediaIds: mediaContainers.compactMap { $0.mediaAttachment?.id },
|
||||||
poll: pollData,
|
poll: pollData,
|
||||||
language: selectedLanguage,
|
language: selectedLanguage,
|
||||||
mediaAttributes: mediaAttributes)
|
mediaAttributes: mediaAttributes)
|
||||||
|
@ -278,11 +288,15 @@ import SwiftUI
|
||||||
spoilerOn = !status.spoilerText.asRawText.isEmpty
|
spoilerOn = !status.spoilerText.asRawText.isEmpty
|
||||||
spoilerText = status.spoilerText.asRawText
|
spoilerText = status.spoilerText.asRawText
|
||||||
visibility = status.visibility
|
visibility = status.visibility
|
||||||
mediasImages = status.mediaAttachments.map { .init(image: nil,
|
mediaContainers = status.mediaAttachments.map {
|
||||||
|
StatusEditorMediaContainer(
|
||||||
|
id: UUID().uuidString,
|
||||||
|
image: nil,
|
||||||
movieTransferable: nil,
|
movieTransferable: nil,
|
||||||
gifTransferable: nil,
|
gifTransferable: nil,
|
||||||
mediaAttachment: $0,
|
mediaAttachment: $0,
|
||||||
error: nil) }
|
error: nil)
|
||||||
|
}
|
||||||
case let .quote(status):
|
case let .quote(status):
|
||||||
embeddedStatus = status
|
embeddedStatus = status
|
||||||
if let url = embeddedStatusURL {
|
if let url = embeddedStatusURL {
|
||||||
|
@ -370,12 +384,14 @@ import SwiftUI
|
||||||
}
|
}
|
||||||
|
|
||||||
func processCameraPhoto(image: UIImage) {
|
func processCameraPhoto(image: UIImage) {
|
||||||
mediasImages.append(.init(image: image,
|
let container = StatusEditorMediaContainer(
|
||||||
|
id: UUID().uuidString,
|
||||||
|
image: image,
|
||||||
movieTransferable: nil,
|
movieTransferable: nil,
|
||||||
gifTransferable: nil,
|
gifTransferable: nil,
|
||||||
mediaAttachment: nil,
|
mediaAttachment: nil,
|
||||||
error: nil))
|
error: nil)
|
||||||
processMediasToUpload()
|
prepareToPost(for: container)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func processItemsProvider(items: [NSItemProvider]) {
|
private func processItemsProvider(items: [NSItemProvider]) {
|
||||||
|
@ -391,32 +407,44 @@ import SwiftUI
|
||||||
if let text = content as? String {
|
if let text = content as? String {
|
||||||
initialText += "\(text) "
|
initialText += "\(text) "
|
||||||
} else if let image = content as? UIImage {
|
} else if let image = content as? UIImage {
|
||||||
mediasImages.append(.init(image: image,
|
let container = StatusEditorMediaContainer(
|
||||||
|
id: UUID().uuidString,
|
||||||
|
image: image,
|
||||||
movieTransferable: nil,
|
movieTransferable: nil,
|
||||||
gifTransferable: nil,
|
gifTransferable: nil,
|
||||||
mediaAttachment: nil,
|
mediaAttachment: nil,
|
||||||
error: nil))
|
error: nil)
|
||||||
|
prepareToPost(for: container)
|
||||||
} else if let content = content as? ImageFileTranseferable,
|
} else if let content = content as? ImageFileTranseferable,
|
||||||
let compressedData = await compressor.compressImageFrom(url: content.url),
|
let compressedData = await compressor.compressImageFrom(url: content.url),
|
||||||
let image = UIImage(data: compressedData)
|
let image = UIImage(data: compressedData)
|
||||||
{
|
{
|
||||||
mediasImages.append(.init(image: image,
|
let container = StatusEditorMediaContainer(
|
||||||
|
id: UUID().uuidString,
|
||||||
|
image: image,
|
||||||
movieTransferable: nil,
|
movieTransferable: nil,
|
||||||
gifTransferable: nil,
|
gifTransferable: nil,
|
||||||
mediaAttachment: nil,
|
mediaAttachment: nil,
|
||||||
error: nil))
|
error: nil)
|
||||||
|
prepareToPost(for: container)
|
||||||
} else if let video = content as? MovieFileTranseferable {
|
} else if let video = content as? MovieFileTranseferable {
|
||||||
mediasImages.append(.init(image: nil,
|
let container = StatusEditorMediaContainer(
|
||||||
|
id: UUID().uuidString,
|
||||||
|
image: nil,
|
||||||
movieTransferable: video,
|
movieTransferable: video,
|
||||||
gifTransferable: nil,
|
gifTransferable: nil,
|
||||||
mediaAttachment: nil,
|
mediaAttachment: nil,
|
||||||
error: nil))
|
error: nil)
|
||||||
|
prepareToPost(for: container)
|
||||||
} else if let gif = content as? GifFileTranseferable {
|
} else if let gif = content as? GifFileTranseferable {
|
||||||
mediasImages.append(.init(image: nil,
|
let container = StatusEditorMediaContainer(
|
||||||
|
id: UUID().uuidString,
|
||||||
|
image: nil,
|
||||||
movieTransferable: nil,
|
movieTransferable: nil,
|
||||||
gifTransferable: gif,
|
gifTransferable: gif,
|
||||||
mediaAttachment: nil,
|
mediaAttachment: nil,
|
||||||
error: nil))
|
error: nil)
|
||||||
|
prepareToPost(for: container)
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
isMediasLoading = false
|
isMediasLoading = false
|
||||||
|
@ -427,9 +455,6 @@ import SwiftUI
|
||||||
statusText = .init(string: initialText)
|
statusText = .init(string: initialText)
|
||||||
selectedRange = .init(location: statusText.string.utf16.count, length: 0)
|
selectedRange = .init(location: statusText.string.utf16.count, length: 0)
|
||||||
}
|
}
|
||||||
if !mediasImages.isEmpty {
|
|
||||||
processMediasToUpload()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -532,89 +557,107 @@ import SwiftUI
|
||||||
// MARK: - Media related function
|
// MARK: - Media related function
|
||||||
|
|
||||||
private func indexOf(container: StatusEditorMediaContainer) -> Int? {
|
private func indexOf(container: StatusEditorMediaContainer) -> Int? {
|
||||||
mediasImages.firstIndex(where: { $0.id == container.id })
|
mediaContainers.firstIndex(where: { $0.id == container.id })
|
||||||
}
|
}
|
||||||
|
|
||||||
func inflateSelectedMedias() {
|
func prepareToPost(for pickerItem: PhotosPickerItem) {
|
||||||
mediasImages = []
|
Task(priority: .high) {
|
||||||
|
if let container = await makeMediaContainer(from: pickerItem) {
|
||||||
Task {
|
self.mediaContainers.append(container)
|
||||||
var medias: [StatusEditorMediaContainer] = []
|
await upload(container: container)
|
||||||
for media in selectedMedias {
|
self.isMediasLoading = false
|
||||||
var file: (any Transferable)?
|
|
||||||
|
|
||||||
if file == nil {
|
|
||||||
file = try? await media.loadTransferable(type: GifFileTranseferable.self)
|
|
||||||
}
|
}
|
||||||
if file == nil {
|
|
||||||
file = try? await media.loadTransferable(type: MovieFileTranseferable.self)
|
|
||||||
}
|
}
|
||||||
if file == nil {
|
|
||||||
file = try? await media.loadTransferable(type: ImageFileTranseferable.self)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let compressor = StatusEditorCompressor()
|
func prepareToPost(for container: StatusEditorMediaContainer) {
|
||||||
if let imageFile = file as? ImageFileTranseferable,
|
Task(priority: .high) {
|
||||||
let compressedData = await compressor.compressImageFrom(url: imageFile.url),
|
self.mediaContainers.append(container)
|
||||||
let image = UIImage(data: compressedData)
|
await upload(container: container)
|
||||||
{
|
self.isMediasLoading = false
|
||||||
medias.append(.init(image: image,
|
}
|
||||||
movieTransferable: nil,
|
}
|
||||||
gifTransferable: nil,
|
|
||||||
mediaAttachment: nil,
|
func makeMediaContainer(from pickerItem: PhotosPickerItem) async -> StatusEditorMediaContainer? {
|
||||||
error: nil))
|
await withTaskGroup(of: StatusEditorMediaContainer?.self, returning: StatusEditorMediaContainer?.self) { taskGroup in
|
||||||
} else if let videoFile = file as? MovieFileTranseferable {
|
taskGroup.addTask(priority: .high) { await Self.makeImageContainer(from: pickerItem) }
|
||||||
medias.append(.init(image: nil,
|
taskGroup.addTask(priority: .high) { await Self.makeGifContainer(from: pickerItem) }
|
||||||
movieTransferable: videoFile,
|
taskGroup.addTask(priority: .high) { await Self.makeMovieContainer(from: pickerItem) }
|
||||||
gifTransferable: nil,
|
|
||||||
mediaAttachment: nil,
|
for await container in taskGroup {
|
||||||
error: nil))
|
if let container {
|
||||||
} else if let gifFile = file as? GifFileTranseferable {
|
taskGroup.cancelAll()
|
||||||
medias.append(.init(image: nil,
|
return container
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static func makeGifContainer(from pickerItem: PhotosPickerItem) async -> StatusEditorMediaContainer? {
|
||||||
|
guard let gifFile = try? await pickerItem.loadTransferable(type: GifFileTranseferable.self) else { return nil }
|
||||||
|
|
||||||
|
return StatusEditorMediaContainer(
|
||||||
|
id: pickerItem.itemIdentifier ?? UUID().uuidString,
|
||||||
|
image: nil,
|
||||||
movieTransferable: nil,
|
movieTransferable: nil,
|
||||||
gifTransferable: gifFile,
|
gifTransferable: gifFile,
|
||||||
mediaAttachment: nil,
|
mediaAttachment: nil,
|
||||||
error: nil))
|
error: nil)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DispatchQueue.main.async { [weak self] in
|
private static func makeMovieContainer(from pickerItem: PhotosPickerItem) async -> StatusEditorMediaContainer? {
|
||||||
self?.mediasImages = medias
|
guard let movieFile = try? await pickerItem.loadTransferable(type: MovieFileTranseferable.self) else { return nil }
|
||||||
self?.processMediasToUpload()
|
|
||||||
}
|
return StatusEditorMediaContainer(
|
||||||
}
|
id: pickerItem.itemIdentifier ?? UUID().uuidString,
|
||||||
|
image: nil,
|
||||||
|
movieTransferable: movieFile,
|
||||||
|
gifTransferable: nil,
|
||||||
|
mediaAttachment: nil,
|
||||||
|
error: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func processMediasToUpload() {
|
private static func makeImageContainer(from pickerItem: PhotosPickerItem) async -> StatusEditorMediaContainer? {
|
||||||
isMediasLoading = false
|
guard let imageFile = try? await pickerItem.loadTransferable(type: ImageFileTranseferable.self) else { return nil }
|
||||||
uploadTask?.cancel()
|
|
||||||
let mediasCopy = mediasImages
|
let compressor = StatusEditorCompressor()
|
||||||
uploadTask = Task {
|
|
||||||
for media in mediasCopy {
|
guard let compressedData = await compressor.compressImageFrom(url: imageFile.url),
|
||||||
if !Task.isCancelled {
|
let image = UIImage(data: compressedData)
|
||||||
await upload(container: media)
|
else { return nil }
|
||||||
}
|
|
||||||
}
|
return StatusEditorMediaContainer(
|
||||||
}
|
id: pickerItem.itemIdentifier ?? UUID().uuidString,
|
||||||
|
image: image,
|
||||||
|
movieTransferable: nil,
|
||||||
|
gifTransferable: nil,
|
||||||
|
mediaAttachment: nil,
|
||||||
|
error: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func upload(container: StatusEditorMediaContainer) async {
|
func upload(container: StatusEditorMediaContainer) async {
|
||||||
if let index = indexOf(container: container) {
|
if let index = indexOf(container: container) {
|
||||||
let originalContainer = mediasImages[index]
|
let originalContainer = mediaContainers[index]
|
||||||
guard originalContainer.mediaAttachment == nil else { return }
|
guard originalContainer.mediaAttachment == nil else { return }
|
||||||
let newContainer = StatusEditorMediaContainer(image: originalContainer.image,
|
let newContainer = StatusEditorMediaContainer(
|
||||||
|
id: originalContainer.id,
|
||||||
|
image: originalContainer.image,
|
||||||
movieTransferable: originalContainer.movieTransferable,
|
movieTransferable: originalContainer.movieTransferable,
|
||||||
gifTransferable: nil,
|
gifTransferable: nil,
|
||||||
mediaAttachment: nil,
|
mediaAttachment: nil,
|
||||||
error: nil)
|
error: nil)
|
||||||
mediasImages[index] = newContainer
|
mediaContainers[index] = newContainer
|
||||||
do {
|
do {
|
||||||
let compressor = StatusEditorCompressor()
|
let compressor = StatusEditorCompressor()
|
||||||
if let image = originalContainer.image {
|
if let image = originalContainer.image {
|
||||||
let imageData = try await compressor.compressImageForUpload(image)
|
let imageData = try await compressor.compressImageForUpload(image)
|
||||||
let uploadedMedia = try await uploadMedia(data: imageData, mimeType: "image/jpeg")
|
let uploadedMedia = try await uploadMedia(data: imageData, mimeType: "image/jpeg")
|
||||||
if let index = indexOf(container: newContainer) {
|
if let index = indexOf(container: newContainer) {
|
||||||
mediasImages[index] = .init(image: mode.isInShareExtension ? originalContainer.image : nil,
|
mediaContainers[index] = StatusEditorMediaContainer(
|
||||||
|
id: originalContainer.id,
|
||||||
|
image: mode.isInShareExtension ? originalContainer.image : nil,
|
||||||
movieTransferable: nil,
|
movieTransferable: nil,
|
||||||
gifTransferable: nil,
|
gifTransferable: nil,
|
||||||
mediaAttachment: uploadedMedia,
|
mediaAttachment: uploadedMedia,
|
||||||
|
@ -629,7 +672,9 @@ import SwiftUI
|
||||||
{
|
{
|
||||||
let uploadedMedia = try await uploadMedia(data: data, mimeType: compressedVideoURL.mimeType())
|
let uploadedMedia = try await uploadMedia(data: data, mimeType: compressedVideoURL.mimeType())
|
||||||
if let index = indexOf(container: newContainer) {
|
if let index = indexOf(container: newContainer) {
|
||||||
mediasImages[index] = .init(image: mode.isInShareExtension ? originalContainer.image : nil,
|
mediaContainers[index] = StatusEditorMediaContainer(
|
||||||
|
id: originalContainer.id,
|
||||||
|
image: mode.isInShareExtension ? originalContainer.image : nil,
|
||||||
movieTransferable: originalContainer.movieTransferable,
|
movieTransferable: originalContainer.movieTransferable,
|
||||||
gifTransferable: nil,
|
gifTransferable: nil,
|
||||||
mediaAttachment: uploadedMedia,
|
mediaAttachment: uploadedMedia,
|
||||||
|
@ -641,7 +686,9 @@ import SwiftUI
|
||||||
} else if let gifData = originalContainer.gifTransferable?.data {
|
} else if let gifData = originalContainer.gifTransferable?.data {
|
||||||
let uploadedMedia = try await uploadMedia(data: gifData, mimeType: "image/gif")
|
let uploadedMedia = try await uploadMedia(data: gifData, mimeType: "image/gif")
|
||||||
if let index = indexOf(container: newContainer) {
|
if let index = indexOf(container: newContainer) {
|
||||||
mediasImages[index] = .init(image: mode.isInShareExtension ? originalContainer.image : nil,
|
mediaContainers[index] = StatusEditorMediaContainer(
|
||||||
|
id: originalContainer.id,
|
||||||
|
image: mode.isInShareExtension ? originalContainer.image : nil,
|
||||||
movieTransferable: nil,
|
movieTransferable: nil,
|
||||||
gifTransferable: originalContainer.gifTransferable,
|
gifTransferable: originalContainer.gifTransferable,
|
||||||
mediaAttachment: uploadedMedia,
|
mediaAttachment: uploadedMedia,
|
||||||
|
@ -653,7 +700,9 @@ import SwiftUI
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
if let index = indexOf(container: newContainer) {
|
if let index = indexOf(container: newContainer) {
|
||||||
mediasImages[index] = .init(image: originalContainer.image,
|
mediaContainers[index] = StatusEditorMediaContainer(
|
||||||
|
id: originalContainer.id,
|
||||||
|
image: originalContainer.image,
|
||||||
movieTransferable: nil,
|
movieTransferable: nil,
|
||||||
gifTransferable: nil,
|
gifTransferable: nil,
|
||||||
mediaAttachment: nil,
|
mediaAttachment: nil,
|
||||||
|
@ -667,17 +716,19 @@ import SwiftUI
|
||||||
Task {
|
Task {
|
||||||
repeat {
|
repeat {
|
||||||
if let client,
|
if let client,
|
||||||
let index = mediasImages.firstIndex(where: { $0.mediaAttachment?.id == mediaAttachement.id })
|
let index = mediaContainers.firstIndex(where: { $0.mediaAttachment?.id == mediaAttachement.id })
|
||||||
{
|
{
|
||||||
guard mediasImages[index].mediaAttachment?.url == nil else {
|
guard mediaContainers[index].mediaAttachment?.url == nil else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
let newAttachement: MediaAttachment = try await client.get(endpoint: Media.media(id: mediaAttachement.id,
|
let newAttachement: MediaAttachment = try await client.get(endpoint: Media.media(id: mediaAttachement.id,
|
||||||
json: .init(description: nil)))
|
json: .init(description: nil)))
|
||||||
if newAttachement.url != nil {
|
if newAttachement.url != nil {
|
||||||
let oldContainer = mediasImages[index]
|
let oldContainer = mediaContainers[index]
|
||||||
mediasImages[index] = .init(image: oldContainer.image,
|
mediaContainers[index] = StatusEditorMediaContainer(
|
||||||
|
id: mediaAttachement.id,
|
||||||
|
image: oldContainer.image,
|
||||||
movieTransferable: oldContainer.movieTransferable,
|
movieTransferable: oldContainer.movieTransferable,
|
||||||
gifTransferable: oldContainer.gifTransferable,
|
gifTransferable: oldContainer.gifTransferable,
|
||||||
mediaAttachment: newAttachement,
|
mediaAttachment: newAttachement,
|
||||||
|
@ -696,7 +747,9 @@ import SwiftUI
|
||||||
do {
|
do {
|
||||||
let media: MediaAttachment = try await client.put(endpoint: Media.media(id: attachment.id,
|
let media: MediaAttachment = try await client.put(endpoint: Media.media(id: attachment.id,
|
||||||
json: .init(description: description)))
|
json: .init(description: description)))
|
||||||
mediasImages[index] = .init(image: nil,
|
mediaContainers[index] = StatusEditorMediaContainer(
|
||||||
|
id: container.id,
|
||||||
|
image: nil,
|
||||||
movieTransferable: nil,
|
movieTransferable: nil,
|
||||||
gifTransferable: nil,
|
gifTransferable: nil,
|
||||||
mediaAttachment: media,
|
mediaAttachment: media,
|
||||||
|
@ -785,3 +838,5 @@ extension StatusEditorViewModel: UITextPasteDelegate {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension PhotosPickerItem: @unchecked Sendable {}
|
||||||
|
|
Loading…
Reference in a new issue