From 8d3affe19caa54fcb8b5388e2a311739e3c94617 Mon Sep 17 00:00:00 2001 From: ddidderr Date: Thu, 23 Jul 2026 18:05:21 +0200 Subject: [PATCH] fix(call-to-play): extend from the current deadline Pass the effective nomination deadline into the Add time action and extend from whichever is later: that deadline or the current time. This preserves remaining time when a call becomes ready early while still giving an overdue call a fresh five-minute window. Test Plan: - just fmt - just frontend-test - just build - git diff --cached --check --- .../src/components/calltoplay/NominationCard.tsx | 5 ++++- .../src/hooks/useCallToPlay.ts | 7 ++++--- .../lanspread-tauri-deno-ts/src/lib/callToPlay.ts | 6 ++++++ .../tests/callToPlay.test.ts | 15 +++++++++++++++ 4 files changed, 29 insertions(+), 4 deletions(-) diff --git a/crates/lanspread-tauri-deno-ts/src/components/calltoplay/NominationCard.tsx b/crates/lanspread-tauri-deno-ts/src/components/calltoplay/NominationCard.tsx index 834fdb9..2eff269 100644 --- a/crates/lanspread-tauri-deno-ts/src/components/calltoplay/NominationCard.tsx +++ b/crates/lanspread-tauri-deno-ts/src/components/calltoplay/NominationCard.tsx @@ -343,7 +343,10 @@ const CardActions = ({ if (accepted && game) onLaunch(game); })} >{game ? 'Start now' : 'Mark as running'} - diff --git a/crates/lanspread-tauri-deno-ts/src/hooks/useCallToPlay.ts b/crates/lanspread-tauri-deno-ts/src/hooks/useCallToPlay.ts index 0e7e388..6e9f92a 100644 --- a/crates/lanspread-tauri-deno-ts/src/hooks/useCallToPlay.ts +++ b/crates/lanspread-tauri-deno-ts/src/hooks/useCallToPlay.ts @@ -4,6 +4,7 @@ import { listen, UnlistenFn } from '@tauri-apps/api/event'; import { callToPlayEvent, + extendDeadline, pruneCallToPlayEvents, reduceCallToPlayEvents, } from '../lib/callToPlay'; @@ -22,7 +23,7 @@ export interface CallToPlayActions { leave: (callId: string) => void; cancel: (callId: string) => void; startNow: (callId: string) => Promise; - addTime: (callId: string, minutes?: number) => void; + addTime: (callId: string, currentDeadline: number, minutes?: number) => void; } export interface UseCallToPlay { @@ -175,8 +176,8 @@ export const useCallToPlay = (username: string): UseCallToPlay => { leave: callId => void publish(callId, 'Leave'), cancel: callId => void publish(callId, 'Cancel'), startNow: callId => publish(callId, 'Start'), - addTime: (callId, minutes = 5) => void publish(callId, { - AddTime: { deadline: Date.now() + minutes * 60_000 }, + addTime: (callId, currentDeadline, minutes = 5) => void publish(callId, { + AddTime: { deadline: extendDeadline(Date.now(), currentDeadline, minutes) }, }), }), [publish]); diff --git a/crates/lanspread-tauri-deno-ts/src/lib/callToPlay.ts b/crates/lanspread-tauri-deno-ts/src/lib/callToPlay.ts index 25d62bf..275a1f1 100644 --- a/crates/lanspread-tauri-deno-ts/src/lib/callToPlay.ts +++ b/crates/lanspread-tauri-deno-ts/src/lib/callToPlay.ts @@ -9,6 +9,12 @@ export const CHECKIN_LEAD_MS = 15 * 60_000; export const EXPIRED_RETENTION_MS = 5 * 60_000; export const TERMINAL_RETENTION_MS = 15 * 60_000; +export const extendDeadline = ( + now: number, + currentDeadline: number, + durationMinutes = 5, +): number => Math.max(now, currentDeadline) + durationMinutes * 60_000; + export type CallToPlayPhase = 'now' | 'scheduled' | 'checkin'; export type CallToPlayStatus = | 'running' diff --git a/crates/lanspread-tauri-deno-ts/tests/callToPlay.test.ts b/crates/lanspread-tauri-deno-ts/tests/callToPlay.test.ts index 8cc21cc..025fe4c 100644 --- a/crates/lanspread-tauri-deno-ts/tests/callToPlay.test.ts +++ b/crates/lanspread-tauri-deno-ts/tests/callToPlay.test.ts @@ -3,6 +3,7 @@ import { EXPIRED_RETENTION_MS, TERMINAL_RETENTION_MS, activeCallCount, + extendDeadline, phaseOf, bumpTime, normalizeTimeInput, @@ -163,6 +164,20 @@ Deno.test('creator can extend, start, and cancel a call', () => { assertEquals(cancelled.terminalAt, NOW + 1, 'cancel timestamp'); }); +Deno.test('adding time extends from the current deadline or the current time', () => { + const futureDeadline = NOW + 30 * 60_000; + assertEquals( + extendDeadline(NOW, futureDeadline), + futureDeadline + 5 * 60_000, + 'ready-early call keeps its remaining time', + ); + assertEquals( + extendDeadline(NOW, NOW - 60_000), + NOW + 5 * 60_000, + 'overdue call gets five minutes from now', + ); +}); + Deno.test('reduction is order-independent and deduplicates events and messages', () => { const message = event('message-event', 'Bob', { SendMessage: { message_id: 'message-1', text: 'Ready?' },