diff --git a/app/components/Settings/BottomScreen/BottomScreen.vue b/app/components/Settings/BottomScreen/BottomScreen.vue
index 5391dc4..1c4079b 100644
--- a/app/components/Settings/BottomScreen/BottomScreen.vue
+++ b/app/components/Settings/BottomScreen/BottomScreen.vue
@@ -1,44 +1,9 @@
-
-
+
diff --git a/app/components/Settings/BottomScreen/Menus/Clock/Menu.vue b/app/components/Settings/BottomScreen/Menus/Clock/Menu.vue
index 004662d..3bccb0b 100644
--- a/app/components/Settings/BottomScreen/Menus/Clock/Menu.vue
+++ b/app/components/Settings/BottomScreen/Menus/Clock/Menu.vue
@@ -34,7 +34,7 @@ const isAnyOtherMenuOpen = computed(() =>
settingsStore.isAnyOtherMenuOpen("clock"),
);
-const animation = useMenuAnimation(isOpen);
+const animation = useMenuAnimation("clock", isOpen);
useRender((ctx) => {
ctx.translate(props.x, props.y);
diff --git a/app/components/Settings/BottomScreen/Menus/Menus.vue b/app/components/Settings/BottomScreen/Menus/Menus.vue
index 3b92df8..f1f8962 100644
--- a/app/components/Settings/BottomScreen/Menus/Menus.vue
+++ b/app/components/Settings/BottomScreen/Menus/Menus.vue
@@ -1,10 +1,16 @@
-
-
-
-
+
+
+
+
+
-
+
+
+
diff --git a/app/components/Settings/BottomScreen/Menus/Options/Menu.vue b/app/components/Settings/BottomScreen/Menus/Options/Menu.vue
index 21d86ac..cce21df 100644
--- a/app/components/Settings/BottomScreen/Menus/Options/Menu.vue
+++ b/app/components/Settings/BottomScreen/Menus/Options/Menu.vue
@@ -34,7 +34,7 @@ const isAnyOtherMenuOpen = computed(() =>
settingsStore.isAnyOtherMenuOpen("options"),
);
-const animation = useMenuAnimation(isOpen);
+const animation = useMenuAnimation("options", isOpen);
useRender((ctx) => {
ctx.translate(props.x, props.y);
diff --git a/app/components/Settings/BottomScreen/Menus/User/Menu.vue b/app/components/Settings/BottomScreen/Menus/User/Menu.vue
index 52ea109..d072d0b 100644
--- a/app/components/Settings/BottomScreen/Menus/User/Menu.vue
+++ b/app/components/Settings/BottomScreen/Menus/User/Menu.vue
@@ -37,7 +37,7 @@ const isAnyOtherMenuOpen = computed(() =>
settingsStore.isAnyOtherMenuOpen("user"),
);
-const animation = useMenuAnimation(isOpen);
+const animation = useMenuAnimation("user", isOpen);
useRender((ctx) => {
ctx.translate(props.x, props.y);
diff --git a/app/components/Settings/TopScreen/Notifications.vue b/app/components/Settings/TopScreen/Notifications.vue
index eb902e4..5c6c080 100644
--- a/app/components/Settings/TopScreen/Notifications.vue
+++ b/app/components/Settings/TopScreen/Notifications.vue
@@ -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 = {
- 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 = {
+ 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,
+ );
}
});
diff --git a/app/composables/useMenuAnimation.ts b/app/composables/useMenuAnimation.ts
index e15ccfb..f521a9b 100644
--- a/app/composables/useMenuAnimation.ts
+++ b/app/composables/useMenuAnimation.ts
@@ -1,33 +1,49 @@
import gsap from "gsap";
-export const useMenuAnimation = (isOpen: Ref) => {
- const animation = reactive({
+export const useMenuAnimation = (key: string, isOpen: Ref) => {
+ const animation = useState(`animation-${key}`, () => ({
playing: false,
stage1Offset: 48,
stage2Offset: 48,
- });
+ }));
watch(isOpen, (current, previous) => {
const duration = 0.1;
const timeline = gsap.timeline({
onStart: () => {
- animation.playing = true;
+ animation.value.playing = true;
},
onComplete: () => {
- animation.playing = false;
+ animation.value.playing = false;
},
});
if (current === true && previous === false) {
timeline
- .fromTo(animation, { stage1Offset: 48 }, { stage1Offset: 0, duration })
- .fromTo(animation, { stage2Offset: 48 }, { stage2Offset: 0, duration });
+ .fromTo(
+ animation.value,
+ { stage1Offset: 48 },
+ { stage1Offset: 0, duration },
+ )
+ .fromTo(
+ animation.value,
+ { stage2Offset: 48 },
+ { stage2Offset: 0, duration },
+ );
} else if (current === false && previous === true) {
timeline
- .fromTo(animation, { stage2Offset: 0 }, { stage2Offset: 48, duration })
- .fromTo(animation, { stage1Offset: 0 }, { stage1Offset: 48, duration });
+ .fromTo(
+ animation.value,
+ { stage2Offset: 0 },
+ { stage2Offset: 48, duration },
+ )
+ .fromTo(
+ animation.value,
+ { stage1Offset: 0 },
+ { stage1Offset: 48, duration },
+ );
}
});
- return animation;
+ return animation.value;
};
diff --git a/app/stores/settings.ts b/app/stores/settings.ts
index d3327b9..bef5c8d 100644
--- a/app/stores/settings.ts
+++ b/app/stores/settings.ts
@@ -1,37 +1,28 @@
export const useSettingsStore = defineStore("settings", {
state: () => ({
- activeMenu: null as string | null,
- navigationStack: [] as string[],
+ currentMenu: null as string | null,
+ currentSubMenu: null as string | null,
}),
getters: {
isMenuOpen: (state) => (menu: string) => {
- if (!state.activeMenu) return false;
- return new RegExp(`^${menu}[A-Z]`).test(state.activeMenu);
+ if (!state.currentMenu) return false;
+ return new RegExp(`^${menu}[A-Z]`).test(state.currentMenu);
},
isAnyOtherMenuOpen: (state) => (excludeMenu: string) => {
- if (!state.activeMenu) return false;
+ if (!state.currentMenu) return false;
return ["options", "clock", "user", "touchScreen"]
.filter((m) => m !== excludeMenu)
- .some((m) => new RegExp(`^${m}[A-Z]`).test(state.activeMenu!));
- },
-
- currentView: (state) => {
- if (state.navigationStack.length === 0) return "menu";
- return state.navigationStack[state.navigationStack.length - 1];
+ .some((m) => new RegExp(`^${m}[A-Z]`).test(state.currentMenu!));
},
},
actions: {
setActiveMenu(menu: string | null) {
- this.activeMenu = menu;
+ this.currentMenu = menu;
},
- pushNavigation(view: string) {
- this.navigationStack.push(view);
- },
-
- popNavigation() {
- this.navigationStack.pop();
+ setCurrentSubMenu(submenu: string | null) {
+ this.currentSubMenu = submenu;
},
},
});
diff --git a/i18n/locales/en.json b/i18n/locales/en.json
index a6d5e1b..f753ec6 100644
--- a/i18n/locales/en.json
+++ b/i18n/locales/en.json
@@ -1,9 +1,7 @@
{
"settings": {
- "main": {
- "title": "Settings",
- "description": "Change system settings here. Select\nthe settings you'd like to change."
- },
+ "title": "Settings",
+ "description": "Change system settings here. Select\nthe settings you'd like to change.",
"options": {
"title": "Options",