mirror of
https://github.com/permissionlesstech/bitchat.git
synced 2026-07-25 09:05:20 +00:00
Liquid Glass theme with in-app appearance switcher (#1337)
* Centralize UI theme colors into semantic ThemePalette tokens Introduce AppTheme/ThemePalette (Utils/Theme.swift) with an environment key and @ThemedPalette property wrapper, persisted via @AppStorage. Views now resolve background/primary/secondary/accentBlue/alertRed/ divider tokens from the environment instead of computing colors inline, removing the backgroundColor/textColor/secondaryTextColor prop-drilling through the header, composer, and people-sheet hierarchy. Matrix theme output is pixel-identical; this is groundwork for a user-selectable theme switcher. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * Add liquid glass theme with in-app appearance switcher Add a .liquidGlass AppTheme alongside the matrix terminal theme, selectable from a one-line APPEARANCE row in the app info sheet (persisted via @AppStorage, applies live). Liquid glass renders system fonts and colors over a subtle gradient backdrop, with the header and composer floating as Liquid Glass panels (real .glassEffect() on iOS/macOS 26, compiler-gated with an ultraThinMaterial fallback for older SDKs). The message list scrolls underneath the chrome via safe-area insets, and all sheets share the same backdrop and surface language. The matrix theme is unchanged. Details: - Theme is threaded through ChatMessageFormatter so message AttributedStrings switch font design per theme; the per-message format cache gains a variant key so themes never serve each other's cached strings - New palette tokens: accent (interactive tint) and locationAccent (geohash green), replacing scattered hardcoded greens/blues in the voice note, waveform, verification, and people-sheet views - Header controls get full-height tap targets and the people count becomes a real Button (previously a tap gesture on the cluster) - CommandSuggestionsView renders nothing when empty instead of a zero-height view that pushed the composer input off-center - New appearance strings localized for all 29 catalog languages Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: jack <jackjackbits@users.noreply.github.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
jack
Claude Fable 5
parent
c8381737bb
commit
af954b05ea
@@ -21,7 +21,7 @@ struct MyQRView: View {
|
||||
var body: some View {
|
||||
VStack(spacing: 12) {
|
||||
Text(Strings.title)
|
||||
.font(.bitchatSystem(size: 16, weight: .bold, design: .monospaced))
|
||||
.bitchatFont(size: 16, weight: .bold)
|
||||
|
||||
VStack(spacing: 10) {
|
||||
QRCodeImage(data: qrString, size: 240)
|
||||
@@ -29,7 +29,7 @@ struct MyQRView: View {
|
||||
|
||||
// Non-scrolling, fully visible URL (wraps across lines)
|
||||
Text(qrString)
|
||||
.font(.bitchatSystem(size: 11, design: .monospaced))
|
||||
.bitchatFont(size: 11)
|
||||
.textSelection(.enabled)
|
||||
.multilineTextAlignment(.leading)
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
@@ -69,7 +69,7 @@ struct QRCodeImage: View {
|
||||
.frame(width: size, height: size)
|
||||
.overlay(
|
||||
Text(Strings.unavailable)
|
||||
.font(.bitchatSystem(size: 12, design: .monospaced))
|
||||
.bitchatFont(size: 12)
|
||||
.foregroundColor(.gray)
|
||||
)
|
||||
}
|
||||
@@ -150,7 +150,7 @@ struct QRScanView: View {
|
||||
.clipShape(RoundedRectangle(cornerRadius: 8))
|
||||
#else
|
||||
Text(Strings.pastePrompt)
|
||||
.font(.bitchatSystem(size: 14, weight: .medium, design: .monospaced))
|
||||
.bitchatFont(size: 14, weight: .medium)
|
||||
TextEditor(text: $input)
|
||||
.frame(height: 100)
|
||||
.border(Color.gray.opacity(0.4))
|
||||
@@ -281,10 +281,10 @@ struct VerificationSheetView: View {
|
||||
@EnvironmentObject private var verificationModel: VerificationModel
|
||||
@Binding var isPresented: Bool
|
||||
@State private var showingScanner = false
|
||||
@Environment(\.colorScheme) var colorScheme
|
||||
@ThemedPalette private var palette
|
||||
|
||||
private var backgroundColor: Color { colorScheme == .dark ? Color.black : Color.white }
|
||||
private var accentColor: Color { colorScheme == .dark ? Color.green : Color(red: 0, green: 0.5, blue: 0) }
|
||||
private var backgroundColor: Color { palette.background }
|
||||
private var accentColor: Color { palette.accent }
|
||||
private var boxColor: Color { Color.gray.opacity(0.1) }
|
||||
|
||||
var body: some View {
|
||||
@@ -292,7 +292,7 @@ struct VerificationSheetView: View {
|
||||
// Top header (always at top)
|
||||
HStack {
|
||||
Text("verification.sheet.title")
|
||||
.font(.bitchatSystem(size: 14, weight: .bold, design: .monospaced))
|
||||
.bitchatFont(size: 14, weight: .bold)
|
||||
.foregroundColor(accentColor)
|
||||
Spacer()
|
||||
Button(action: {
|
||||
@@ -316,7 +316,7 @@ struct VerificationSheetView: View {
|
||||
if showingScanner {
|
||||
VStack(alignment: .leading, spacing: 12) {
|
||||
Text("verification.scan.prompt_friend")
|
||||
.font(.bitchatSystem(size: 16, weight: .bold, design: .monospaced))
|
||||
.bitchatFont(size: 16, weight: .bold)
|
||||
.frame(maxWidth: .infinity)
|
||||
.multilineTextAlignment(.center)
|
||||
.foregroundColor(accentColor)
|
||||
@@ -350,13 +350,13 @@ struct VerificationSheetView: View {
|
||||
if showingScanner {
|
||||
Button(action: { showingScanner = false }) {
|
||||
Label("show my qr", systemImage: "qrcode")
|
||||
.font(.bitchatSystem(size: 13, design: .monospaced))
|
||||
.bitchatFont(size: 13)
|
||||
}
|
||||
.buttonStyle(.bordered)
|
||||
} else {
|
||||
Button(action: { showingScanner = true }) {
|
||||
Label("scan someone else's qr", systemImage: "camera.viewfinder")
|
||||
.font(.bitchatSystem(size: 13, weight: .medium, design: .monospaced))
|
||||
.bitchatFont(size: 13, weight: .medium)
|
||||
}
|
||||
.buttonStyle(.bordered)
|
||||
.tint(.gray)
|
||||
@@ -367,7 +367,7 @@ struct VerificationSheetView: View {
|
||||
verificationModel.isVerified(peerID: peerID) {
|
||||
Button(action: { verificationModel.unverifyFingerprint(for: peerID) }) {
|
||||
Label("remove verification", systemImage: "minus.circle")
|
||||
.font(.bitchatSystem(size: 12, design: .monospaced))
|
||||
.bitchatFont(size: 12)
|
||||
}
|
||||
.buttonStyle(.bordered)
|
||||
.tint(.gray)
|
||||
@@ -376,7 +376,7 @@ struct VerificationSheetView: View {
|
||||
.frame(maxWidth: .infinity)
|
||||
.padding(.vertical, 14)
|
||||
}
|
||||
.background(backgroundColor)
|
||||
.themedSheetBackground()
|
||||
.onDisappear { showingScanner = false }
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user