remove reset button, move auto save indicator in velxio

master
a2nr 2026-04-15 20:03:36 +07:00
parent 998472f996
commit 65c12bc716
2 changed files with 35 additions and 29 deletions

View File

@ -27,7 +27,8 @@
const LONG_PRESS_MS = 400; const LONG_PRESS_MS = 400;
const DOUBLE_TAP_MS = 300; const DOUBLE_TAP_MS = 300;
const HOLDING_TIMEOUT_MS = 5000; const HOLDING_TIMEOUT_MS = 5000;
const CURSOR_OFFSET_Y = -(parseInt(env.PUBLIC_CURSOR_OFFSET_Y || '50', 10)); const BASE_OFFSET_Y = -(parseInt(env.PUBLIC_CURSOR_OFFSET_Y || '50', 10));
let currentOffset = $derived(isTouchDevice ? BASE_OFFSET_Y : 0);
/** /**
* State machine: * State machine:
@ -46,12 +47,18 @@
$effect(() => { $effect(() => {
if (typeof window === 'undefined') return; if (typeof window === 'undefined') return;
const mql = window.matchMedia('(hover: none) and (pointer: coarse)'); const mql = window.matchMedia('(hover: none) and (pointer: coarse)');
isTouchDevice = mql.matches; const checkTouch = () => {
const handler = (e: MediaQueryListEvent) => { isTouchDevice = mql.matches && window.innerWidth < 768;
isTouchDevice = e.matches; };
checkTouch();
mql.addEventListener('change', checkTouch);
window.addEventListener('resize', checkTouch);
return () => {
mql.removeEventListener('change', checkTouch);
window.removeEventListener('resize', checkTouch);
}; };
mql.addEventListener('change', handler);
return () => mql.removeEventListener('change', handler);
}); });
function getIframeTarget(x: number, y: number): Element | null { function getIframeTarget(x: number, y: number): Element | null {
@ -142,7 +149,7 @@
if (!overlayEl) return; if (!overlayEl) return;
const rect = overlayEl.getBoundingClientRect(); const rect = overlayEl.getBoundingClientRect();
crosshairX = viewportX - rect.left; crosshairX = viewportX - rect.left;
crosshairY = viewportY - rect.top + CURSOR_OFFSET_Y; crosshairY = viewportY - rect.top + currentOffset;
} }
function getCrosshairViewport(): { x: number; y: number } { function getCrosshairViewport(): { x: number; y: number } {

View File

@ -101,7 +101,7 @@
// Auto-save Velxio state periodically // Auto-save Velxio state periodically
$effect(() => { $effect(() => {
if (velxioReady && auth.isLoggedIn && !showSolution) { if (velxioReady && $authLoggedIn && !showSolution) {
const interval = setInterval(() => { const interval = setInterval(() => {
const state = getVelxioState(); const state = getVelxioState();
if (!state) return; if (!state) return;
@ -921,17 +921,14 @@
Hubungi guru jika masalah berlanjut. Hubungi guru jika masalah berlanjut.
</div> </div>
{:else} {:else}
<div class="velxio-toolbar"> {#if $authLoggedIn}
<button type="button" class="btn btn-secondary btn-sm" onclick={handleReset}>Reset</button> <div class="storage-indicator-inline" title={velxioSaving ? "Menyimpan draf..." : "Draf tersimpan di browser"}>
{#if auth.isLoggedIn} <span class="indicator-icon" class:saving={velxioSaving}>
<div class="storage-indicator-inline" title={velxioSaving ? "Menyimpan draf..." : "Draf tersimpan di browser"}> {velxioSaving ? '●' : '☁'}
<span class="indicator-icon" class:saving={velxioSaving}> </span>
{velxioSaving ? '●' : '☁'} <span class="indicator-text">Auto-save</span>
</span> </div>
<span class="indicator-text">Auto-save</span> {/if}
</div>
{/if}
</div>
<!-- svelte-ignore a11y_missing_attribute --> <!-- svelte-ignore a11y_missing_attribute -->
<iframe <iframe
class="velxio-iframe" class="velxio-iframe"
@ -1243,22 +1240,23 @@
} }
/* ── Velxio (Arduino simulator) ─────────────────────── */ /* ── Velxio (Arduino simulator) ─────────────────────── */
.velxio-toolbar {
display: flex;
align-items: center;
gap: 0.5rem;
padding: 0.4rem 0.5rem;
border-bottom: 1px solid var(--color-border);
flex-shrink: 0;
}
.storage-indicator-inline { .storage-indicator-inline {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 6px; gap: 6px;
font-size: 0.7rem; font-size: 0.75rem;
color: var(--color-text-muted); color: var(--color-text-muted);
background: var(--color-bg-secondary);
padding: 3px 10px;
border-radius: 12px;
border: 1px solid var(--color-border);
position: absolute;
bottom: 1rem;
right: 1.5rem;
z-index: 10;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.15);
pointer-events: none; pointer-events: none;
margin-left: auto; opacity: 0.8;
} }
.storage-indicator-inline .indicator-icon { .storage-indicator-inline .indicator-icon {
line-height: 1; line-height: 1;
@ -1278,6 +1276,7 @@
flex-direction: column; flex-direction: column;
flex: 1; flex: 1;
min-height: 0; min-height: 0;
position: relative;
} }
.velxio-panel.tab-hidden { .velxio-panel.tab-hidden {
display: none; display: none;