feat(ai): unify reply center and refresh keyboard AI features

- Merge invitation, task, blessing, clarification, and empathy actions
  into a single Reply flow, with three fixed, clearly labeled stance
  choices whenever user intent must not be guessed.
- Refine clipboard semantic routing with bilingual schedule,
  confirmation, and follow-up models, conservative language thresholds,
  and explicit-assignment guard for complaint-only text.
- Persist Apple account refresh state, harden session recovery, and
  surface durable account diagnostics across keyboard and app.
- Derive personal-style prompts through two-stage corpus evidence and
  apply real low-confidence ASR tendencies instead of neutral templates.
- Localize the new reply center, clipboard semantics, and personal-style
  surfaces in both English and Simplified Chinese.
This commit is contained in:
Rocky
2026-08-29 11:51:21 +08:00
parent f91a8f2456
commit 3c10d73d7f
30 changed files with 2090 additions and 447 deletions
+26 -9
View File
@@ -6,6 +6,11 @@
import SwiftUI
private struct MacPolishStyleErrorAlert {
let title: String
let message: String
}
struct MacPolishStylesView: View {
@ObservedObject var viewModel: MacDictationViewModel
@ObservedObject private var history = SpeechHistoryStore.shared
@@ -13,7 +18,7 @@ struct MacPolishStylesView: View {
@State private var editingPack: PolishStylePack?
@State private var viewingPack: PolishStylePack?
@State private var errorMessage: String?
@State private var errorAlert: MacPolishStyleErrorAlert?
@State private var isGeneratingLearnedStyle = false
private var lang: AppUILanguage { viewModel.config.uiLanguage }
@@ -95,15 +100,15 @@ struct MacPolishStylesView: View {
MacPolishStylePromptDetailSheet(pack: pack, language: lang)
}
.alert(
MacL10n.string("mac.styles.error", language: lang),
errorAlert?.title ?? "",
isPresented: Binding(
get: { errorMessage != nil },
set: { if !$0 { errorMessage = nil } }
get: { errorAlert != nil },
set: { if !$0 { errorAlert = nil } }
)
) {
Button(MacL10n.string("mac.done", language: lang)) { errorMessage = nil }
Button(MacL10n.string("mac.done", language: lang)) { errorAlert = nil }
} message: {
Text(errorMessage ?? "")
Text(errorAlert?.message ?? "")
}
.task {
await MacICloudSyncBootstrap.polishStyleSync.pullAndMergeIfEnabled()
@@ -276,7 +281,13 @@ struct MacPolishStylesView: View {
// becomes the active dictation personality.
editingPack = generated
} catch {
errorMessage = localizedLearningError(error)
errorAlert = MacPolishStyleErrorAlert(
title: MacL10n.string(
"mac.styles.learn.error.title",
language: lang
),
message: localizedLearningError(error)
)
}
}
}
@@ -292,7 +303,10 @@ struct MacPolishStylesView: View {
case .requestTooLarge:
return MacL10n.string("mac.styles.learn.error.requestTooLarge", language: lang)
case nil:
return MacL10n.string("mac.styles.learn.error.request", language: lang)
return PolishStyleLearningFailureMessage.localized(
for: error,
language: lang
) ?? MacL10n.string("mac.styles.learn.error.request", language: lang)
}
}
@@ -323,7 +337,10 @@ struct MacPolishStylesView: View {
try? await MacICloudSyncBootstrap.settingsSync.pushLocalIfEnabled()
}
} catch {
errorMessage = MacL10n.string("mac.styles.validation", language: lang)
errorAlert = MacPolishStyleErrorAlert(
title: MacL10n.string("mac.styles.error", language: lang),
message: MacL10n.string("mac.styles.validation", language: lang)
)
}
}