iOS: allow settings light mode
This commit is contained in:
@@ -4,6 +4,7 @@ import UIKit
|
|||||||
struct RootCanvas: View {
|
struct RootCanvas: View {
|
||||||
@Environment(NodeAppModel.self) private var appModel
|
@Environment(NodeAppModel.self) private var appModel
|
||||||
@Environment(VoiceWakeManager.self) private var voiceWake
|
@Environment(VoiceWakeManager.self) private var voiceWake
|
||||||
|
@Environment(\.colorScheme) private var systemColorScheme
|
||||||
@Environment(\.scenePhase) private var scenePhase
|
@Environment(\.scenePhase) private var scenePhase
|
||||||
@AppStorage(VoiceWakePreferences.enabledKey) private var voiceWakeEnabled: Bool = false
|
@AppStorage(VoiceWakePreferences.enabledKey) private var voiceWakeEnabled: Bool = false
|
||||||
@AppStorage("screen.preventSleep") private var preventSleep: Bool = true
|
@AppStorage("screen.preventSleep") private var preventSleep: Bool = true
|
||||||
@@ -24,38 +25,19 @@ struct RootCanvas: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
ZStack(alignment: .topTrailing) {
|
ZStack {
|
||||||
ScreenTab()
|
CanvasContent(
|
||||||
|
systemColorScheme: self.systemColorScheme,
|
||||||
VStack(spacing: 10) {
|
bridgeStatus: self.bridgeStatus,
|
||||||
OverlayButton(systemImage: "text.bubble.fill") {
|
|
||||||
self.presentedSheet = .chat
|
|
||||||
}
|
|
||||||
.accessibilityLabel("Chat")
|
|
||||||
|
|
||||||
OverlayButton(systemImage: "gearshape.fill") {
|
|
||||||
self.presentedSheet = .settings
|
|
||||||
}
|
|
||||||
.accessibilityLabel("Settings")
|
|
||||||
}
|
|
||||||
.padding(.top, 10)
|
|
||||||
.padding(.trailing, 10)
|
|
||||||
}
|
|
||||||
.overlay(alignment: .topLeading) {
|
|
||||||
StatusPill(
|
|
||||||
bridge: self.bridgeStatus,
|
|
||||||
voiceWakeEnabled: self.voiceWakeEnabled,
|
voiceWakeEnabled: self.voiceWakeEnabled,
|
||||||
onTap: { self.presentedSheet = .settings })
|
voiceWakeToastText: self.voiceWakeToastText,
|
||||||
.padding(.leading, 10)
|
openChat: {
|
||||||
.safeAreaPadding(.top, 10)
|
self.presentedSheet = .chat
|
||||||
}
|
},
|
||||||
.overlay(alignment: .topLeading) {
|
openSettings: {
|
||||||
if let voiceWakeToastText, !voiceWakeToastText.isEmpty {
|
self.presentedSheet = .settings
|
||||||
VoiceWakeToast(command: voiceWakeToastText)
|
})
|
||||||
.padding(.leading, 10)
|
.preferredColorScheme(.dark)
|
||||||
.safeAreaPadding(.top, 58)
|
|
||||||
.transition(.move(edge: .top).combined(with: .opacity))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.sheet(item: self.$presentedSheet) { sheet in
|
.sheet(item: self.$presentedSheet) { sheet in
|
||||||
switch sheet {
|
switch sheet {
|
||||||
@@ -65,7 +47,6 @@ struct RootCanvas: View {
|
|||||||
ChatSheet(bridge: self.appModel.bridgeSession)
|
ChatSheet(bridge: self.appModel.bridgeSession)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.preferredColorScheme(.dark)
|
|
||||||
.onAppear { self.updateIdleTimer() }
|
.onAppear { self.updateIdleTimer() }
|
||||||
.onChange(of: self.preventSleep) { _, _ in self.updateIdleTimer() }
|
.onChange(of: self.preventSleep) { _, _ in self.updateIdleTimer() }
|
||||||
.onChange(of: self.scenePhase) { _, _ in self.updateIdleTimer() }
|
.onChange(of: self.scenePhase) { _, _ in self.updateIdleTimer() }
|
||||||
@@ -117,8 +98,61 @@ struct RootCanvas: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private struct CanvasContent: View {
|
||||||
|
var systemColorScheme: ColorScheme
|
||||||
|
var bridgeStatus: StatusPill.BridgeState
|
||||||
|
var voiceWakeEnabled: Bool
|
||||||
|
var voiceWakeToastText: String?
|
||||||
|
var openChat: () -> Void
|
||||||
|
var openSettings: () -> Void
|
||||||
|
|
||||||
|
private var brightenButtons: Bool { self.systemColorScheme == .light }
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
ZStack(alignment: .topTrailing) {
|
||||||
|
ScreenTab()
|
||||||
|
|
||||||
|
VStack(spacing: 10) {
|
||||||
|
OverlayButton(systemImage: "text.bubble.fill", brighten: self.brightenButtons) {
|
||||||
|
self.openChat()
|
||||||
|
}
|
||||||
|
.accessibilityLabel("Chat")
|
||||||
|
|
||||||
|
OverlayButton(systemImage: "gearshape.fill", brighten: self.brightenButtons) {
|
||||||
|
self.openSettings()
|
||||||
|
}
|
||||||
|
.accessibilityLabel("Settings")
|
||||||
|
}
|
||||||
|
.padding(.top, 10)
|
||||||
|
.padding(.trailing, 10)
|
||||||
|
}
|
||||||
|
.overlay(alignment: .topLeading) {
|
||||||
|
StatusPill(
|
||||||
|
bridge: self.bridgeStatus,
|
||||||
|
voiceWakeEnabled: self.voiceWakeEnabled,
|
||||||
|
brighten: self.brightenButtons,
|
||||||
|
onTap: {
|
||||||
|
self.openSettings()
|
||||||
|
})
|
||||||
|
.padding(.leading, 10)
|
||||||
|
.safeAreaPadding(.top, 10)
|
||||||
|
}
|
||||||
|
.overlay(alignment: .topLeading) {
|
||||||
|
if let voiceWakeToastText, !voiceWakeToastText.isEmpty {
|
||||||
|
VoiceWakeToast(
|
||||||
|
command: voiceWakeToastText,
|
||||||
|
brighten: self.brightenButtons)
|
||||||
|
.padding(.leading, 10)
|
||||||
|
.safeAreaPadding(.top, 58)
|
||||||
|
.transition(.move(edge: .top).combined(with: .opacity))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private struct OverlayButton: View {
|
private struct OverlayButton: View {
|
||||||
let systemImage: String
|
let systemImage: String
|
||||||
|
let brighten: Bool
|
||||||
let action: () -> Void
|
let action: () -> Void
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
@@ -135,8 +169,8 @@ private struct OverlayButton: View {
|
|||||||
.fill(
|
.fill(
|
||||||
LinearGradient(
|
LinearGradient(
|
||||||
colors: [
|
colors: [
|
||||||
.white.opacity(0.18),
|
.white.opacity(self.brighten ? 0.26 : 0.18),
|
||||||
.white.opacity(0.04),
|
.white.opacity(self.brighten ? 0.08 : 0.04),
|
||||||
.clear,
|
.clear,
|
||||||
],
|
],
|
||||||
startPoint: .topLeading,
|
startPoint: .topLeading,
|
||||||
@@ -145,7 +179,7 @@ private struct OverlayButton: View {
|
|||||||
}
|
}
|
||||||
.overlay {
|
.overlay {
|
||||||
RoundedRectangle(cornerRadius: 12, style: .continuous)
|
RoundedRectangle(cornerRadius: 12, style: .continuous)
|
||||||
.strokeBorder(.white.opacity(0.18), lineWidth: 0.5)
|
.strokeBorder(.white.opacity(self.brighten ? 0.24 : 0.18), lineWidth: 0.5)
|
||||||
}
|
}
|
||||||
.shadow(color: .black.opacity(0.35), radius: 12, y: 6)
|
.shadow(color: .black.opacity(0.35), radius: 12, y: 6)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ struct StatusPill: View {
|
|||||||
|
|
||||||
var bridge: BridgeState
|
var bridge: BridgeState
|
||||||
var voiceWakeEnabled: Bool
|
var voiceWakeEnabled: Bool
|
||||||
|
var brighten: Bool = false
|
||||||
var onTap: () -> Void
|
var onTap: () -> Void
|
||||||
|
|
||||||
@State private var pulse: Bool = false
|
@State private var pulse: Bool = false
|
||||||
@@ -63,7 +64,7 @@ struct StatusPill: View {
|
|||||||
.fill(.ultraThinMaterial)
|
.fill(.ultraThinMaterial)
|
||||||
.overlay {
|
.overlay {
|
||||||
RoundedRectangle(cornerRadius: 14, style: .continuous)
|
RoundedRectangle(cornerRadius: 14, style: .continuous)
|
||||||
.strokeBorder(.white.opacity(0.18), lineWidth: 0.5)
|
.strokeBorder(.white.opacity(self.brighten ? 0.24 : 0.18), lineWidth: 0.5)
|
||||||
}
|
}
|
||||||
.shadow(color: .black.opacity(0.25), radius: 12, y: 6)
|
.shadow(color: .black.opacity(0.25), radius: 12, y: 6)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import SwiftUI
|
|||||||
|
|
||||||
struct VoiceWakeToast: View {
|
struct VoiceWakeToast: View {
|
||||||
var command: String
|
var command: String
|
||||||
|
var brighten: Bool = false
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
HStack(spacing: 10) {
|
HStack(spacing: 10) {
|
||||||
@@ -22,7 +23,7 @@ struct VoiceWakeToast: View {
|
|||||||
.fill(.ultraThinMaterial)
|
.fill(.ultraThinMaterial)
|
||||||
.overlay {
|
.overlay {
|
||||||
RoundedRectangle(cornerRadius: 14, style: .continuous)
|
RoundedRectangle(cornerRadius: 14, style: .continuous)
|
||||||
.strokeBorder(.white.opacity(0.18), lineWidth: 0.5)
|
.strokeBorder(.white.opacity(self.brighten ? 0.24 : 0.18), lineWidth: 0.5)
|
||||||
}
|
}
|
||||||
.shadow(color: .black.opacity(0.25), radius: 12, y: 6)
|
.shadow(color: .black.opacity(0.25), radius: 12, y: 6)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user