Compare commits

...

1 Commits

Author SHA1 Message Date
e456ac864d 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+
2024-09-22 00:38:15 -04:00
4 changed files with 65 additions and 22 deletions

View File

@@ -28,18 +28,25 @@ struct TranslateView: View {
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)
}
}

View File

@@ -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
}
}
}

View File

@@ -244,11 +244,7 @@ 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;
@@ -276,10 +272,18 @@ func should_translate(event: NostrEvent, our_keypair: Keypair, settings: UserSet
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)
}

View File

@@ -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)