From 0eb11db7d864d7bb358dcf826d9dbe19d7cbb46d Mon Sep 17 00:00:00 2001 From: pleb Date: Wed, 29 Oct 2025 09:52:00 -0700 Subject: [PATCH] head-to-head: add buttons --- .../tools/beatleader-compare/+page.svelte | 8 +- .../tools/beatleader-headtohead/+page.svelte | 134 +++++++++++++++++- 2 files changed, 134 insertions(+), 8 deletions(-) diff --git a/src/routes/tools/beatleader-compare/+page.svelte b/src/routes/tools/beatleader-compare/+page.svelte index 982f76e..c3b4c47 100644 --- a/src/routes/tools/beatleader-compare/+page.svelte +++ b/src/routes/tools/beatleader-compare/+page.svelte @@ -88,7 +88,7 @@ // Toast notification state let toastMessage = ''; let showToast = false; - let toastTimeout: number | null = null; + let toastTimeout: ReturnType | null = null; // Button feedback state - track which buttons are currently "lit up" let litButtons = new Set(); @@ -543,15 +543,15 @@ target="_blank" rel="noopener" title="Open in BeatSaver" - >BSRBS + title="!bsr" + >!bsr diff --git a/src/routes/tools/beatleader-headtohead/+page.svelte b/src/routes/tools/beatleader-headtohead/+page.svelte index 43842c9..d786247 100644 --- a/src/routes/tools/beatleader-headtohead/+page.svelte +++ b/src/routes/tools/beatleader-headtohead/+page.svelte @@ -72,6 +72,55 @@ let metaByHash: Record = {}; let loadingMeta = false; + // Toast notification state + let toastMessage = ''; + let showToast = false; + let toastTimeout: ReturnType | null = null; + + // Button feedback state - track which buttons are currently "lit up" + let litButtons = new Set(); + + function showToastMessage(message: string) { + // Clear any existing toast + if (toastTimeout) { + clearTimeout(toastTimeout); + } + + toastMessage = message; + showToast = true; + + // Auto-hide toast after 3 seconds + toastTimeout = setTimeout(() => { + showToast = false; + toastMessage = ''; + }, 3000); + } + + function lightUpButton(buttonId: string) { + litButtons.add(buttonId); + // Reassign here too to trigger reactivity immediately + litButtons = litButtons; + // Remove the lighting effect after 1 second + setTimeout(() => { + litButtons.delete(buttonId); + litButtons = litButtons; // Trigger reactivity + }, 1000); + } + + async function copyBsrCommand(key: string, hash: string) { + try { + const bsrCommand = `!bsr ${key}`; + await navigator.clipboard.writeText(bsrCommand); + + // Show success feedback with the actual command + showToastMessage(`Copied "${bsrCommand}" to clipboard`); + lightUpButton(`bsr-${hash}`); + } catch (err) { + console.error('Failed to copy to clipboard:', err); + showToastMessage('Failed to copy to clipboard'); + } + } + function normalizeAccuracy(value: number | undefined): number | null { if (value === undefined || value === null) return null; return value <= 1 ? value * 100 : value; @@ -192,7 +241,8 @@ if (!bMap.has(key)) continue; const bScore = bMap.get(key)!; const [hashLower, diffName, modeName] = key.split('|'); - const hash = (aScore.leaderboard?.song?.hash ?? bScore.leaderboard?.song?.hash ?? hashLower).toString(); + const rawHash = (aScore.leaderboard?.song?.hash ?? bScore.leaderboard?.song?.hash ?? hashLower); + const hash = String(rawHash).toLowerCase(); const tA = parseTimeset(aScore.timeset); const tB = parseTimeset(bScore.timeset); const accA = normalizeAccuracy((aScore.accuracy ?? aScore.acc) as number | undefined); @@ -638,11 +688,32 @@ {/if}
-
- + BL + target="_blank" + rel="noopener" + title="Open in BeatLeader" + >BL + BS +
@@ -663,6 +734,13 @@ {/if} + +{#if showToast} +
+ {toastMessage} +
+{/if} +