56fb399e89
ExtL10n.text returns Text; use ExtL10n.string where String is required (computed properties, Text/Button initializers). TypeStyle has caption, not caption1 — align onboarding and dictionary views. Co-authored-by: Rocky <hkgood@users.noreply.github.com>
76 lines
2.7 KiB
Swift
76 lines
2.7 KiB
Swift
// AppContextChip.swift
|
|
// OSGKeyboard · Keyboard Extension
|
|
//
|
|
// Surfaces the v0.3.0 per-app polish context on the keyboard top
|
|
// bar. The LLM prompt already adapts to the detected context (see
|
|
// `PolishingService.buildPrompt(for:context:)`), but without a UI
|
|
// cue the user has no way to know "I'm currently in code mode" —
|
|
// and no way to override the heuristic when it guesses wrong.
|
|
//
|
|
// Tap the chip → cycle through the five `AppContext` cases. The new
|
|
// value is written to `AppGroupStore.setDetectedAppContext(_:at:)`,
|
|
// so the next `PolishingService` call picks it up immediately.
|
|
|
|
import SwiftUI
|
|
import OSGKeyboardShared
|
|
|
|
struct AppContextChip: View {
|
|
@Environment(\.themePalette) private var palette: ThemePalette
|
|
|
|
@ObservedObject var state: KeyboardViewController.State
|
|
|
|
var body: some View {
|
|
Menu {
|
|
ForEach(AppContext.allCases, id: \.self) { context in
|
|
Button {
|
|
state.setAppContext(context)
|
|
} label: {
|
|
if context == state.appContext {
|
|
Label(menuLabel(for: context), systemImage: "checkmark")
|
|
} else {
|
|
Text(menuLabel(for: context))
|
|
}
|
|
}
|
|
}
|
|
} label: {
|
|
label
|
|
}
|
|
.menuStyle(.button)
|
|
.accessibilityLabel(ExtL10n.text("keyboard.appContext.a11y"))
|
|
.accessibilityHint(ExtL10n.text("keyboard.appContext.a11yHint"))
|
|
}
|
|
|
|
private var label: some View {
|
|
HStack(spacing: 4) {
|
|
Image(systemName: iconName(for: state.appContext))
|
|
Text(chipText)
|
|
Image(systemName: "chevron.down")
|
|
.font(.system(size: 8, weight: .bold))
|
|
}
|
|
.font(TypeStyle.caption2)
|
|
.foregroundStyle(palette.textPrimary)
|
|
.padding(.horizontal, Spacing.xs + 2)
|
|
.padding(.vertical, 6)
|
|
.frame(minHeight: 28)
|
|
.background(palette.surfaceElevated, in: Capsule())
|
|
.overlay(Capsule().stroke(palette.divider, lineWidth: 0.5))
|
|
}
|
|
|
|
private var chipText: String {
|
|
ExtL10n.string("keyboard.appContext.chip.\(state.appContext.rawValue)")
|
|
}
|
|
|
|
private func menuLabel(for context: AppContext) -> String {
|
|
ExtL10n.string("keyboard.appContext.menu.\(context.rawValue)")
|
|
}
|
|
|
|
private func iconName(for context: AppContext) -> String {
|
|
switch context {
|
|
case .code: return "chevron.left.forwardslash.chevron.right"
|
|
case .email: return "envelope"
|
|
case .chat: return "bubble.left"
|
|
case .document: return "doc.text"
|
|
case .unknown: return "questionmark.circle"
|
|
}
|
|
}
|
|
} |