Replace native confirm() with an in-site confirmation dialog

Add App.confirm() in common.js: a promise-based dialog styled like the
site's modals, with a title, multi-line message and custom button labels.
Destructive actions use a red OK button and focus Cancel by default;
Escape and backdrop clicks cancel, and Tab stays inside the dialog.

Use it for folding when a check is possible, leaving the table,
confirming showdown winners and deleting tables from the lobby. After the
dialog closes, re-check that the action is still valid (turn not passed,
pot not already awarded, table still listed) before sending it.

Also add a "poker-test" launch config that runs on port 4672 with the
example keys from .env.example, for local browser testing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
agomizi1cmandClaude Opus 5.5 committed 2026-10-20 00:34:43 +09:00
1 parent d89ce1dd30
commit 680aa20d30
5 files changed
+122 -11

No files matched your search

+21 -8
View File
@@ -532,7 +532,7 @@
renderAwardPanel(state.hand.pots);
});
$('award-confirm').addEventListener('click', () => {
$('award-confirm').addEventListener('click', async () => {
if (pending || !awardSel.every((set) => set.size > 0)) return;
const winners = awardSel.map((set) => [...set]);
const names = winners.map((w) => w.map(nameOf).join('・'));
@@ -540,7 +540,9 @@
names.length === 1
? `${names[0]} の勝ちで確定しますか?`
: names.map((n, i) => `${i === 0 ? 'メイン' : 'サイド'}: ${n}`).join('\n') + '\nで確定しますか?';
if (!confirm(msg)) return;
const ok = await App.confirm({ title: '勝者の確定', message: msg, ok: '確定する' });
// 確認中に他の人が確定した・ハンドが終わった場合は送らない
if (!ok || pending || $('award-panel').hidden) return;
pending = true;
emit('table:award', { winners });
render();
@@ -589,10 +591,20 @@
const options = () => (state && state.me && state.me.options) || null;
$('act-fold').addEventListener('click', () => {
$('act-fold').addEventListener('click', async () => {
const o = options();
if (!o) return;
if (o.canCheck && !confirm('チェックできます。フォールドしますか?')) return;
if (o.canCheck) {
const ok = await App.confirm({
title: 'フォールドしますか?',
message: 'いまはチップを出さずにチェックできます。',
ok: 'フォールド',
cancel: 'やめる',
danger: true,
});
// 確認中に手番が過ぎていたら何もしない
if (!ok || !options()) return;
}
sendAction('fold');
});
$('act-call').addEventListener('click', () => {
@@ -672,14 +684,15 @@
$('rebuy').addEventListener('click', () => emit('table:rebuy'));
$('take-seat').addEventListener('click', () => join(true));
$('leave').addEventListener('click', () => {
$('leave').addEventListener('click', async () => {
const me = state && state.mySeat >= 0 ? state.seats[state.mySeat] : null;
if (!me) return (location.href = '/');
const inHand = state.hand && !state.hand.finished && me.inHand && !me.folded;
const msg = inHand
? 'ハンドの途中です。退席するとフォールドになり、チップは失われます。退席しますか?'
: 'テーブルから退席しますか?(チップは失われます)';
if (!confirm(msg)) return;
? 'ハンドの途中です。退席するとフォールドになり、チップは失われます。'
: '退席するとチップは失われます。';
const ok = await App.confirm({ title: 'テーブルから退席しますか?', message: msg, ok: '退席する', danger: true });
if (!ok) return;
socket.emit('table:leave', null, () => { location.href = '/'; });
});