commit 2a19d5d831abaf6a9e6e45cfde837bbb3b7d877c
parent 51ee4046a0471369485c4f9838e1958d56245b7d
Author: Terry Yiu <git@tyiu.xyz>
Date: Fri, 21 Jun 2024 00:11:18 -0400
Add Apple translation popovers for notes for iOS 17.4+ and macOS 14.4+
Changelog-Added: Add Apple translation popovers for notes for iOS 17.4+ and macOS 14.4+
Diffstat:
4 files changed, 65 insertions(+), 22 deletions(-)
diff --git a/damus/Components/TranslateView.swift b/damus/Components/TranslateView.swift
@@ -27,19 +27,26 @@ struct TranslateView: View {
let damus_state: DamusState
let event: NostrEvent
let size: EventViewKind
-
+
+ @Binding var isAppleTranslationPopoverPresented: Bool
+
@ObservedObject var translations_model: TranslationModel
- init(damus_state: DamusState, event: NostrEvent, size: EventViewKind) {
+ init(damus_state: DamusState, event: NostrEvent, size: EventViewKind, isAppleTranslationPopoverPresented: Binding<Bool>) {
self.damus_state = damus_state
self.event = event
self.size = size
+ self._isAppleTranslationPopoverPresented = isAppleTranslationPopoverPresented
self._translations_model = ObservedObject(wrappedValue: damus_state.events.get_cache_data(event.id).translations_model)
}
var TranslateButton: some View {
Button(NSLocalizedString("Translate Note", comment: "Button to translate note from different language.")) {
- translate()
+ if damus_state.settings.translation_service == .none {
+ isAppleTranslationPopoverPresented = true
+ } else {
+ translate()
+ }
}
.translate_button_style()
}
@@ -74,17 +81,25 @@ struct TranslateView: View {
}
func should_transl(_ note_lang: String) -> Bool {
- should_translate(event: event, our_keypair: damus_state.keypair, settings: damus_state.settings, note_lang: note_lang)
+ guard should_translate(event: event, our_keypair: damus_state.keypair, note_lang: note_lang) else {
+ return false
+ }
+
+ if TranslationService.isAppleTranslationPopoverSupported {
+ return damus_state.settings.translation_service == .none || damus_state.settings.can_translate
+ } else {
+ return damus_state.settings.can_translate
+ }
}
var body: some View {
Group {
switch self.translations_model.state {
case .havent_tried:
- if damus_state.settings.auto_translate {
+ if damus_state.settings.auto_translate && damus_state.settings.translation_service != .none {
Text("")
} else if let note_lang = translations_model.note_language, should_transl(note_lang) {
- TranslateButton
+ TranslateButton
} else {
Text("")
}
@@ -114,9 +129,11 @@ extension View {
}
struct TranslateView_Previews: PreviewProvider {
+ @State static var isAppleTranslationPopoverPresented: Bool = false
+
static var previews: some View {
let ds = test_damus_state
- TranslateView(damus_state: ds, event: test_note, size: .normal)
+ TranslateView(damus_state: ds, event: test_note, size: .normal, isAppleTranslationPopoverPresented: $isAppleTranslationPopoverPresented)
}
}
diff --git a/damus/Models/TranslationService.swift b/damus/Models/TranslationService.swift
@@ -38,7 +38,13 @@ enum TranslationService: String, CaseIterable, Identifiable, StringCodable {
var model: Model {
switch self {
case .none:
- return .init(tag: self.rawValue, displayName: NSLocalizedString("none_translation_service", value: "None", comment: "Dropdown option for selecting no translation service."))
+ let displayName: String
+ if TranslationService.isAppleTranslationPopoverSupported {
+ displayName = NSLocalizedString("apple_translation_service", value: "Apple", comment: "Dropdown option for selecting Apple as a translation service.")
+ } else {
+ displayName = NSLocalizedString("none_translation_service", value: "None", comment: "Dropdown option for selecting no translation service.")
+ }
+ return .init(tag: self.rawValue, displayName: displayName)
case .purple:
return .init(tag: self.rawValue, displayName: NSLocalizedString("Damus Purple", comment: "Dropdown option for selecting Damus Purple as a translation service."))
case .libretranslate:
@@ -51,4 +57,12 @@ enum TranslationService: String, CaseIterable, Identifiable, StringCodable {
return .init(tag: self.rawValue, displayName: NSLocalizedString("translate.nostr.wine (DeepL, Pay with BTC)", comment: "Dropdown option for selecting translate.nostr.wine as the translation service."))
}
}
+
+ static var isAppleTranslationPopoverSupported: Bool {
+ if #available(iOS 17.4, macOS 14.4, *) {
+ return true
+ } else {
+ return false
+ }
+ }
}
diff --git a/damus/Util/EventCache.swift b/damus/Util/EventCache.swift
@@ -244,16 +244,12 @@ class EventCache {
}
}
-func should_translate(event: NostrEvent, our_keypair: Keypair, settings: UserSettingsStore, note_lang: String?) -> Bool {
- guard settings.can_translate else {
- return false
- }
-
+func should_translate(event: NostrEvent, our_keypair: Keypair, note_lang: String?) -> Bool {
// don't translate reposts, longform, etc
if event.kind != 1 {
return false;
}
-
+
// Do not translate self-authored notes if logged in with a private key
// as we can assume the user can understand their own notes.
// The detected language prediction could be incorrect and not in the list of preferred languages.
@@ -261,25 +257,33 @@ func should_translate(event: NostrEvent, our_keypair: Keypair, settings: UserSet
if our_keypair.privkey != nil && our_keypair.pubkey == event.pubkey {
return false
}
-
+
if let note_lang {
let preferredLanguages = Set(Locale.preferredLanguages.map { localeToLanguage($0) })
-
+
// Don't translate if its in our preferred languages
guard !preferredLanguages.contains(note_lang) else {
// if its the same, give up and don't retry
return false
}
}
-
+
// we should start translating if we have auto_translate on
return true
}
+func can_and_should_translate(event: NostrEvent, our_keypair: Keypair, settings: UserSettingsStore, note_lang: String?) -> Bool {
+ guard settings.can_translate else {
+ return false
+ }
+
+ return should_translate(event: event, our_keypair: our_keypair, note_lang: note_lang)
+}
+
func should_preload_translation(event: NostrEvent, our_keypair: Keypair, current_status: TranslateStatus, settings: UserSettingsStore, note_lang: String?) -> Bool {
switch current_status {
case .havent_tried:
- return should_translate(event: event, our_keypair: our_keypair, settings: settings, note_lang: note_lang) && settings.auto_translate
+ return can_and_should_translate(event: event, our_keypair: our_keypair, settings: settings, note_lang: note_lang) && settings.auto_translate
case .translating: return false
case .translated: return false
case .not_needed: return false
@@ -413,7 +417,7 @@ func preload_event(plan: PreloadPlan, state: DamusState) async {
var translations: TranslateStatus? = nil
// We have to recheck should_translate here now that we have note_language
- if plan.load_translations && should_translate(event: plan.event, our_keypair: our_keypair, settings: settings, note_lang: note_language) && settings.auto_translate
+ if plan.load_translations && can_and_should_translate(event: plan.event, our_keypair: our_keypair, settings: settings, note_lang: note_language) && settings.auto_translate
{
translations = await translate_note(profiles: profiles, keypair: our_keypair, event: plan.event, settings: settings, note_lang: note_language, purple: state.purple)
}
diff --git a/damus/Views/NoteContentView.swift b/damus/Views/NoteContentView.swift
@@ -9,6 +9,7 @@ import SwiftUI
import LinkPresentation
import NaturalLanguage
import MarkdownUI
+import Translation
struct Blur: UIViewRepresentable {
var style: UIBlurEffect.Style = .systemUltraThinMaterial
@@ -32,6 +33,8 @@ struct NoteContentView: View {
let preview_height: CGFloat?
let options: EventViewOptions
+ @State var isAppleTranslationPopoverPresented: Bool = false
+
@ObservedObject var artifacts_model: NoteArtifactsModel
@ObservedObject var preview_model: PreviewModel
@ObservedObject var settings: UserSettingsStore
@@ -96,7 +99,7 @@ struct NoteContentView: View {
}
var translateView: some View {
- TranslateView(damus_state: damus_state, event: event, size: self.size)
+ TranslateView(damus_state: damus_state, event: event, size: self.size, isAppleTranslationPopoverPresented: $isAppleTranslationPopoverPresented)
}
func previewView(links: [URL]) -> some View {
@@ -145,7 +148,7 @@ struct NoteContentView: View {
}
}
- if !options.contains(.no_translate) && (size == .selected || damus_state.settings.auto_translate) {
+ if !options.contains(.no_translate) && (size == .selected || TranslationService.isAppleTranslationPopoverSupported || damus_state.settings.auto_translate) {
if with_padding {
translateView
.padding(.horizontal)
@@ -298,7 +301,12 @@ struct NoteContentView: View {
Markdown(md.markdown)
.padding([.leading, .trailing, .top])
case .separated(let separated):
- MainContent(artifacts: separated)
+ if #available(iOS 17.4, macOS 14.4, *) {
+ MainContent(artifacts: separated)
+ .translationPresentation(isPresented: $isAppleTranslationPopoverPresented, text: event.get_content(damus_state.keypair))
+ } else {
+ MainContent(artifacts: separated)
+ }
}
}
.fixedSize(horizontal: false, vertical: true)