diff --git a/IceCubesAppWidgetsExtension/MentionWidget/MentionWidget.swift b/IceCubesAppWidgetsExtension/MentionWidget/MentionWidget.swift index 8612cbec..a3d2616b 100644 --- a/IceCubesAppWidgetsExtension/MentionWidget/MentionWidget.swift +++ b/IceCubesAppWidgetsExtension/MentionWidget/MentionWidget.swift @@ -33,7 +33,7 @@ struct MentionsWidgetProvider: AppIntentTimelineProvider { oauthToken: configuration.account.account.oauthToken) var excludedTypes = Models.Notification.NotificationType.allCases excludedTypes.removeAll(where: { $0 == .mention }) - var notifications: [Models.Notification] = + let notifications: [Models.Notification] = try await client.get(endpoint: Notifications.notifications(minId: nil, maxId: nil, types: excludedTypes.map(\.rawValue), diff --git a/Packages/Account/Sources/Account/AccountDetailContextMenu.swift b/Packages/Account/Sources/Account/AccountDetailContextMenu.swift index cba82d4f..d4fdd01b 100644 --- a/Packages/Account/Sources/Account/AccountDetailContextMenu.swift +++ b/Packages/Account/Sources/Account/AccountDetailContextMenu.swift @@ -9,6 +9,7 @@ public struct AccountDetailContextMenu: View { @Environment(UserPreferences.self) private var preferences @Binding var showBlockConfirmation: Bool + @Binding var showTranslateView: Bool var viewModel: AccountDetailViewModel @@ -136,15 +137,15 @@ public struct AccountDetailContextMenu: View { #endif } - if let lang = preferences.serverPreferences?.postLanguage ?? Locale.current.language.languageCode?.identifier { - Button { - Task { - await viewModel.translate(userLang: lang) + #if canImport(_Translation_SwiftUI) + if #available(iOS 17.4, *) { + Button { + showTranslateView = true + } label: { + Label("status.action.translate", systemImage: "captions.bubble") + } } - } label: { - Label("status.action.translate", systemImage: "captions.bubble") - } - } + #endif if viewModel.relationship?.following == true { Button { diff --git a/Packages/Account/Sources/Account/AccountDetailView.swift b/Packages/Account/Sources/Account/AccountDetailView.swift index 1669e90b..0ed1bc69 100644 --- a/Packages/Account/Sources/Account/AccountDetailView.swift +++ b/Packages/Account/Sources/Account/AccountDetailView.swift @@ -24,6 +24,7 @@ public struct AccountDetailView: View { @State private var isCurrentUser: Bool = false @State private var showBlockConfirmation: Bool = false @State private var isEditingRelationshipNote: Bool = false + @State private var showTranslateView: Bool = false @State private var displayTitle: Bool = false @@ -285,7 +286,9 @@ public struct AccountDetailView: View { } Menu { - AccountDetailContextMenu(showBlockConfirmation: $showBlockConfirmation, viewModel: viewModel) + AccountDetailContextMenu(showBlockConfirmation: $showBlockConfirmation, + showTranslateView: $showTranslateView, + viewModel: viewModel) if !viewModel.isCurrentUser { Button { @@ -380,6 +383,9 @@ public struct AccountDetailView: View { } message: { Text("account.action.block-user-confirmation") } + #if canImport(_Translation_SwiftUI) + .addTranslateView(isPresented: $showTranslateView, text: viewModel.account?.note.asRawText ?? "") + #endif } } } diff --git a/Packages/Account/Sources/Account/AccountDetailViewModel.swift b/Packages/Account/Sources/Account/AccountDetailViewModel.swift index d5bb7b08..80d2270d 100644 --- a/Packages/Account/Sources/Account/AccountDetailViewModel.swift +++ b/Packages/Account/Sources/Account/AccountDetailViewModel.swift @@ -273,22 +273,4 @@ import SwiftUI func statusDidAppear(status _: Models.Status) {} func statusDidDisappear(status _: Status) {} - - func translate(userLang: String) async { - guard let account else { return } - withAnimation { - isLoadingTranslation = true - } - - let userAPIKey = DeepLUserAPIHandler.readKeyIfAllowed() - let userAPIFree = UserPreferences.shared.userDeeplAPIFree - let deeplClient = DeepLClient(userAPIKey: userAPIKey, userAPIFree: userAPIFree) - - let translation = try? await deeplClient.request(target: userLang, text: account.note.asRawText) - - withAnimation { - self.translation = translation - isLoadingTranslation = false - } - } } diff --git a/Packages/Account/Sources/Account/AccountsList/AccountsListRow.swift b/Packages/Account/Sources/Account/AccountsList/AccountsListRow.swift index e37096ed..ce124b49 100644 --- a/Packages/Account/Sources/Account/AccountsList/AccountsListRow.swift +++ b/Packages/Account/Sources/Account/AccountsList/AccountsListRow.swift @@ -32,6 +32,7 @@ public struct AccountsListRow: View { @State private var isEditingRelationshipNote: Bool = false @State private var showBlockConfirmation: Bool = false + @State private var showTranslateView: Bool = false let isFollowRequest: Bool let requestUpdated: (() -> Void)? @@ -108,8 +109,13 @@ public struct AccountsListRow: View { .onTapGesture { routerPath.navigate(to: .accountDetailWithAccount(account: viewModel.account)) } + #if canImport(_Translation_SwiftUI) + .addTranslateView(isPresented: $showTranslateView, text: viewModel.account.note.asRawText) + #endif .contextMenu { - AccountDetailContextMenu(showBlockConfirmation: $showBlockConfirmation, viewModel: .init(account: viewModel.account)) + AccountDetailContextMenu(showBlockConfirmation: $showBlockConfirmation, + showTranslateView: $showTranslateView, + viewModel: .init(account: viewModel.account)) } preview: { List { AccountDetailHeaderView(viewModel: .init(account: viewModel.account), diff --git a/Packages/Env/Sources/Env/Ext/TranslationView.swift b/Packages/Env/Sources/Env/Ext/TranslationView.swift new file mode 100644 index 00000000..1f629f92 --- /dev/null +++ b/Packages/Env/Sources/Env/Ext/TranslationView.swift @@ -0,0 +1,15 @@ +import SwiftUI + +#if canImport(_Translation_SwiftUI) + import Translation + + extension View { + public func addTranslateView(isPresented: Binding, text: String) -> some View { + if #available(iOS 17.4, *) { + return self.translationPresentation(isPresented: isPresented, text: text) + } else { + return self + } + } + } +#endif diff --git a/Packages/StatusKit/Sources/StatusKit/Editor/Components/MediaEditView.swift b/Packages/StatusKit/Sources/StatusKit/Editor/Components/MediaEditView.swift index fabb3179..72d4bbf4 100644 --- a/Packages/StatusKit/Sources/StatusKit/Editor/Components/MediaEditView.swift +++ b/Packages/StatusKit/Sources/StatusKit/Editor/Components/MediaEditView.swift @@ -24,6 +24,7 @@ extension StatusEditor { @State private var isGeneratingDescription: Bool = false @State private var showTranslateButton: Bool = false + @State private var showTranslateView: Bool = false @State private var isTranslating: Bool = false var body: some View { @@ -111,12 +112,14 @@ extension StatusEditor { Task { if let description = await generateDescription(url: url) { imageDescription = description + #if canImport(_Translation_SwiftUI) let lang = preferences.serverPreferences?.postLanguage ?? Locale.current.language.languageCode?.identifier - if lang != nil, lang != "en" { + if #available(iOS 17.4, *), lang != nil, lang != "en", DeepLUserAPIHandler.readKey().isEmpty == false { withAnimation { showTranslateButton = true } } + #endif } } } label: { @@ -133,14 +136,7 @@ extension StatusEditor { private var translateButton: some View { if showTranslateButton { Button { - Task { - if let description = await translateDescription() { - imageDescription = description - withAnimation { - showTranslateButton = false - } - } - } + showTranslateView = true } label: { if isTranslating { ProgressView() @@ -148,6 +144,9 @@ extension StatusEditor { Text("status.action.translate") } } + #if canImport(_Translation_SwiftUI) + .addTranslateView(isPresented: $showTranslateView, text: imageDescription) + #endif } } @@ -158,17 +157,5 @@ extension StatusEditor { isGeneratingDescription = false return response?.trimmedText } - - private func translateDescription() async -> String? { - isTranslating = true - let userAPIKey = DeepLUserAPIHandler.readKeyIfAllowed() - let userAPIFree = UserPreferences.shared.userDeeplAPIFree - let deeplClient = DeepLClient(userAPIKey: userAPIKey, userAPIFree: userAPIFree) - let lang = preferences.serverPreferences?.postLanguage ?? Locale.current.language.languageCode?.identifier - guard let lang else { return nil } - let translation = try? await deeplClient.request(target: lang, text: imageDescription) - isTranslating = false - return translation?.content.asRawText - } } } diff --git a/Packages/StatusKit/Sources/StatusKit/Row/StatusRowView.swift b/Packages/StatusKit/Sources/StatusKit/Row/StatusRowView.swift index 056aae63..3b69548b 100644 --- a/Packages/StatusKit/Sources/StatusKit/Row/StatusRowView.swift +++ b/Packages/StatusKit/Sources/StatusKit/Row/StatusRowView.swift @@ -5,19 +5,6 @@ import Foundation import Models import Network import SwiftUI -#if canImport(_Translation_SwiftUI) - import Translation - - extension View { - func addTranslateView(isPresented: Binding, text: String) -> some View { - if #available(iOS 17.4, *) { - return self.translationPresentation(isPresented: isPresented, text: text) - } else { - return self - } - } - } -#endif @MainActor public struct StatusRowView: View {