Compare commits
1 Commits
profile-na
...
offline-tr
| Author | SHA1 | Date | |
|---|---|---|---|
|
e456ac864d
|
@@ -27,19 +27,26 @@ struct TranslateView: View {
|
|||||||
let damus_state: DamusState
|
let damus_state: DamusState
|
||||||
let event: NostrEvent
|
let event: NostrEvent
|
||||||
let size: EventViewKind
|
let size: EventViewKind
|
||||||
|
|
||||||
|
@Binding var isAppleTranslationPopoverPresented: Bool
|
||||||
|
|
||||||
@ObservedObject var translations_model: TranslationModel
|
@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.damus_state = damus_state
|
||||||
self.event = event
|
self.event = event
|
||||||
self.size = size
|
self.size = size
|
||||||
|
self._isAppleTranslationPopoverPresented = isAppleTranslationPopoverPresented
|
||||||
self._translations_model = ObservedObject(wrappedValue: damus_state.events.get_cache_data(event.id).translations_model)
|
self._translations_model = ObservedObject(wrappedValue: damus_state.events.get_cache_data(event.id).translations_model)
|
||||||
}
|
}
|
||||||
|
|
||||||
var TranslateButton: some View {
|
var TranslateButton: some View {
|
||||||
Button(NSLocalizedString("Translate Note", comment: "Button to translate note from different language.")) {
|
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()
|
.translate_button_style()
|
||||||
}
|
}
|
||||||
@@ -74,17 +81,25 @@ struct TranslateView: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func should_transl(_ note_lang: String) -> Bool {
|
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 {
|
var body: some View {
|
||||||
Group {
|
Group {
|
||||||
switch self.translations_model.state {
|
switch self.translations_model.state {
|
||||||
case .havent_tried:
|
case .havent_tried:
|
||||||
if damus_state.settings.auto_translate {
|
if damus_state.settings.auto_translate && damus_state.settings.translation_service != .none {
|
||||||
Text("")
|
Text("")
|
||||||
} else if let note_lang = translations_model.note_language, should_transl(note_lang) {
|
} else if let note_lang = translations_model.note_language, should_transl(note_lang) {
|
||||||
TranslateButton
|
TranslateButton
|
||||||
} else {
|
} else {
|
||||||
Text("")
|
Text("")
|
||||||
}
|
}
|
||||||
@@ -114,9 +129,11 @@ extension View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct TranslateView_Previews: PreviewProvider {
|
struct TranslateView_Previews: PreviewProvider {
|
||||||
|
@State static var isAppleTranslationPopoverPresented: Bool = false
|
||||||
|
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
let ds = test_damus_state
|
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,13 @@ enum TranslationService: String, CaseIterable, Identifiable, StringCodable {
|
|||||||
var model: Model {
|
var model: Model {
|
||||||
switch self {
|
switch self {
|
||||||
case .none:
|
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:
|
case .purple:
|
||||||
return .init(tag: self.rawValue, displayName: NSLocalizedString("Damus Purple", comment: "Dropdown option for selecting Damus Purple as a translation service."))
|
return .init(tag: self.rawValue, displayName: NSLocalizedString("Damus Purple", comment: "Dropdown option for selecting Damus Purple as a translation service."))
|
||||||
case .libretranslate:
|
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."))
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -244,16 +244,12 @@ class EventCache {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func should_translate(event: NostrEvent, our_keypair: Keypair, settings: UserSettingsStore, note_lang: String?) -> Bool {
|
func should_translate(event: NostrEvent, our_keypair: Keypair, note_lang: String?) -> Bool {
|
||||||
guard settings.can_translate else {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// don't translate reposts, longform, etc
|
// don't translate reposts, longform, etc
|
||||||
if event.kind != 1 {
|
if event.kind != 1 {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do not translate self-authored notes if logged in with a private key
|
// Do not translate self-authored notes if logged in with a private key
|
||||||
// as we can assume the user can understand their own notes.
|
// 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.
|
// 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 {
|
if our_keypair.privkey != nil && our_keypair.pubkey == event.pubkey {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if let note_lang {
|
if let note_lang {
|
||||||
let preferredLanguages = Set(Locale.preferredLanguages.map { localeToLanguage($0) })
|
let preferredLanguages = Set(Locale.preferredLanguages.map { localeToLanguage($0) })
|
||||||
|
|
||||||
// Don't translate if its in our preferred languages
|
// Don't translate if its in our preferred languages
|
||||||
guard !preferredLanguages.contains(note_lang) else {
|
guard !preferredLanguages.contains(note_lang) else {
|
||||||
// if its the same, give up and don't retry
|
// if its the same, give up and don't retry
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// we should start translating if we have auto_translate on
|
// we should start translating if we have auto_translate on
|
||||||
return true
|
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 {
|
func should_preload_translation(event: NostrEvent, our_keypair: Keypair, current_status: TranslateStatus, settings: UserSettingsStore, note_lang: String?) -> Bool {
|
||||||
switch current_status {
|
switch current_status {
|
||||||
case .havent_tried:
|
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 .translating: return false
|
||||||
case .translated: return false
|
case .translated: return false
|
||||||
case .not_needed: return false
|
case .not_needed: return false
|
||||||
@@ -413,7 +417,7 @@ func preload_event(plan: PreloadPlan, state: DamusState) async {
|
|||||||
|
|
||||||
var translations: TranslateStatus? = nil
|
var translations: TranslateStatus? = nil
|
||||||
// We have to recheck should_translate here now that we have note_language
|
// 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)
|
translations = await translate_note(profiles: profiles, keypair: our_keypair, event: plan.event, settings: settings, note_lang: note_language, purple: state.purple)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import SwiftUI
|
|||||||
import LinkPresentation
|
import LinkPresentation
|
||||||
import NaturalLanguage
|
import NaturalLanguage
|
||||||
import MarkdownUI
|
import MarkdownUI
|
||||||
|
import Translation
|
||||||
|
|
||||||
struct Blur: UIViewRepresentable {
|
struct Blur: UIViewRepresentable {
|
||||||
var style: UIBlurEffect.Style = .systemUltraThinMaterial
|
var style: UIBlurEffect.Style = .systemUltraThinMaterial
|
||||||
@@ -32,6 +33,8 @@ struct NoteContentView: View {
|
|||||||
let preview_height: CGFloat?
|
let preview_height: CGFloat?
|
||||||
let options: EventViewOptions
|
let options: EventViewOptions
|
||||||
|
|
||||||
|
@State var isAppleTranslationPopoverPresented: Bool = false
|
||||||
|
|
||||||
@ObservedObject var artifacts_model: NoteArtifactsModel
|
@ObservedObject var artifacts_model: NoteArtifactsModel
|
||||||
@ObservedObject var preview_model: PreviewModel
|
@ObservedObject var preview_model: PreviewModel
|
||||||
@ObservedObject var settings: UserSettingsStore
|
@ObservedObject var settings: UserSettingsStore
|
||||||
@@ -96,7 +99,7 @@ struct NoteContentView: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var translateView: some 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 {
|
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 {
|
if with_padding {
|
||||||
translateView
|
translateView
|
||||||
.padding(.horizontal)
|
.padding(.horizontal)
|
||||||
@@ -298,7 +301,12 @@ struct NoteContentView: View {
|
|||||||
Markdown(md.markdown)
|
Markdown(md.markdown)
|
||||||
.padding([.leading, .trailing, .top])
|
.padding([.leading, .trailing, .top])
|
||||||
case .separated(let separated):
|
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)
|
.fixedSize(horizontal: false, vertical: true)
|
||||||
|
|||||||
Reference in New Issue
Block a user