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
This commit is contained in:
@@ -343,7 +343,10 @@ const CardActions = ({
|
|||||||
if (accepted && game) onLaunch(game);
|
if (accepted && game) onLaunch(game);
|
||||||
})}
|
})}
|
||||||
><Icon.play /><span>{game ? 'Start now' : 'Mark as running'}</span></button>
|
><Icon.play /><span>{game ? 'Start now' : 'Mark as running'}</span></button>
|
||||||
<button className="ghost-btn" onClick={() => actions.addTime(nomination.id)}>
|
<button
|
||||||
|
className="ghost-btn"
|
||||||
|
onClick={() => actions.addTime(nomination.id, nomination.deadline)}
|
||||||
|
>
|
||||||
Add 5 more minutes
|
Add 5 more minutes
|
||||||
</button>
|
</button>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { listen, UnlistenFn } from '@tauri-apps/api/event';
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
callToPlayEvent,
|
callToPlayEvent,
|
||||||
|
extendDeadline,
|
||||||
pruneCallToPlayEvents,
|
pruneCallToPlayEvents,
|
||||||
reduceCallToPlayEvents,
|
reduceCallToPlayEvents,
|
||||||
} from '../lib/callToPlay';
|
} from '../lib/callToPlay';
|
||||||
@@ -22,7 +23,7 @@ export interface CallToPlayActions {
|
|||||||
leave: (callId: string) => void;
|
leave: (callId: string) => void;
|
||||||
cancel: (callId: string) => void;
|
cancel: (callId: string) => void;
|
||||||
startNow: (callId: string) => Promise<boolean>;
|
startNow: (callId: string) => Promise<boolean>;
|
||||||
addTime: (callId: string, minutes?: number) => void;
|
addTime: (callId: string, currentDeadline: number, minutes?: number) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UseCallToPlay {
|
export interface UseCallToPlay {
|
||||||
@@ -175,8 +176,8 @@ export const useCallToPlay = (username: string): UseCallToPlay => {
|
|||||||
leave: callId => void publish(callId, 'Leave'),
|
leave: callId => void publish(callId, 'Leave'),
|
||||||
cancel: callId => void publish(callId, 'Cancel'),
|
cancel: callId => void publish(callId, 'Cancel'),
|
||||||
startNow: callId => publish(callId, 'Start'),
|
startNow: callId => publish(callId, 'Start'),
|
||||||
addTime: (callId, minutes = 5) => void publish(callId, {
|
addTime: (callId, currentDeadline, minutes = 5) => void publish(callId, {
|
||||||
AddTime: { deadline: Date.now() + minutes * 60_000 },
|
AddTime: { deadline: extendDeadline(Date.now(), currentDeadline, minutes) },
|
||||||
}),
|
}),
|
||||||
}), [publish]);
|
}), [publish]);
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,12 @@ export const CHECKIN_LEAD_MS = 15 * 60_000;
|
|||||||
export const EXPIRED_RETENTION_MS = 5 * 60_000;
|
export const EXPIRED_RETENTION_MS = 5 * 60_000;
|
||||||
export const TERMINAL_RETENTION_MS = 15 * 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 CallToPlayPhase = 'now' | 'scheduled' | 'checkin';
|
||||||
export type CallToPlayStatus =
|
export type CallToPlayStatus =
|
||||||
| 'running'
|
| 'running'
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import {
|
|||||||
EXPIRED_RETENTION_MS,
|
EXPIRED_RETENTION_MS,
|
||||||
TERMINAL_RETENTION_MS,
|
TERMINAL_RETENTION_MS,
|
||||||
activeCallCount,
|
activeCallCount,
|
||||||
|
extendDeadline,
|
||||||
phaseOf,
|
phaseOf,
|
||||||
bumpTime,
|
bumpTime,
|
||||||
normalizeTimeInput,
|
normalizeTimeInput,
|
||||||
@@ -163,6 +164,20 @@ Deno.test('creator can extend, start, and cancel a call', () => {
|
|||||||
assertEquals(cancelled.terminalAt, NOW + 1, 'cancel timestamp');
|
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', () => {
|
Deno.test('reduction is order-independent and deduplicates events and messages', () => {
|
||||||
const message = event('message-event', 'Bob', {
|
const message = event('message-event', 'Bob', {
|
||||||
SendMessage: { message_id: 'message-1', text: 'Ready?' },
|
SendMessage: { message_id: 'message-1', text: 'Ready?' },
|
||||||
|
|||||||
Reference in New Issue
Block a user