Files
pihkaal-me/app/components/Contact/BottomScreen/BottomScreen.vue

135 lines
3.2 KiB
Vue

<script setup lang="ts">
// TODO: buttons should take in account opacity
import Background from "./Background.vue";
import Buttons from "./Buttons.vue";
import ButtonSelector from "~/components/Common/ButtonSelector.vue";
const store = useContactStore();
const { open: openModal, state: modalState } = useConfirmationModal();
const ACTIONS = {
github: ["Open", "Github profile", "https://github.com/pihkaal"],
email: ["Copy", "Email", "hello@pihkaal.me"],
website: ["Copy", "Website link", "https://pihkaal.me"],
cv: ["Open", "CV", "https://pihkaal.me/cv"],
} as const satisfies Record<
string,
[action: "Copy" | "Open", verb: string, content: string]
>;
const { selectedButton, selectorPosition } = useButtonNavigation({
buttons: {
github: [26, 27, 202, 42],
email: [26, 59, 202, 42],
website: [26, 91, 202, 42],
cv: [26, 123, 202, 42],
},
navigation: {
github: {
down: "email",
},
email: {
up: "github",
down: "website",
},
website: {
up: "email",
down: "cv",
},
cv: {
up: "website",
},
},
initialButton: "github",
onButtonClick: (button) => {
actionateButton(button);
},
disabled: computed(() => store.isIntro || store.isOutro),
});
const actionateButton = async (button: (typeof selectedButton)["value"]) => {
const [action, verb, content] = ACTIONS[button];
if (action === "Copy") {
try {
await navigator.clipboard.writeText(content);
store.pushNotification(`${verb} copied to clipboard`);
} catch (error) {
console.error("Failed to copy to clipboard:", error);
}
} else {
const url = content.replace(/^https?:\/\//, "");
openModal({
text: `Open ${url}?`,
onConfirm: async () => {
store.pushNotification(`${verb} opened`);
await sleep(100);
await navigateTo(content, { open: { target: "_blank " } });
},
});
}
};
// TODO: use @activate events from common buttons
const QUIT_BUTTON: Rect = [31, 172, 80, 18];
const OK_BUTTON: Rect = [144, 172, 80, 18];
useScreenClick((x, y) => {
if (modalState.value.isOpen || store.isIntro || store.isOutro) {
return;
}
if (rectContains(QUIT_BUTTON, [x, y])) {
store.animateOutro();
} else if (rectContains(OK_BUTTON, [x, y])) {
actionateButton(selectedButton.value);
}
});
useKeyDown((key) => {
if (modalState.value.isOpen || store.isIntro || store.isOutro) return;
switch (key) {
case "NDS_B":
store.animateOutro();
break;
}
});
</script>
<template>
<Background />
<Buttons />
<ButtonSelector
:rect="selectorPosition"
:opacity="
store.isIntro ? store.intro.stage3Opacity : store.outro.stage1Opacity
"
/>
<CommonBars
title="Choose a Chat Room to join."
:opacity="
store.isIntro ? store.intro.stage3Opacity : store.outro.stage2Opacity
"
:y-offset="store.isIntro ? store.intro.barOffsetY : 0"
/>
<CommonConfirmationModal />
<CommonButtons
:y-offset="
store.isIntro ? store.intro.barOffsetY : modalState.buttonsYOffset
"
:opacity="
store.isIntro
? store.intro.stage3Opacity
: store.isOutro
? store.outro.stage2Opacity
: 1
"
b-label="Quit"
:a-label="ACTIONS[selectedButton][0]"
/>
</template>