Android self-bind protection auf nahezu MDM-Niveau ohne Device-Owner: - Device-Admin (RebreakDeviceAdminReceiver) blockt Uninstall OS-seitig, aktiv ab Boot ohne Prozess/a11y. Deaktivierung nur via 24h-Cooldown (removeDeviceAdmin in forceDisable). a11y blockt die DeviceAdminAdd-Settings-Seite (Class-Match, auf Samsung One UI per Logcat verifiziert). - Boot-Receiver (RebreakVpnBootReceiver) startet VPN+a11y nach Reboot, damit der Tamper-Lock ohne manuellen App-Start hochkommt. - Manifest-Wiring (Device-Admin-Receiver, Boot-Receiver, RECEIVE_BOOT_COMPLETED, device_admin.xml) ins with-rebreak-protection-android Config-Plugin verlagert → ueberlebt 'expo prebuild' (android/ ist gitignored). - a11y-Detection zurueck auf die funktionierende Version: zu breites 'loeschen'- Uninstall-Keyword raus (blockte halbe Settings); a11y-Label jetzt 'ReBreak Schutz'. - a11y-Deeplink behaelt den Samsung-Step-Guide (openAccessibilitySettings). Session-Frontend in diesem Batch: - Avatar-Placeholder: neutrales clarity-avatar-line SVG statt dominantem Blau. - DiGA-Milestone folgt kumulativen protectedDays (erreicht rueckfall-anfaellige User). - Dev-Build crasht nicht mehr ohne CallKit-Native-Modul. - VPN-Permission-Dialog nur noch im Bypass-Fall. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
80 lines
2.0 KiB
TypeScript
80 lines
2.0 KiB
TypeScript
import { useThemeStore } from '../stores/theme';
|
|
|
|
export const theme = {
|
|
bg: 'bg-white',
|
|
surface: 'bg-neutral-50',
|
|
surfaceElevated: 'bg-neutral-100',
|
|
border: 'border-neutral-200',
|
|
text: 'text-neutral-900',
|
|
textMuted: 'text-neutral-500',
|
|
brandOrange: 'text-rebreak-500',
|
|
brandOrangeBg: 'bg-rebreak-500',
|
|
brandBlue: 'bg-midnight-800',
|
|
} as const;
|
|
|
|
export type ColorScheme = {
|
|
bg: string;
|
|
surface: string;
|
|
surfaceElevated: string;
|
|
/** iOS systemGroupedBackground — page background for list/settings screens */
|
|
groupedBg: string;
|
|
/** iOS secondarySystemGroupedBackground — card/row surface within grouped pages */
|
|
card: string;
|
|
border: string;
|
|
text: string;
|
|
textMuted: string;
|
|
/** Neutraler Grauton für Initialen-Avatare ohne Foto (iOS-Kontakt-Look:
|
|
graue Scheibe, weiße Initialen). Bewusst NICHT brandOrange (=#007AFF, blau). */
|
|
avatarPlaceholder: string;
|
|
brandOrange: string;
|
|
brandBlue: string;
|
|
success: string;
|
|
error: string;
|
|
warning: string;
|
|
};
|
|
|
|
const light: ColorScheme = {
|
|
bg: '#ffffff',
|
|
surface: '#fafafa',
|
|
surfaceElevated: '#f5f5f5',
|
|
groupedBg: '#F2F2F7',
|
|
card: '#ffffff',
|
|
border: '#e5e5e5',
|
|
text: '#0a0a0a',
|
|
textMuted: '#737373',
|
|
avatarPlaceholder: '#8E8E93',
|
|
brandOrange: '#007AFF',
|
|
brandBlue: '#0e1f3a',
|
|
success: '#16a34a',
|
|
error: '#dc2626',
|
|
warning: '#f59e0b',
|
|
};
|
|
|
|
const dark: ColorScheme = {
|
|
bg: '#000000',
|
|
surface: '#1c1c1e',
|
|
surfaceElevated: '#2c2c2e',
|
|
groupedBg: '#000000',
|
|
card: '#1c1c1e',
|
|
border: '#38383a',
|
|
text: '#ffffff',
|
|
textMuted: '#8e8e93',
|
|
avatarPlaceholder: '#48484A',
|
|
brandOrange: '#007AFF',
|
|
brandBlue: '#0e1f3a',
|
|
success: '#30d158',
|
|
error: '#ff453a',
|
|
warning: '#ffd60a',
|
|
};
|
|
|
|
export const colorSchemes = { light, dark };
|
|
|
|
export function useColors(): ColorScheme {
|
|
const scheme = useThemeStore((s) => s.colorScheme);
|
|
return scheme === 'dark' ? dark : light;
|
|
}
|
|
|
|
// Legacy flat export — used by files that haven't migrated to useColors() yet.
|
|
// Wave 2 should remove this.
|
|
export const colors = light;
|