Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
a1ca67b
fix(calls): keep a left call from rejoining on its own
peterchinman Oct 21, 2026
bad2ab1
fix(ios): make Leave always end the native call, its PiP and its room
peterchinman Oct 21, 2026
8ab2271
fix(calls): evict stranded rooms and end calls left with one person
peterchinman Oct 21, 2026
dfe1714
feat(calls): ask a user alone in a call whether to stay
peterchinman Oct 21, 2026
c910aa2
fix(calls): stop logging participant identities in call webhooks
peterchinman Oct 21, 2026
3507038
Merge remote-tracking branch 'origin/main' into peter/orphan-call
peterchinman Oct 21, 2026
85d3781
fix(calls): close review gaps in leaving, PiP teardown and the alone …
peterchinman Oct 22, 2026
f5dc19c
Merge remote-tracking branch 'origin/main' into peter/orphan-call
peterchinman Oct 22, 2026
19e0955
fix(calls): restore the leave result initializer
peterchinman Oct 22, 2026
f2214c2
Merge remote-tracking branch 'origin/main' into peter/orphan-call
peterchinman Oct 22, 2026
ec3046f
Merge remote-tracking branch 'origin/main' into peter/orphan-call
peterchinman Oct 23, 2026
a2deeb1
test(calls): make the alone prompt test tolerate a live countdown
peterchinman Oct 23, 2026
f1d7ca6
Merge remote-tracking branch 'origin/main' into peter/orphan-call
peterchinman Oct 23, 2026
996dbf4
Merge remote-tracking branch 'origin/main' into peter/orphan-call
peterchinman Oct 26, 2026
5af4f6c
refactor(calls): move the alone timeout to its own pull request
peterchinman Oct 26, 2026
7d61db6
feat(calls): end a call left to one person unless they choose to stay
peterchinman Oct 26, 2026
dcbf3ff
feat(calls): ask a user alone in a call whether to stay
peterchinman Oct 26, 2026
ee430a7
feat(ios): show the alone-in-call warning as a native alert
peterchinman Oct 26, 2026
038dbf4
test(calls): load the alone prompt before its deadline tests
peterchinman Oct 26, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

This file was deleted.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

45 changes: 45 additions & 0 deletions apps/web/src/features/channel/Call/CallAlonePrompt.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { ConfirmDialog } from '@ui/components/ConfirmDialog';
import { createSignal, onCleanup } from 'solid-js';

function formatRemaining(ms: number) {
const totalSeconds = Math.max(0, Math.ceil(ms / 1000));
const minutes = Math.floor(totalSeconds / 60);
const seconds = totalSeconds % 60;
return `${minutes}:${seconds.toString().padStart(2, '0')}`;
}

/**
* Asks a user who is alone in a call whether to keep it going before the
* server ends it at `endsAt`. Dismissing leaves the deadline in place.
*/
export function CallAlonePrompt(props: {
/** Epoch ms when the server ends the call. */
endsAt: number;
pending: boolean;
onStay: () => void;
onDismiss: () => void;
}) {
const [nowMs, setNowMs] = createSignal(Date.now());
const countdownTimer = globalThis.setInterval(
() => setNowMs(Date.now()),
1000
);
onCleanup(() => globalThis.clearInterval(countdownTimer));

return (
<ConfirmDialog
open
onOpenChange={(open) => {
if (!open) props.onDismiss();
}}
title="You're the only one here"
body={`No one else is in this call. It will end in ${formatRemaining(
props.endsAt - nowMs()
)} unless you stay.`}
confirmLabel="Stay in call"
cancelLabel="Dismiss"
pending={props.pending}
onConfirm={props.onStay}
/>
);
}
Loading
Loading