Merge branch 'feature/intelligent-polish-and-personal-dict' into main
Resolved real conflicts introduced by translation-polish-2 (#3) and docs refresh (#4) being merged to main during development: - OSGKeyboardShared/Models/ProviderConfig.swift Add polishIntensity field alongside translationTargetLocaleId / polishScenarioId / handednessPreference. Both new fields coexist. - OSGKeyboardShared/Services/AppGroupStore.swift Keep main's translation setters; add polishIntensity setter, detectedAppContext setter, and personalDictionary getter/setter. - OSGKeyboardShared/Services/PolishingService.swift Merge v0.2.1 translate-and-polish path with v0.3.0 context-aware intelligent prompt. New polish() entry point accepts both modes; translation mode still uses TranslationPrompt, polish mode now uses buildPrompt(for:context:). - OSGKeyboard/Views/SettingsView.swift Compose localEngineSettingsSection (main) with polishIntensitySection, languageAndModelsSection, systemPromptLinkSection, personalDictionaryLinkSection (feature). - OSGKeyboardShared/{en,zh-Hans}.lproj/Shared.strings Concat scenario keys + polish intensity / app context / dictionary keys. Auto-merged without conflict: - AppGroupStore new methods (localASRBackend, etc.) - FlowSessionManager, KeyboardViewController (auto-merged) - MaterialIcon, HistoryView (auto-merged, my icons added on top) Co-authored-by: Mavis <Mavis@hkgood.dev>
This commit is contained in:
@@ -74,9 +74,15 @@ struct SettingsView: View {
|
||||
providerSection
|
||||
apiSection
|
||||
}
|
||||
languageAndModelsSection
|
||||
polishIntensitySection
|
||||
if config.engineMode == "cloud" {
|
||||
systemPromptLinkSection
|
||||
}
|
||||
if config.engineMode == "local" {
|
||||
localEngineSettingsSection
|
||||
}
|
||||
personalDictionaryLinkSection
|
||||
if presentation == .tab {
|
||||
preferencesSection
|
||||
footerLinks
|
||||
@@ -275,6 +281,76 @@ struct SettingsView: View {
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Polish intensity (v0.3.0)
|
||||
|
||||
private var polishIntensitySection: some View {
|
||||
VStack(alignment: .leading, spacing: SettingsListMetrics.sectionLabelSpacing) {
|
||||
sectionHeader("settings.polishIntensity.title")
|
||||
VStack(spacing: 0) {
|
||||
Picker("", selection: $config.polishIntensity) {
|
||||
ForEach(PolishIntensity.allCases, id: \.self) { intensity in
|
||||
Text(LocalizedStringKey(intensity.labelKey))
|
||||
.tag(intensity)
|
||||
}
|
||||
}
|
||||
.pickerStyle(.segmented)
|
||||
.padding(.horizontal, Spacing.md)
|
||||
.padding(.vertical, Spacing.sm)
|
||||
|
||||
Text(LocalizedStringKey(config.polishIntensity.descriptionKey))
|
||||
.font(TypeStyle.caption2)
|
||||
.foregroundStyle(palette.textSecondary)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.padding(.horizontal, Spacing.md)
|
||||
.padding(.bottom, Spacing.sm)
|
||||
}
|
||||
.background(palette.surface, in: RoundedRectangle(cornerRadius: Radius.large, style: .continuous))
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: Radius.large, style: .continuous)
|
||||
.stroke(palette.divider, lineWidth: 0.5)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Personal dictionary (v0.3.0)
|
||||
|
||||
private var personalDictionaryLinkSection: some View {
|
||||
VStack(alignment: .leading, spacing: SettingsListMetrics.sectionLabelSpacing) {
|
||||
sectionHeader("settings.personalDictionary.sectionTitle")
|
||||
VStack(spacing: 0) {
|
||||
NavigationLink {
|
||||
PersonalDictionaryView()
|
||||
} label: {
|
||||
HStack(spacing: Spacing.sm) {
|
||||
MaterialIcon(name: .bookmark, size: 18)
|
||||
.foregroundStyle(palette.accent)
|
||||
VStack(alignment: .leading, spacing: 2) {
|
||||
Text("settings.personalDictionary.title")
|
||||
.font(TypeStyle.body)
|
||||
.foregroundStyle(palette.textPrimary)
|
||||
Text("settings.personalDictionary.summary")
|
||||
.font(TypeStyle.caption2)
|
||||
.foregroundStyle(palette.textSecondary)
|
||||
}
|
||||
Spacer()
|
||||
Image(systemName: "chevron.right")
|
||||
.font(.system(size: 14, weight: .semibold))
|
||||
.foregroundStyle(palette.textTertiary)
|
||||
}
|
||||
.padding(.horizontal, Spacing.md)
|
||||
.frame(minHeight: SettingsListMetrics.singleLineMinHeight)
|
||||
.contentShape(Rectangle())
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
}
|
||||
.background(palette.surface, in: RoundedRectangle(cornerRadius: Radius.large, style: .continuous))
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: Radius.large, style: .continuous)
|
||||
.stroke(palette.divider, lineWidth: 0.5)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Footer links (tab settings only)
|
||||
|
||||
private var footerLinks: some View {
|
||||
|
||||
Reference in New Issue
Block a user