0.2.3: prepare follow-up fixes and client features (#407, #408, #410, #413, #431, #435, #436, #440, #444)
Add special-target activation without bypassing attack cadence, cooperative card preferences and emotes, skill sound banks, per-operator voice choices, text sizing, install prompts, closed-tab recovery and unanimous setup rerolls. Retain late deployment elapsed time and resolve echo/counter pulses without recursive hook overflow. Independent final review remains pending. Golden: roster-016, roster-035, roster-036, roster-045; boss-boss_1-pair, boss-boss_3-pair, boss-boss_5-pair, boss-boss_7-pair, hidden-boss_9-pair; solo-HARD-9-boosted: Lemuen attack cadence. diy-132: Necras extra activation targets. coop2-NORMAL-14-standins: cooperative purchase preference and simulation fixes. hidden-boss_10-solo: echo pulse FIFO resolution. See DESIGN 28.13-28.24 for assumptions, sources and contributor credit.
This commit is contained in:
1 parent
314564c139
commit
f3658a0dd4
104 files changed
+3674
-741
No files matched your search
@@ -0,0 +1,38 @@
|
||||
// Recover an explicitly selected local seat; nickname and IP never identify a player.
|
||||
import { useEffect, useState } from '../../vendor/hooks.module.js';
|
||||
import { html, Button, Modal } from './components.js';
|
||||
import { identity } from '../net.js';
|
||||
import { t } from '../../../shared/i18n.js';
|
||||
import { toast } from './toasts.js';
|
||||
|
||||
export function ResumeMatchButton() {
|
||||
const [items, setItems] = useState(() => identity.recoverable());
|
||||
const [open, setOpen] = useState(false);
|
||||
const [busy, setBusy] = useState(false);
|
||||
useEffect(() => {
|
||||
const refresh = () => setItems(identity.recoverable());
|
||||
window.addEventListener('storage', refresh);
|
||||
window.addEventListener('focus', refresh);
|
||||
refresh();
|
||||
return () => { window.removeEventListener('storage', refresh); window.removeEventListener('focus', refresh); };
|
||||
}, []);
|
||||
if (!items.length) return null;
|
||||
const resume = async (item) => {
|
||||
if (busy) return;
|
||||
setBusy(true);
|
||||
if (await identity.resume(item.id)) {
|
||||
identity.saveName(item.name);
|
||||
identity.setEntered(true);
|
||||
location.reload();
|
||||
} else {
|
||||
setBusy(false);
|
||||
toast(t('此对局仍在其他窗口中,或当前浏览器无法安全恢复。请关闭原窗口后重试。'), 'warn');
|
||||
}
|
||||
};
|
||||
return html`<${Button} variant="secondary" size="sm" data-testid="resume-local-match" onClick=${() => setOpen(true)}>${t('恢复本机对局')}<//>
|
||||
<${Modal} open=${open} onClose=${() => !busy && setOpen(false)} title=${t('恢复本机对局')}>
|
||||
<p>${t('选择已关闭窗口的对局。服务器重启或对局过期后无法恢复。')}</p>
|
||||
${items.map((item) => html`<${Button} key=${item.id} variant="secondary" block=${true} disabled=${busy} onClick=${() => resume(item)}>
|
||||
${t('{name} · 同盟 {code}', { name: item.name || t('博士'), code: item.code || '—' })}<//>`)}
|
||||
<//>`;
|
||||
}
|
||||
Reference in new issue
Block a user