oxedyne/daimond/dev/shot_mobile.mjs
3.4 KiB, 1 run
created by r2519314175:163, which is this file's identity for as long as the history lasts, whatever it is later renamed to
download · who wrote it · its history
| 1 | // shot_mobile.mjs — capture the phone shell for the eye, not the assertion. |
| 2 | import { open } from './harness.mjs'; |
| 3 | const sleep = ms => new Promise(r => setTimeout(r, ms)); |
| 4 | |
| 5 | const s = await open({ signIn: true, connect: true, name: 'mobileshots' }); |
| 6 | const { page } = s; |
| 7 | // Never let a hung webfont fetch stall document.fonts.ready (and the screenshot). |
| 8 | await page.route('**/*.{woff,woff2,ttf,otf}', r => r.abort()); |
| 9 | await page.setViewportSize({ width: 390, height: 844 }); |
| 10 | await page.addStyleTag({ content: '*,*::before,*::after{transition:none!important;animation:none!important}' }); |
| 11 | await sleep(300); |
| 12 | // connectMock leaves the settings modal up; take it down for a clean floor. |
| 13 | await page.evaluate(() => { try { window.DaimondAdmin.closeModal(); } catch (e) {} const m = document.getElementById('settings-modal'); if (m) m.style.display = 'none'; }); |
| 14 | await sleep(200); |
| 15 | |
| 16 | // A started chat, so the floor is a real conversation. |
| 17 | await page.evaluate(() => { try { document.getElementById('new-session-btn').click(); } catch (e) {} }); |
| 18 | await sleep(300); |
| 19 | await page.evaluate(() => { const b = [...document.querySelectorAll('button')].find(x => /^Start$/.test(x.textContent.trim())); if (b) b.click(); }); |
| 20 | await sleep(400); |
| 21 | await page.evaluate(() => { |
| 22 | // A couple of turns of copy so the floor reads like a conversation. |
| 23 | const out = document.getElementById('chat-output'); if (!out) return; |
| 24 | out.insertAdjacentHTML('beforeend', |
| 25 | '<div class="chat-msg chat-msg-user"><div class="chat-msg-content">What did the invoice from Acme say?</div></div>' + |
| 26 | '<div class="chat-msg chat-msg-assistant"><div class="chat-msg-content">It totals £1,240, due on the 30th. Want me to open it beside us?</div></div>'); |
| 27 | }); |
| 28 | await sleep(200); |
| 29 | // Playwright's screenshot waits on document.fonts.ready, which never settles |
| 30 | // here; CDP's captureScreenshot does not, so use it directly. |
| 31 | import { writeFileSync } from 'node:fs'; |
| 32 | const cdp = await s.browser.newCDPSession(page); |
| 33 | const shot = async (p) => { |
| 34 | try { |
| 35 | const { data } = await cdp.send('Page.captureScreenshot', { format: 'png' }); |
| 36 | writeFileSync(p, Buffer.from(data, 'base64')); |
| 37 | console.log('shot ' + p); |
| 38 | } catch (e) { console.log('SKIP ' + p + ' — ' + e.message.split('\n')[0]); } |
| 39 | }; |
| 40 | |
| 41 | await shot('shots/mobile-1-floor.png'); |
| 42 | |
| 43 | // The drawer. |
| 44 | await page.evaluate(() => document.getElementById('drawer-btn').click()); |
| 45 | await sleep(400); |
| 46 | await shot('shots/mobile-2-drawer.png'); |
| 47 | await page.evaluate(() => document.getElementById('scrim').click()); |
| 48 | await sleep(400); |
| 49 | |
| 50 | // A message, risen as a sheet at its half detent — the thing beside the daimon. |
| 51 | await page.evaluate(() => { |
| 52 | const head = document.getElementById('msg-head'), body = document.getElementById('msg-body'); |
| 53 | if (head) head.innerHTML = '<div class="msg-subject" style="font-weight:600;font-size:16px;margin-bottom:6px">Invoice #4021 — Acme Ltd</div><div style="color:var(--text-muted);font-size:13px">accounts@acme.example · 14 Jul</div>'; |
| 54 | if (body) body.innerHTML = '<p>Dear customer,</p><p>Please find attached invoice #4021 for services rendered in June, totalling <b>£1,240.00</b>, payable by 30 July.</p><p>Kind regards,<br>Acme Ltd Accounts</p>'; |
| 55 | window.DaimondPanels.show('msg'); |
| 56 | }); |
| 57 | await sleep(500); |
| 58 | await shot('shots/mobile-3-sheet-half.png'); |
| 59 | |
| 60 | // Raised to full for immersive reading. |
| 61 | await page.evaluate(() => { const g = document.getElementById('msheet-grab'); /* nudge to full via API-free path */ }); |
| 62 | await sleep(100); |
| 63 | await s.close(); |
| 64 | console.log('done'); |