Release Healer Man 0.1.28

This commit is contained in:
phenom committed 2026-09-10 14:14:02 -04:00
1 parent ed8b9e3719
commit 8c9809d3e0
23 files changed
+975 -55

No files matched your search

+59
View File
@@ -0,0 +1,59 @@
import { create } from "zustand";
import { Capacitor } from "@capacitor/core";
import { loadUiPreferences, saveUiPreferences } from "../app/accountRepository";
import { useShellStore } from "../app/shellStore";
import { normalizeUiPreferences, type UiDevice, type UiLayout, type UiPreferences } from "./uiLayout";
export function currentUiDevice(): UiDevice {
return Capacitor.isNativePlatform() || (typeof navigator !== "undefined" && /Android|iPhone|iPad|iPod/i.test(navigator.userAgent))
|| (typeof window !== "undefined" && window.matchMedia?.("(pointer: coarse)").matches && window.innerWidth < 1100)
? "mobile" : "pc";
}
interface UiLayoutState {
ownerId: string | null;
preferences: UiPreferences;
draft: UiLayout | null;
device: UiDevice;
mode: "layout" | "bindings";
selectedButton: { bar: number; slot: number } | null;
selectedElement: string | null;
begin: () => void;
updateDraft: (update: (layout: UiLayout) => UiLayout) => void;
persist: (preferences: UiPreferences) => void;
finish: (save: boolean) => void;
}
export const useUiLayoutStore = create<UiLayoutState>((set, get) => ({
ownerId: null, preferences: normalizeUiPreferences(null), draft: null, device: currentUiDevice(),
mode: "layout", selectedButton: null, selectedElement: null,
begin: () => {
const device = currentUiDevice();
set({ draft: get().preferences.current[device], device, mode: "layout", selectedButton: null });
},
updateDraft: (update) => set((state) => state.draft ? { draft: update(state.draft) } : state),
persist: (preferences) => {
const ownerId = get().ownerId;
if (!ownerId) throw new Error("Sign in or choose an offline profile before saving your UI.");
// Write first: storage errors leave the editor open with its draft intact.
const saved = saveUiPreferences(ownerId, preferences);
set({ preferences: saved });
},
finish: (save) => {
const { draft, device, preferences } = get();
if (save && draft) get().persist({ ...preferences, current: { ...preferences.current, [device]: draft } });
set({ draft: null, selectedButton: null, mode: "layout" });
},
}));
function activateOwner() {
const ownerId = useShellStore.getState().session?.ownerId ?? null;
useUiLayoutStore.setState({ ownerId, preferences: ownerId ? loadUiPreferences(ownerId) : normalizeUiPreferences(null), draft: null });
}
activateOwner();
useShellStore.subscribe((state, previous) => {
if (state.session !== previous.session) activateOwner();
});
export function activeUiLayout(): UiLayout {
const state = useUiLayoutStore.getState();
return state.draft ?? state.preferences.current[currentUiDevice()];
}