feat: iOS appearance, iPad logo fix, demo seed, and landing hero polish
Add System/Light/Dark preference for iPhone and iPad, restore the iPad sidebar brand mark, ship a DEBUG seed-demo URL for rich placeholder data, and refresh GitHub Pages with the device composite, full-bleed pale-green hero wash, and transparent Mac screenshot chrome.
This commit is contained in:
@@ -8,6 +8,14 @@ import OSGKeyboardShared
|
||||
struct OSGKeyboardApp: App {
|
||||
@UIApplicationDelegateAdaptor(AppURLHandler.self) private var appURLHandler
|
||||
|
||||
/// App-local light / dark preference (Settings ▸ Preferences ▸ Appearance).
|
||||
@AppStorage(AppearancePreference.storageKey)
|
||||
private var appearanceRaw = AppearancePreference.system.rawValue
|
||||
|
||||
private var appearance: AppearancePreference {
|
||||
AppearancePreference.fromStored(appearanceRaw)
|
||||
}
|
||||
|
||||
init() {
|
||||
MaterialIconsFont.registerIfNeeded()
|
||||
if AppGroup.isAvailable {
|
||||
@@ -21,10 +29,12 @@ struct OSGKeyboardApp: App {
|
||||
ThemedRoot {
|
||||
MainAppRoot()
|
||||
}
|
||||
.preferredColorScheme(appearance.colorScheme)
|
||||
} else {
|
||||
ThemedRoot {
|
||||
AppGroupErrorView()
|
||||
}
|
||||
.preferredColorScheme(appearance.colorScheme)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,6 +80,11 @@ struct MainAppRoot: View {
|
||||
switch url.host {
|
||||
case "startflow":
|
||||
flowManager.startSession(coldStart: true)
|
||||
#if DEBUG
|
||||
case "seed-demo":
|
||||
DemoDataSeeder.seedRichPlaceholderData()
|
||||
config.reloadFromPersistedStorage()
|
||||
#endif
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
@@ -54,13 +54,19 @@ struct MainSplitView: View {
|
||||
|
||||
private var brandHeader: some View {
|
||||
HStack {
|
||||
Image("osglogo")
|
||||
// Match macOS sidebar: template wide mark tinted with accent so
|
||||
// light / dark both stay readable (PNG `osglogo` can fail to
|
||||
// show under NavigationSplitView chrome on some iPad sizes).
|
||||
Image("OSGLogoWide")
|
||||
.renderingMode(.template)
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.frame(height: 28)
|
||||
.foregroundStyle(palette.accent)
|
||||
.accessibilityLabel("OSGKeyboard")
|
||||
Spacer()
|
||||
Spacer(minLength: 0)
|
||||
}
|
||||
.frame(maxWidth: .infinity, minHeight: 28, alignment: .leading)
|
||||
.padding(.leading, WideLayoutMetrics.sidebarContentInset)
|
||||
.padding(.trailing, WideLayoutMetrics.sidebarInset)
|
||||
.padding(.top, Spacing.lg)
|
||||
|
||||
@@ -156,6 +156,10 @@ struct SettingsView: View {
|
||||
|
||||
Divider().background(palette.divider)
|
||||
|
||||
AppearancePickerRow()
|
||||
|
||||
Divider().background(palette.divider)
|
||||
|
||||
LocalePickerRow(
|
||||
locales: effectiveLocales,
|
||||
selection: Binding(
|
||||
@@ -495,6 +499,27 @@ private struct AppLanguagePickerRow: View {
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Appearance picker row
|
||||
|
||||
private struct AppearancePickerRow: View {
|
||||
@AppStorage(AppearancePreference.storageKey)
|
||||
private var appearanceRaw = AppearancePreference.system.rawValue
|
||||
|
||||
private var options: [(id: String, label: String)] {
|
||||
AppearancePreference.allCases.map { preference in
|
||||
(preference.rawValue, AppL10n.string(preference.labelKey))
|
||||
}
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
PickerRow(
|
||||
title: AppL10n.string("settings.appearance.title"),
|
||||
options: options,
|
||||
selection: $appearanceRaw
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Flow inactivity picker row
|
||||
|
||||
private struct FlowInactivityPickerRow: View {
|
||||
|
||||
@@ -91,6 +91,10 @@
|
||||
"settings.appLanguage.auto" = "Auto";
|
||||
"settings.appLanguage.english" = "English";
|
||||
"settings.appLanguage.chinese" = "Chinese";
|
||||
"settings.appearance.title" = "Appearance";
|
||||
"settings.appearance.system" = "System";
|
||||
"settings.appearance.light" = "Light";
|
||||
"settings.appearance.dark" = "Dark";
|
||||
"settings.reset.title" = "Reset all settings?";
|
||||
"settings.reset.message" = "API key, model, base URL, voice history, and cloud consent will be cleared.";
|
||||
"settings.reset.confirm" = "Reset all settings";
|
||||
|
||||
@@ -91,6 +91,10 @@
|
||||
"settings.appLanguage.auto" = "自动";
|
||||
"settings.appLanguage.english" = "英文";
|
||||
"settings.appLanguage.chinese" = "中文";
|
||||
"settings.appearance.title" = "外观";
|
||||
"settings.appearance.system" = "跟随系统";
|
||||
"settings.appearance.light" = "浅色";
|
||||
"settings.appearance.dark" = "深色";
|
||||
"settings.reset.title" = "重置所有设置?";
|
||||
"settings.reset.message" = "将清空 API Key、模型、接口地址、语音历史及云端确认状态。";
|
||||
"settings.reset.confirm" = "重置所有设置";
|
||||
|
||||
Reference in New Issue
Block a user