Files
pihkaal-me/app/stores/app.ts

132 lines
2.9 KiB
TypeScript

import { z } from "zod/mini";
import type * as THREE from "three";
export const LOGICAL_WIDTH = 256;
export const LOGICAL_HEIGHT = 192;
export const SCREEN_SCALE = 2;
export const SCREEN_WIDTH = LOGICAL_WIDTH * SCREEN_SCALE;
export const SCREEN_HEIGHT = LOGICAL_HEIGHT * SCREEN_SCALE;
export const APP_COLORS = [
["#61829a", "#ba4900", "#fb0018", "#fb8afb"],
["#fb9200", "#f3e300", "#aafb00", "#00fb00"],
["#00a238", "#49db8a", "#30baf3", "#0059f3"],
["#000092", "#8a00d3", "#d300eb", "#fb0092"],
];
const STORAGE_ID = "nds-settings";
const settingsSchema = z.object({
color: z.object({
col: z.number(),
row: z.number(),
}),
renderingMode: z.enum(["3d", "2d"]),
volume: z.number(),
});
type Settings = z.infer<typeof settingsSchema>;
const defaultSettings = (): Settings => ({
color: { col: 0, row: 0 },
renderingMode: "3d",
volume: 0.5,
});
export const useAppStore = defineStore("app", {
state: () => {
let settings: Settings;
const stored = localStorage.getItem(STORAGE_ID);
try {
settings = settingsSchema.parse(JSON.parse(stored ?? ""));
} catch {
settings = defaultSettings();
}
return {
ready: false,
booted: false,
userHasInteracted: false,
settings,
previousScreen: "home" as AppScreen,
screen: "home" as AppScreen,
visitedGallery: false,
camera: null as THREE.Camera | null,
hintsVisible: false,
hintsAllowed: false,
lagDetected: false,
lagModalOpen: false,
};
},
actions: {
setColor(col: number, row: number) {
this.settings.color = { col, row };
},
setRenderingMode(mode: Settings["renderingMode"]) {
this.ready = mode === "2d";
this.settings.renderingMode = mode;
this.lagDetected = false;
this.save();
},
navigateTo(screen: AppScreen) {
this.previousScreen = this.screen;
this.screen = screen;
const achievements = useAchievementsStore();
switch (screen) {
case "projects":
achievements.unlock("projects_visit");
break;
case "gallery":
this.visitedGallery = true;
break;
case "contact":
achievements.unlock("contact_visit");
break;
}
},
allowHints() {
this.hintsAllowed = true;
},
disallowHints() {
this.hintsAllowed = false;
this.hintsVisible = false;
},
showHints() {
if (!this.hintsAllowed) return;
this.hintsVisible = true;
},
hideHints() {
this.hintsVisible = false;
},
setCamera(camera: THREE.Camera) {
this.camera = camera;
},
save() {
localStorage.setItem(STORAGE_ID, JSON.stringify(this.settings));
},
},
getters: {
color: (state) => ({
col: state.settings.color.col,
row: state.settings.color.row,
hex: APP_COLORS[state.settings.color.row]![state.settings.color.col]!,
}),
},
});