Nach dem 0.2.1.8-Deploy sah die App "unveraendert" aus — korrekt, weil der Hauptchat nur eine Kachel hat (= Vollbild-Chat). Jetzt explizit umschaltbar: - services/viewMode.ts: 'compact' | 'cockpit', persistiert (aria_view_mode), Default 'compact' (nichts aendert sich fuer normale Nutzung). - ViewModeToggle im Navigations-Header (rechts, kollisionsfrei): "⧉ Kompakt" / "⧉ Cockpit". - WorkspaceScreen: compact → klassische ChatScreen direkt; cockpit → Canvas. - Canvas: Uebersicht/Gesten/Back jetzt auch bei einer Kachel erreichbar (der single-Force-Fokus entfaellt), damit sich Cockpit auch im Hauptchat wie ein Desktop anfuehlt. "⤢ Uebersicht"-Button nach unten rechts verschoben (weg von ChatScreens Kopf-Icons). Changelog: Workspace-Release als 0.2.1.8 gefuehrt, Umschalter als 0.2.1.9. tsc clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
58 lines
1.5 KiB
TypeScript
58 lines
1.5 KiB
TypeScript
/**
|
|
* viewMode — App-Ansicht: 'compact' (klassischer Vollbild-Chat wie vor 0.2.2.0)
|
|
* oder 'cockpit' (zoombarer Kachel-Desktop).
|
|
*
|
|
* Default 'compact' → fuer normale Nutzung aendert sich nichts (Mama-tauglich).
|
|
* Umschaltbar ueber den Header-Button; persistiert in AsyncStorage. Muster wie
|
|
* services/rvs.ts (Singleton mit Listener-Liste).
|
|
*/
|
|
|
|
import AsyncStorage from '@react-native-async-storage/async-storage';
|
|
|
|
export type ViewModeValue = 'compact' | 'cockpit';
|
|
|
|
const KEY = 'aria_view_mode';
|
|
type Sub = (mode: ViewModeValue) => void;
|
|
|
|
class ViewMode {
|
|
private mode: ViewModeValue = 'compact';
|
|
private subs: Sub[] = [];
|
|
private loaded = false;
|
|
|
|
constructor() {
|
|
AsyncStorage.getItem(KEY).then((v) => {
|
|
if (v === 'cockpit' || v === 'compact') this.mode = v;
|
|
this.loaded = true;
|
|
this.emit();
|
|
}).catch(() => { this.loaded = true; });
|
|
}
|
|
|
|
get(): ViewModeValue { return this.mode; }
|
|
isLoaded(): boolean { return this.loaded; }
|
|
|
|
set(mode: ViewModeValue): void {
|
|
if (this.mode === mode) return;
|
|
this.mode = mode;
|
|
AsyncStorage.setItem(KEY, mode).catch(() => {});
|
|
this.emit();
|
|
}
|
|
|
|
toggle(): void {
|
|
this.set(this.mode === 'compact' ? 'cockpit' : 'compact');
|
|
}
|
|
|
|
subscribe(cb: Sub): () => void {
|
|
this.subs.push(cb);
|
|
cb(this.mode);
|
|
return () => { this.subs = this.subs.filter((s) => s !== cb); };
|
|
}
|
|
|
|
private emit(): void {
|
|
const m = this.mode;
|
|
this.subs.forEach((cb) => cb(m));
|
|
}
|
|
}
|
|
|
|
const viewMode = new ViewMode();
|
|
export default viewMode;
|