feat: move top screen components to own folder, and implement calendar

This commit is contained in:
2025-11-10 14:24:20 +01:00
parent c465679b47
commit 009b19e404
6 changed files with 105 additions and 41 deletions

View File

@@ -1,45 +1,24 @@
<!-- <template> <script setup lang="ts">
const showStats = ref(false);
</script>
<template>
<div <div
:style="{ :style="{
position: 'relative', display: 'flex',
width: '256px', flexDirection: 'column',
transformOrigin: 'top left', gap: '4px',
}" }"
> >
<div <div :style="{ display: 'flex', alignItems: 'center', gap: '4px' }">
:style="{ <input id="statsCheckbox" type="checkbox" v-model="showStats" />
boxSizing: 'border-box', <label for="statsCheckbox">Stats</label>
width: '256px', </div>
height: '192px',
}"
>
<img src="/assets/background.png" />
<div <div>
:style="{ <TopScreen>
position: 'absolute', <Stats v-if="showStats" />
display: 'grid', </TopScreen>
gap: '1px',
top: 'calc(4 * 16px)',
right: 'calc(1 * 16px + 1px)',
gridTemplateRows: 'repeat(5, 15px)',
gridTemplateColumns: 'repeat(7, 15px)',
}"
>
<div
v-for="i in 5 * 7"
:key="i"
:style="{ display: 'flex', flexDirection: 'column' }"
>
<span :style="{ fontSize: '12px' }">8</span>
</div>
</div>
</div> </div>
</div> </div>
</template> -->
<template>
<Screen>
<Background />
<Stats />
</Screen>
</template> </template>

View File

@@ -36,7 +36,11 @@ const renderFrame = (timestamp: number) => {
ctx.clearRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); ctx.clearRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
for (const callback of renderCallbacks) { for (const callback of renderCallbacks) {
ctx.save();
callback(ctx); callback(ctx);
ctx.restore();
} }
lastRealFrameTime = Date.now() - start; lastRealFrameTime = Date.now() - start;

View File

@@ -31,7 +31,7 @@ useRender((ctx) => {
const LINE_HEIGHT = 12; const LINE_HEIGHT = 12;
ctx.fillStyle = "red"; ctx.fillStyle = "red";
ctx.fillRect(props.x - 2, props.y, 140, LINE_COUNT * LINE_HEIGHT + 3); ctx.fillRect(props.x - 2, props.y, 120, LINE_COUNT * LINE_HEIGHT + 3);
let textY = props.y; let textY = props.y;
@@ -59,5 +59,3 @@ useRender((ctx) => {
); );
}); });
</script> </script>
<template></template>

View File

@@ -1,4 +1,4 @@
<script lang="ts" setup> <script setup lang="ts">
const backgroundImage = useTemplateRef("backgroundImage"); const backgroundImage = useTemplateRef("backgroundImage");
useRender((ctx) => { useRender((ctx) => {

View File

@@ -0,0 +1,75 @@
<script setup lang="ts">
// NOTE: calendar background is handled by TopScreenBackground
const lastRowImage = useTemplateRef("lastRowImage");
const daySelectorImage = useTemplateRef("daySelectorImage");
useRender((ctx) => {
if (!lastRowImage.value || !daySelectorImage.value) return;
ctx.fillStyle = "black";
ctx.font = "7px NDS7";
const CALENDAR_COLS = 7;
const CALENDAR_ROWS = 5;
const CALENDAR_LEFT = 128;
const CALENDAR_TOP = 64;
ctx.fillStyle = "#343434";
const now = new Date();
const year = now.getFullYear();
const month = now.getMonth();
const firstDay = new Date(year, month, 1).getDay();
const daysInMonth = new Date(year, month + 1, 0).getDate();
const extraRow = CALENDAR_COLS * CALENDAR_ROWS - daysInMonth - firstDay < 0;
if (extraRow) {
ctx.drawImage(lastRowImage.value, CALENDAR_LEFT - 3, CALENDAR_TOP + 79);
}
for (let col = 0; col < CALENDAR_ROWS + (extraRow ? 1 : 0); col += 1) {
for (let row = 0; row < CALENDAR_COLS; row += 1) {
const cellIndex = col * CALENDAR_COLS + row;
const day = cellIndex - firstDay + 1;
if (day > 0 && day <= daysInMonth) {
const dayText = day.toString();
const { actualBoundingBoxRight: width } = ctx.measureText(dayText);
const cellLeft = CALENDAR_LEFT + row * 16;
const cellTop = CALENDAR_TOP + col * 16;
if (now.getDate() === day) {
ctx.drawImage(daySelectorImage.value, cellLeft, cellTop);
}
ctx.fillText(
dayText,
cellLeft + Math.floor((15 - width) / 2),
cellTop + 11,
);
}
}
}
ctx.fillStyle = "black";
ctx.font = "9px NDS9";
ctx.letterSpacing = "2px";
const timeText = `${month}/${year}`;
const { actualBoundingBoxRight: width } = ctx.measureText(timeText);
ctx.fillText(
timeText,
CALENDAR_LEFT + Math.floor((111 - width) / 2),
CALENDAR_TOP - 20,
);
});
</script>
<template>
<img ref="lastRowImage" src="/assets/calendar_last-row.png" hidden />
<img ref="daySelectorImage" src="/assets/calendar_day-selector.png" hidden />
</template>

View File

@@ -0,0 +1,8 @@
<template>
<Screen>
<TopScreenBackground />
<TopScreenCalendar />
<slot />
</Screen>
</template>