Files
pihkaal-me/app/components/Settings/BottomScreen/Menus/Clock/Achievements.vue

216 lines
5.5 KiB
Vue

<script setup lang="ts">
import { SettingsBottomScreenNumberInput as NumberInput } from "#components";
import { ICONS } from "~/utils/icons";
import gsap from "gsap";
const APP_COLOR_TO_FONT_COLOR: Record<string, string> = {
"#61829a": "#fbfbfb", // cyan
"#ba4900": "#fbe3d3", // maroon
"#fb0018": "#fbcbd3", // red
"#fb8afb": "#fbebfb", // pink
"#fb9200": "#fbf3e3", // orange
"#f3e300": "#fbfbdb", // yellow
"#aafb00": "#fbfbfb", // lime
"#00fb00": "#fbfbfb", // green
"#00a238": "#fbfbfb", // dark green
"#49db8a": "#ebfbf3", // duck
"#30baf3": "#fbfbfb", // light blue
"#0059f3": "#dbebfb", // blue
"#000092": "#ebebfb", // dark blue
"#8a00d3": "#f3dbfb", // purple
"#d300eb": "#fbfbfb", // magenta
"#fb0092": "#ebe3f3", // fuschia
};
const { assets } = useAssets();
const achievementAssets =
assets.images.settings.bottomScreen.clock.achievements;
const { onRender, onClick } = useScreen();
const app = useAppStore();
const store = useSettingsStore();
const achievements = useAchievementsStore();
const achievementsScreen = useAchievementsScreen();
const confirmationModal = useConfirmationModal();
const isAnimating = ref(true);
const bLabel = ref($t("common.goBack"));
const aLabel = ref($t("common.select"));
const SLIDE_OFFSET = 96;
const SLIDE_DURATION = 0.25;
const ARROW_SLIDE_DELAY = 0.15;
const ARROW_SLIDE_DURATION = 0.167;
const VIEW_ALL_OFFSET = -20;
const animation = reactive({
offsetY: SLIDE_OFFSET,
opacity: 0,
viewAllOffsetY: VIEW_ALL_OFFSET,
});
const obtainedRef =
useTemplateRef<InstanceType<typeof NumberInput>>("obtained");
const totalRef = useTemplateRef<InstanceType<typeof NumberInput>>("total");
const animateIntro = async () => {
isAnimating.value = true;
await Promise.all([
obtainedRef.value?.animateIntro(),
totalRef.value?.animateIntro(),
gsap
.timeline()
.to(animation, { offsetY: 0, duration: SLIDE_DURATION, ease: "none" }, 0)
.to(animation, { opacity: 1, duration: SLIDE_DURATION, ease: "none" }, 0)
.call(
() => {
bLabel.value = $t("common.cancel");
aLabel.value = $t("common.reset");
},
[],
SUBMENU_LABEL_CHANGE_DELAY,
)
.to(
animation,
{ viewAllOffsetY: 0, duration: ARROW_SLIDE_DURATION, ease: "none" },
SLIDE_DURATION + ARROW_SLIDE_DELAY,
),
]);
isAnimating.value = false;
};
const animateOutro = async () => {
isAnimating.value = true;
await Promise.all([
obtainedRef.value?.animateOutro(),
totalRef.value?.animateOutro(),
gsap
.timeline()
.to(
animation,
{
viewAllOffsetY: VIEW_ALL_OFFSET,
duration: ARROW_SLIDE_DURATION,
ease: "none",
},
0,
)
.to(
animation,
{ offsetY: SLIDE_OFFSET, duration: SLIDE_DURATION, ease: "none" },
0,
)
.to(animation, { opacity: 0, duration: SLIDE_DURATION, ease: "none" }, 0),
]);
};
onMounted(() => {
animateIntro();
});
const handleActivateB = async () => {
if (isAnimating.value) return;
await animateOutro();
store.closeSubMenu();
};
const handleReset = () => {
if (isAnimating.value) return;
confirmationModal.open({
text: $t("settings.clock.achievements.resetConfirmation"),
bLabel: $t("common.no"),
aLabel: $t("common.yes"),
onClosed: (choice) => {
if (choice === "A") {
achievements.reset();
}
},
});
};
const handleVisitAll = () => {
if (isAnimating.value) return;
assets.audio.menuOpen.play();
achievementsScreen.animateFadeToBlackIntro();
};
onClick((x, y) => {
if (isAnimating.value) return;
const viewAllRect = achievementAssets.viewAllButton.rect;
if (rectContains([127, 2, viewAllRect.width, viewAllRect.height], [x, y])) {
handleVisitAll();
}
});
useKeyDown(({ key }) => {
if (isAnimating.value) return;
if (key === "NDS_X") {
handleVisitAll();
}
});
onRender((ctx) => {
// slash divider
ctx.globalAlpha = animation.opacity;
ctx.translate(0, animation.offsetY);
ctx.fillStyle = "#515151";
ctx.fillRect(7 * 16 - 1, 4 * 16 - 1, 16 * 3 + 1, 16 * 3 + 1);
ctx.fillStyle = achievements.allObtained ? app.color.hex : "#797979";
ctx.fillRect(7 * 16, 4 * 16, 16 * 3 - 1, 16 * 3 - 1);
ctx.font = "39px NDS39";
ctx.letterSpacing = "2px";
ctx.fillStyle = achievements.allObtained
? APP_COLOR_TO_FONT_COLOR[app.color.hex]!
: "#fbfbfb";
ctx.fillText("/", 7 * 16 + 3, 4 * 16 + 4 + 39);
});
onRender((ctx) => {
ctx.translate(0, animation.viewAllOffsetY);
achievementAssets.viewAllButton.draw(ctx, 127, 2);
achievementAssets.smallTrophy.draw(ctx, 131, 6);
ctx.font = "10px NDS10";
ctx.fillStyle = "#010101";
const label = `${ICONS.X} ${$t("settings.clock.achievements.viewAll")}`;
fillTextHCentered(
ctx,
label,
145,
7 + 9,
achievementAssets.viewAllButton.rect.width - 18,
);
}, 1000);
</script>
<template>
<NumberInput
ref="obtained"
:model-value="achievements.unlocked.length"
:title="$t('settings.clock.achievements.obtained')"
:x="4 * 16 - 1"
:selected="achievements.allObtained"
:disabled="true"
/>
<NumberInput
ref="total"
:model-value="ACHIEVEMENTS.length"
:title="$t('settings.clock.achievements.total')"
:x="9 * 16 - 1"
:selected="achievements.allObtained"
:disabled="true"
/>
<CommonButtons
:y-offset="confirmationModal.buttonsYOffset + store.submenuButtonsOffsetY"
:b-label="bLabel"
:a-label="aLabel"
@activate-b="handleActivateB()"
@activate-a="handleReset()"
/>
</template>