e0b92ff35a
- Split Palette.dark / Palette.light into a ThemePalette struct - Add EnvironmentKey<ThemePalette> + ThemedRoot<Content> - Wrap OSGKeyboardApp root in ThemedRoot so main App follows system - Remove 6 .preferredColorScheme(.dark) overrides from main App views - KeyboardRootView drops its Palette.background fill, uses .background(Color.clear) - Drop the unused 'background' computed property from KeyboardRootView - Legacy 'Palette.xxx' static accessors still resolve to dark values, so 2000 lines of existing call sites stay untouched xcodebuild iOS Simulator: SUCCEEDED
157 lines
5.3 KiB
Swift
157 lines
5.3 KiB
Swift
// HomeView.swift
|
|
// OSGKeyboard · Main App
|
|
//
|
|
// Post-onboarding home. Two jobs: (1) tell the user we're ready, and
|
|
// (2) give a clear path to the next setup step if anything is missing.
|
|
|
|
import SwiftUI
|
|
import OSGKeyboardShared
|
|
import OSGKeyboardExt
|
|
|
|
struct HomeView: View {
|
|
@ObservedObject var config = ProviderConfig.shared
|
|
@State private var showSettings = false
|
|
@State private var showKeyboardPreview = false
|
|
|
|
var body: some View {
|
|
ZStack {
|
|
Palette.background.ignoresSafeArea()
|
|
VStack(spacing: 0) {
|
|
statusHeader
|
|
.padding(.top, Spacing.xl)
|
|
Spacer()
|
|
heroButton
|
|
Spacer()
|
|
actionStack
|
|
.padding(.horizontal, Spacing.md)
|
|
.padding(.bottom, Spacing.lg)
|
|
}
|
|
}
|
|
.sheet(isPresented: $showSettings) {
|
|
SettingsView()
|
|
}
|
|
.sheet(isPresented: $showKeyboardPreview) {
|
|
KeyboardPreviewSheet()
|
|
}
|
|
}
|
|
|
|
// MARK: - Header
|
|
|
|
private var statusHeader: some View {
|
|
VStack(spacing: Spacing.xs) {
|
|
HStack(spacing: 6) {
|
|
Circle()
|
|
.fill(config.isConfigured ? Palette.success : Palette.warning)
|
|
.frame(width: 8, height: 8)
|
|
Text(config.isConfigured ? "Ready" : "Setup incomplete")
|
|
.font(TypeStyle.caption)
|
|
.foregroundStyle(Palette.textSecondary)
|
|
}
|
|
Text("OSGKeyboard")
|
|
.font(TypeStyle.largeTitle)
|
|
.foregroundStyle(Palette.textPrimary)
|
|
Text(providerLine)
|
|
.font(TypeStyle.caption)
|
|
.foregroundStyle(Palette.textSecondary)
|
|
.multilineTextAlignment(.center)
|
|
}
|
|
}
|
|
|
|
private var providerLine: String {
|
|
let p = LLMProvider.provider(id: config.providerId)
|
|
let model = config.model.isEmpty ? "—" : config.model
|
|
return "\(p.name) · \(model)"
|
|
}
|
|
|
|
// MARK: - Hero
|
|
|
|
private var heroButton: some View {
|
|
Button {
|
|
showSettings = true
|
|
} label: {
|
|
ZStack {
|
|
Circle()
|
|
.fill(Palette.accentMuted)
|
|
.frame(width: 220, height: 220)
|
|
.blur(radius: 40)
|
|
Circle()
|
|
.fill(LinearGradient(
|
|
colors: [Palette.surfaceElevated, Palette.surface],
|
|
startPoint: .top,
|
|
endPoint: .bottom
|
|
))
|
|
.frame(width: 160, height: 160)
|
|
.overlay(
|
|
Circle().stroke(Palette.accent.opacity(0.35), lineWidth: 1.5)
|
|
)
|
|
.shadow(color: Palette.accent.opacity(0.18), radius: 24, y: 8)
|
|
VStack(spacing: 6) {
|
|
Image(systemName: "waveform")
|
|
.font(.system(size: 36, weight: .light))
|
|
.foregroundStyle(Palette.accent)
|
|
Text("Tap to configure")
|
|
.font(TypeStyle.caption)
|
|
.foregroundStyle(Palette.textSecondary)
|
|
}
|
|
}
|
|
}
|
|
.buttonStyle(.plain)
|
|
.accessibilityLabel(Text("Open OSGKeyboard settings"))
|
|
}
|
|
|
|
// MARK: - Actions
|
|
|
|
private var actionStack: some View {
|
|
VStack(spacing: Spacing.xs) {
|
|
Button {
|
|
if let url = URL(string: UIApplication.openSettingsURLString) {
|
|
UIApplication.shared.open(url)
|
|
}
|
|
} label: {
|
|
Label("启用键盘 · Enable in iOS Settings", systemImage: "keyboard")
|
|
.primaryButton()
|
|
}
|
|
.buttonStyle(.plain)
|
|
|
|
Button {
|
|
showSettings = true
|
|
} label: {
|
|
Label("编辑 API 配置 · Edit API Configuration", systemImage: "slider.horizontal.3")
|
|
.secondaryButton()
|
|
}
|
|
.buttonStyle(.plain)
|
|
|
|
#if DEBUG
|
|
Button {
|
|
showKeyboardPreview = true
|
|
} label: {
|
|
Label("键盘预览 · Keyboard Preview (Debug)", systemImage: "eye")
|
|
.secondaryButton()
|
|
}
|
|
.buttonStyle(.plain)
|
|
#endif
|
|
|
|
HStack(spacing: Spacing.xs) {
|
|
Button {
|
|
if let url = URL(string: "https://github.com/hkgood/OSGKeyboard") {
|
|
UIApplication.shared.open(url)
|
|
}
|
|
} label: {
|
|
Text("GitHub")
|
|
.font(TypeStyle.caption)
|
|
.foregroundStyle(Palette.textSecondary)
|
|
.padding(.horizontal, Spacing.sm)
|
|
.padding(.vertical, 6)
|
|
.background(Palette.surface, in: Capsule())
|
|
.overlay(Capsule().stroke(Palette.divider, lineWidth: 0.5))
|
|
}
|
|
.buttonStyle(.plain)
|
|
Spacer()
|
|
Text("v\(Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "0.1.0")")
|
|
.font(TypeStyle.caption2)
|
|
.foregroundStyle(Palette.textTertiary)
|
|
}
|
|
}
|
|
}
|
|
}
|