Repository navigation
feat: 觀眾手機即時投票、互動頁參考與規劃設計原則 - #3
Conversation
- references/live-poll/:Cloudflare Worker+Durable Object 投票後端、投影片端 live-poll.js/css、150 支手機壓測腳本 - scripts/poll-slides.mjs:占位 section → 加入頁與投票頁(QR 帶 data-url),注入講者端程式 - references/interactive-pages.md:互動地圖、製作技巧頁、PPTX 轉 HTML 插入互動頁 - references/design-principles.md:X 簡報技巧整理的原則與工具清單併入 skill,SKILL.md 第 1 步引用 - TECHNIQUES 4.5–4.7、README、pitfalls、CHANGELOG、CI 語法檢查同步 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: da5964d8a0
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| } | ||
|
|
||
| const { event, polls } = JSON.parse(readFileSync(join(worker, 'src', 'polls.json'), 'utf8')); | ||
| const QR = requirePkg('qrcode'); |
There was a problem hiding this comment.
Install qrcode before invoking the generator
On a fresh installation following the documented live-poll setup, this exits with “找不到套件 qrcode”: the skill package contains only jsqr and pngjs, while the npm install under worker/ installs only Wrangler and is not on the resolver's upward search path when the command is run from the deck project. Add an explicit npm install qrcode setup step or package and resolve qrcode as a skill-local dependency so the advertised generation command works.
AGENTS.md reference: AGENTS.md:L6-L10
Useful? React with 👍 / 👎.
| const res = await api('/api/results?poll=' + id); | ||
| results[id] = res; | ||
| if (res.phase !== 'revealed') { | ||
| const r = await control({ poll: id, phase: 'open' }); | ||
| results[id] = r.results; |
There was a problem hiding this comment.
Guard poll activation against stale slide requests
If the presenter leaves this poll slide while the results request is pending, onShow sends {poll:null}, but this continuation can subsequently send {poll:id, phase:'open'} and reopen the question after the slide is no longer visible. Rapid navigation between poll slides can similarly leave the wrong poll active on audience phones; check that current === id after each await or cancel/serialize these transitions before issuing the control request.
Useful? React with 👍 / 👎.
| } else { | ||
| const vals = rows.map(r => Number(r.value)).sort((a, b) => a - b); | ||
| out.counts = def.bins.map(([lo, hi]) => vals.filter(v => v >= lo && v <= hi).length); | ||
| out.median = vals.length ? vals[Math.floor((vals.length - 1) / 2)] : null; |
There was a problem hiding this comment.
Average the middle values for even-sized numeric polls
For an even number of numeric responses, this reports the lower middle observation rather than the median of the two middle observations. For example, votes [0, 100] display a median of 0 instead of 50, making the live statistic inaccurate whenever a numeric poll has an even response count.
Useful? React with 👍 / 👎.
| ws.onclose = () => { | ||
| conn.textContent = "重新連線中…"; | ||
| fallback(); | ||
| setTimeout(connect, Math.min(15000, 1000 * 2 ** retry++)); |
There was a problem hiding this comment.
Cancel pending reconnects before opening another socket
After a disconnect schedules this retry, returning the tab to the foreground can call connect() immediately via visibilitychange; the pending timeout then opens a second socket without closing or checking the first. Both remain tagged as phones, so the backend's socket-based phones count is inflated and repeated disconnects can accumulate additional connections; retain and clear the retry timer or make connect() return while a socket is already connecting/open.
Useful? React with 👍 / 👎.
互動內容原本收在「講者工具」的收合區塊裡,首頁看不到;改成不收合的章節並加入導覽列與流程圖。 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix: 處理 PR #3/#4 的 Codex 審查意見 - 中位數偶數筆取中間兩筆平均(worker 抽出 stats.js 並加測試;模擬模式同步) - 投影片端換頁競態:控制請求排隊、換頁序號擋掉過期的開題 - 手機頁重連:取消排定的重連、已在連線就不再開新 socket - 模擬模式啟動即設定加入頁人數 - qrcode 改為 skill 自帶套件(resolve.mjs SKILL_LOCAL) - README 部署指令改用子 shell;live-poll README 補 cd .. - Live Demo 改為 Node 20+,重新 build docs/index.html - CI 執行 worker 的 node --test * fix: 控制請求排隊時略過過期的換頁指令 斷線時 /api/control 卡住、講者連換多頁,積壓的換頁指令輪到時若已換過頁就略過, 只送最新狀態;不會重播舊題、也不會疊加多次逾時。揭曉/清空照送。 重新 build docs/index.html。 --------- Co-authored-by: keanu77 <20503845+keanu77@users.noreply.github.com>
內容
skills/html-slide-deck/references/live-poll/:Worker+Durable Object 後端、手機頁(揭曉前不含答案)、投影片端程式(A 揭曉、Shift+R 清空、斷線改輪詢)、load-test.mjs。scripts/poll-slides.mjs:把<section data-poll-join>/<section data-poll="id">占位換成完整投票頁並注入講者端;產出檔含 ADMIN_KEY,只放講者電腦。references/interactive-pages.md:互動地圖、製作技巧頁、PPTX 轉 HTML 插入互動頁。references/design-principles.md:docs/html-slides-tips-from-x-2026-10-17.md的原則與工具清單併入 skill,SKILL.md 第 1 步引用。測試
wrangler dev:load-test.mjs三題各 150 支假手機全數通過(開題、投票、統計、揭曉)qa-screenshots.mjs(含QA_OFFLINE=1)通過,投票頁 QR 解碼相符🤖 Generated with Claude Code