feat(settings): more specific notification handling, and put menu in query to allow user to go back in history to go back in menus

This commit is contained in:
2025-11-26 22:58:03 +01:00
parent 4d9371f1b0
commit a5c1c93260
9 changed files with 181 additions and 128 deletions

View File

@@ -33,25 +33,6 @@ const [
GBA_MODE_IMAGE,
);
const activeMenu = computed(() => {
if (!store.activeMenu) return null;
if (/^options[A-Z]/.test(store.activeMenu)) {
return { id: "options", image: optionsImage };
}
if (/^clock[A-Z]/.test(store.activeMenu)) {
return { id: "clock", image: clockImage };
}
if (/^user[A-Z]/.test(store.activeMenu)) {
return { id: "user", image: userImage };
}
if (/^touchScreen[A-Z]/.test(store.activeMenu)) {
return { id: "touchScreen", image: touchScreenImage };
}
return null;
});
const renderNotification = (
ctx: CanvasRenderingContext2D,
image: HTMLImageElement,
@@ -73,50 +54,100 @@ const renderNotification = (
}
};
const notificationStack = computed(() => {
const stack: Array<{ id: string; image: HTMLImageElement }> = [
{ id: "main", image: settingsImage! },
];
const mainNotification = computed(() => ({
image: settingsImage!,
title: $t("settings.title"),
description: $t("settings.description"),
}));
if (activeMenu.value) {
stack.push({ id: activeMenu.value.id, image: activeMenu.value.image! });
const menuNotification = computed(() => {
if (!store.currentMenu) return null;
let image: HTMLImageElement | null = null;
let id = "";
if (/^options[A-Z]/.test(store.currentMenu)) {
image = optionsImage!;
id = "options";
} else if (/^clock[A-Z]/.test(store.currentMenu)) {
image = clockImage!;
id = "clock";
} else if (/^user[A-Z]/.test(store.currentMenu)) {
image = userImage!;
id = "user";
} else if (/^touchScreen[A-Z]/.test(store.currentMenu)) {
image = touchScreenImage!;
id = "touchScreen";
}
for (const view of store.navigationStack) {
const menuMatch = view.match(/^(options|clock|user|touchScreen)(.+)$/);
if (menuMatch) {
const [, menu, submenu] = menuMatch;
const submenuKey = submenu!.charAt(0).toLowerCase() + submenu!.slice(1);
const imageMap: Record<string, HTMLImageElement> = {
optionsStartUp: startUpImage!,
optionsLanguage: languageImage!,
optionsGbaMode: gbaModeImage!,
};
if (imageMap[view]) {
stack.push({ id: `${menu}.${submenuKey}`, image: imageMap[view]! });
}
}
}
if (!image) return null;
return stack;
return {
image,
title: $t(`settings.${id}.title`),
description: $t(`settings.${id}.description`),
};
});
const IMAGES_MAP: Record<string, HTMLImageElement> = {
optionsStartUp: startUpImage!,
optionsLanguage: languageImage!,
optionsGbaMode: gbaModeImage!,
};
const submenuNotification = computed(() => {
if (!store.currentSubMenu) return null;
const image = IMAGES_MAP[store.currentSubMenu];
if (!image) return null;
const menuMatch = store.currentSubMenu.match(
/^(options|clock|user|touchScreen)(.+)$/,
);
if (!menuMatch) return null;
const [, menu, submenu] = menuMatch;
const submenuKey = submenu!.charAt(0).toLowerCase() + submenu!.slice(1);
return {
image,
title: $t(`settings.${menu}.${submenuKey}.title`),
description: $t(`settings.${menu}.${submenuKey}.description`),
};
});
useRender((ctx) => {
const stackSize = notificationStack.value.length;
let count = 1;
if (menuNotification.value) count++;
if (submenuNotification.value) count++;
ctx.translate(0, 144 - (stackSize - 1) * 16);
ctx.translate(0, 144 - (count - 1) * 16);
for (let i = 0; i < stackSize; i++) {
const notification = notificationStack.value[i]!;
renderNotification(
ctx,
mainNotification.value.image,
mainNotification.value.title,
mainNotification.value.description,
);
if (menuNotification.value) {
ctx.translate(0, 16);
renderNotification(
ctx,
notification.image,
$t(`settings.${notification.id}.title`),
$t(`settings.${notification.id}.description`),
menuNotification.value.image,
menuNotification.value.title,
menuNotification.value.description,
);
}
if (submenuNotification.value) {
ctx.translate(0, 16);
renderNotification(
ctx,
submenuNotification.value.image,
submenuNotification.value.title,
submenuNotification.value.description,
);
}
});