Seat transfer phrases: carry your games to another device
While seated, "transfer seat" in the masthead mints a spoken-word one-time phrase from the game's own vocabulary (ember-troll-dagger), good for ten minutes. Typing it into the lobby's "claim a transferred seat" box on any other device hands over the seat's token, adds the game to that browser's ledger, and sits you straight down at the table. Phrases are single-use, expire, are voided by a server restart (seats never are), and both devices keep the seat afterward — the phone on the couch and the desktop upstairs can play the same wizard. Verified end to end: mint, claim, rejoin, and a second claim refused. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
bc8013863b
commit
2184721ab4
@@ -10,6 +10,7 @@
|
||||
|
||||
let name = $state("");
|
||||
let joinCode = $state("");
|
||||
let claimPhrase = $state("");
|
||||
let drawCount = $state(2);
|
||||
let withExpansion = $state(true);
|
||||
/** Your creature selected for movement/attacks. */
|
||||
@@ -449,6 +450,7 @@
|
||||
<span class="mast-sub">sixth edition</span>
|
||||
{#if net.roomId}
|
||||
<span class="mast-room">room <b>{net.roomId}</b></span>
|
||||
<button class="mast-leave" onclick={() => net.requestTransferCode()}>transfer seat</button>
|
||||
<button class="mast-leave" onclick={() => net.leave()}>leave table</button>
|
||||
{/if}
|
||||
<span class="mast-status" class:offline={net.status !== "connected"}>
|
||||
@@ -460,6 +462,14 @@
|
||||
<div class="toast" role="alert">{net.error}</div>
|
||||
{/if}
|
||||
|
||||
{#if net.transferCode}
|
||||
<div class="slip transfer-slip">
|
||||
Speak this phrase into your other device (good for 10 minutes, one use):
|
||||
<strong class="transfer-phrase">{net.transferCode.code}</strong>
|
||||
<button class="hint-cancel" onclick={() => (net.transferCode = null)}>dismiss</button>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if !net.roomId}
|
||||
<section class="boxlid">
|
||||
<div class="boxlid-inner">
|
||||
@@ -480,6 +490,15 @@
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="claim-row">
|
||||
<input class="claim-input" bind:value={claimPhrase}
|
||||
placeholder="ember-troll-dagger" aria-label="seat transfer phrase" />
|
||||
<button class="stamp tiny" disabled={!claimPhrase.trim()}
|
||||
onclick={() => { net.claimTransfer(claimPhrase); claimPhrase = ""; }}>
|
||||
Claim a transferred seat
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{#if net.seats.length > 0}
|
||||
<div class="ledger">
|
||||
<div class="ledger-head">
|
||||
@@ -848,6 +867,41 @@
|
||||
.check { display: flex; gap: 0.5rem; align-items: center; justify-content: center; font-size: 0.92rem; margin-bottom: 1rem; }
|
||||
.waiting { color: #6b5a41; font-style: italic; }
|
||||
|
||||
.transfer-slip {
|
||||
max-width: 30rem;
|
||||
margin: 0 auto 0.7rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.6rem;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.transfer-phrase {
|
||||
font-family: "Courier Prime", monospace;
|
||||
font-size: 1.05rem;
|
||||
letter-spacing: 0.04em;
|
||||
background: rgba(67, 51, 31, 0.12);
|
||||
padding: 0.1rem 0.45rem;
|
||||
border-radius: 3px;
|
||||
user-select: all;
|
||||
}
|
||||
.claim-row {
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-top: 1.1rem;
|
||||
}
|
||||
.claim-input {
|
||||
background: #f4eede;
|
||||
border: 1px solid #b3a687;
|
||||
border-radius: 4px;
|
||||
padding: 0.4rem 0.6rem;
|
||||
font-family: "Courier Prime", monospace;
|
||||
font-size: 0.9rem;
|
||||
color: #43331f;
|
||||
width: 13rem;
|
||||
}
|
||||
|
||||
/* the games ledger */
|
||||
.ledger {
|
||||
margin-top: 1.6rem;
|
||||
|
||||
Reference in New Issue
Block a user