diff --git a/MastodonSDK/Sources/MastodonUI/Extension/View.swift b/MastodonSDK/Sources/MastodonUI/Extension/View.swift new file mode 100644 index 000000000..756e51b64 --- /dev/null +++ b/MastodonSDK/Sources/MastodonUI/Extension/View.swift @@ -0,0 +1,21 @@ +// +// View.swift +// +// +// Created by MainasuK on 2022/11/8. +// + +import SwiftUI + +extension View { + public func badgeView(_ content: Content) -> some View where Content: View { + overlay( + ZStack { + content + } + .alignmentGuide(.top) { $0.height / 2 } + .alignmentGuide(.trailing) { $0.width / 2 } + .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topTrailing) + ) + } +} diff --git a/MastodonSDK/Sources/MastodonUI/Scene/ComposeContent/Attachment/AttachmentView.swift b/MastodonSDK/Sources/MastodonUI/Scene/ComposeContent/Attachment/AttachmentView.swift index f4d1397a9..f67745849 100644 --- a/MastodonSDK/Sources/MastodonUI/Scene/ComposeContent/Attachment/AttachmentView.swift +++ b/MastodonSDK/Sources/MastodonUI/Scene/ComposeContent/Attachment/AttachmentView.swift @@ -13,18 +13,17 @@ import AVKit public struct AttachmentView: View { - static let size = CGSize(width: 56, height: 56) - static let cornerRadius: CGFloat = 8 - @ObservedObject var viewModel: AttachmentViewModel let action: (Action) -> Void - - @State var isCaptionEditorPresented = false - @State var caption = "" public var body: some View { - Text("Hello") + ZStack { + let image = viewModel.thumbnail ?? .placeholder(color: .secondarySystemFill) + Image(uiImage: image) + .resizable() + .aspectRatio(contentMode: .fill) + } // Menu { // menu // } label: { diff --git a/MastodonSDK/Sources/MastodonUI/Scene/ComposeContent/Attachment/AttachmentViewModel.swift b/MastodonSDK/Sources/MastodonUI/Scene/ComposeContent/Attachment/AttachmentViewModel.swift index 7d0e8c859..f2c7e76e7 100644 --- a/MastodonSDK/Sources/MastodonUI/Scene/ComposeContent/Attachment/AttachmentViewModel.swift +++ b/MastodonSDK/Sources/MastodonUI/Scene/ComposeContent/Attachment/AttachmentViewModel.swift @@ -22,6 +22,7 @@ final public class AttachmentViewModel: NSObject, ObservableObject, Identifiable var observations = Set() // input + public let authContext: AuthContext public let input: Input @Published var caption = "" @Published var sizeLimit = SizeLimit() @@ -33,13 +34,19 @@ final public class AttachmentViewModel: NSObject, ObservableObject, Identifiable @Published var error: Error? let progress = Progress() // upload progress - public init(input: Input) { + public init( + authContext: AuthContext, + input: Input + ) { + self.authContext = authContext self.input = input super.init() // end init defer { - load(input: input) + Task { + await load(input: input) + } } $output @@ -53,6 +60,7 @@ final public class AttachmentViewModel: NSObject, ObservableObject, Identifiable return nil } } + .receive(on: DispatchQueue.main) .assign(to: &$thumbnail) } @@ -86,13 +94,6 @@ extension AttachmentViewModel { case png case jpg } - - public var twitterMediaCategory: TwitterMediaCategory { - switch self { - case .image: return .image - case .video: return .amplifyVideo - } - } } public struct SizeLimit { @@ -115,18 +116,13 @@ extension AttachmentViewModel { case invalidAttachmentType case attachmentTooLarge } - - public enum TwitterMediaCategory: String { - case image = "TWEET_IMAGE" - case GIF = "TWEET_GIF" - case video = "TWEET_VIDEO" - case amplifyVideo = "AMPLIFY_VIDEO" - } + } extension AttachmentViewModel { - private func load(input: Input) { + @MainActor + private func load(input: Input) async { switch input { case .image(let image): guard let data = image.pngData() else { @@ -135,32 +131,26 @@ extension AttachmentViewModel { } output = .image(data, imageKind: .png) case .url(let url): - Task { @MainActor in - do { - let output = try await AttachmentViewModel.load(url: url) - self.output = output - } catch { - self.error = error - } - } // end Task + do { + let output = try await AttachmentViewModel.load(url: url) + self.output = output + } catch { + self.error = error + } case .pickerResult(let pickerResult): - Task { @MainActor in - do { - let output = try await AttachmentViewModel.load(itemProvider: pickerResult.itemProvider) - self.output = output - } catch { - self.error = error - } - } // end Task + do { + let output = try await AttachmentViewModel.load(itemProvider: pickerResult.itemProvider) + self.output = output + } catch { + self.error = error + } case .itemProvider(let itemProvider): - Task { @MainActor in - do { - let output = try await AttachmentViewModel.load(itemProvider: itemProvider) - self.output = output - } catch { - self.error = error - } - } // end Task + do { + let output = try await AttachmentViewModel.load(itemProvider: itemProvider) + self.output = output + } catch { + self.error = error + } } } diff --git a/MastodonSDK/Sources/MastodonUI/Scene/ComposeContent/ComposeContentViewController.swift b/MastodonSDK/Sources/MastodonUI/Scene/ComposeContent/ComposeContentViewController.swift index 3417ed935..38efe8feb 100644 --- a/MastodonSDK/Sources/MastodonUI/Scene/ComposeContent/ComposeContentViewController.swift +++ b/MastodonSDK/Sources/MastodonUI/Scene/ComposeContent/ComposeContentViewController.swift @@ -325,16 +325,10 @@ extension ComposeContentViewController: PHPickerViewControllerDelegate { public func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) { picker.dismiss(animated: true, completion: nil) - // TODO: -// let attachmentServices: [MastodonAttachmentService] = results.map { result in -// let service = MastodonAttachmentService( -// context: context, -// pickerResult: result, -// initialAuthenticationBox: viewModel.authenticationBox -// ) -// return service -// } -// viewModel.attachmentServices = viewModel.attachmentServices + attachmentServices + let attachmentViewModels: [AttachmentViewModel] = results.map { result in + AttachmentViewModel(authContext: viewModel.authContext, input: .pickerResult(result)) + } + viewModel.attachmentViewModels += attachmentViewModels } } diff --git a/MastodonSDK/Sources/MastodonUI/Scene/ComposeContent/View/ComposeContentView.swift b/MastodonSDK/Sources/MastodonUI/Scene/ComposeContent/View/ComposeContentView.swift index 25584848a..ffc92c01e 100644 --- a/MastodonSDK/Sources/MastodonUI/Scene/ComposeContent/View/ComposeContentView.swift +++ b/MastodonSDK/Sources/MastodonUI/Scene/ComposeContent/View/ComposeContentView.swift @@ -11,6 +11,7 @@ import MastodonAsset import MastodonCore import MastodonLocalization import Stripes +import Kingfisher public struct ComposeContentView: View { @@ -108,6 +109,9 @@ public struct ComposeContentView: View { // poll pollView .padding(.horizontal, ComposeContentView.margin) + // media + mediaView + .padding(.horizontal, ComposeContentView.margin) } .background( GeometryReader { proxy in @@ -194,6 +198,29 @@ extension ComposeContentView { } } // end VStack } + + // MARK: - media + var mediaView: some View { + VStack(spacing: 16) { + ForEach(viewModel.attachmentViewModels, id: \.self) { attachmentViewModel in + Color.clear.aspectRatio(358.0/232.0, contentMode: .fill) + .overlay( + AttachmentView(viewModel: attachmentViewModel) { action in + + } + ) + .clipShape(Rectangle()) + .badgeView( + Button { + viewModel.attachmentViewModels.removeAll(where: { $0 === attachmentViewModel }) + } label: { + Image(systemName: "minus.circle.fill") + .foregroundColor(.red) + } + ) + } // end ForEach + } // end VStack + } } //private struct ScrollOffsetPreferenceKey: PreferenceKey { diff --git a/ShareActionExtension/Scene/View/StatusAttachmentView.swift b/ShareActionExtension/Scene/View/StatusAttachmentView.swift index 90b8aceeb..8540b95f1 100644 --- a/ShareActionExtension/Scene/View/StatusAttachmentView.swift +++ b/ShareActionExtension/Scene/View/StatusAttachmentView.swift @@ -77,19 +77,6 @@ struct StatusAttachmentView: View { } } -extension View { - func badgeView(_ content: Content) -> some View where Content: View { - overlay( - ZStack { - content - } - .alignmentGuide(.top) { $0.height / 2 } - .alignmentGuide(.trailing) { $0.width / 2 } - .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topTrailing) - ) - } -} - /// ref: https://stackoverflow.com/a/57715771/3797903 extension View { func placeholder(