From 0913069c09e39a8844138ddf9667b01147fca604 Mon Sep 17 00:00:00 2001 From: Sridhar Bala Date: Fri, 16 Oct 2026 22:19:16 +0530 Subject: [PATCH 01/11] Continue new cloud accounts into setup and expose pairing server --- src/install-wizard.html | 19 ++++++------------- tests/browser-cloud-auth.test.js | 8 ++++++++ tests/cloud-agent-bootstrap.test.js | 12 ++++++++++-- tests/cloud-signup-in-app.test.js | 6 ++++-- 4 files changed, 28 insertions(+), 17 deletions(-) diff --git a/src/install-wizard.html b/src/install-wizard.html index bfa989b22..9ce569a4c 100644 --- a/src/install-wizard.html +++ b/src/install-wizard.html @@ -815,7 +815,7 @@

Connect to Posnic Cloud

New to Posnic? Create a cloud account -
Use a pairing code instead
+
Use a pairing code instead

Already filled for Posnic Cloud. For your own server, use the address supplied with your code.

Connect to a custom server
Use the address provided by your administrator.
@@ -1636,8 +1636,10 @@

💾 Backup Configuration (Step 4 of 4)

document.getElementById('cloudError').style.display = 'block'; return; } + const server = document.getElementById('pairServer'); + if (!server.reportValidity()) return; await runCloudSetup(() => window.electronAPI.cloud.pair({ - serverUrl: document.getElementById('cloudServer').value.trim(), code, + serverUrl: server.value.trim(), code, })); }); @@ -1745,18 +1747,9 @@

💾 Backup Configuration (Step 4 of 4)

if (data.users === 0) { progress.style.display = 'none'; btn.disabled = false; - errorBox.style.color = '#475569'; - errorBox.innerHTML = - 'Connected! Your cloud account doesn't have a store yet. ' + - 'Set up your store now, everything will sync to your cloud account automatically.'; - errorBox.style.display = 'block'; - document.getElementById('cloudConnectBtn').style.display = 'none'; - // This button becomes the only way forward, so it has - // to come back out of the disabled state above. backBtn.disabled = false; - backBtn.textContent = 'Set Up My Store →'; - backBtn.className = 'btn btn-primary'; - backBtn.onclick = () => showSection('stepQuick'); + // Continue directly to shop creation for a new cloud account. + showSection('stepQuick'); return; } progressText.textContent = '✅ All data downloaded. Opening login…'; diff --git a/tests/browser-cloud-auth.test.js b/tests/browser-cloud-auth.test.js index e82d99826..5f41c7bbf 100644 --- a/tests/browser-cloud-auth.test.js +++ b/tests/browser-cloud-auth.test.js @@ -156,3 +156,11 @@ test('successful browser approval restores its initiating window without blockin assert.deepEqual(calls, focusFails ? ['restore','show','connect'] : ['restore','show','focus','connect']); } }); + +test('signup returns through the same approval callback as login', async t => { + const f = fixture(t), done = f.client.authorize({ ...details, intent: 'signup' }); + await f.opening; + assert.equal(f.initial.intent, 'signup'); + assert.equal((await f.callback()).status, 200); + assert.equal((await done).deviceId, 'test-device'); +}); diff --git a/tests/cloud-agent-bootstrap.test.js b/tests/cloud-agent-bootstrap.test.js index a900bbd87..eb50c6c66 100644 --- a/tests/cloud-agent-bootstrap.test.js +++ b/tests/cloud-agent-bootstrap.test.js @@ -133,10 +133,11 @@ function wizard(t, cloud) { const document = { getElementById(id) { if (!elements.has(id)) elements.set(id, { style: {}, disabled: false, textContent: '' }); return elements.get(id); } }; let poll; let now = 0; - const sandbox = { resumeCloudDownload: false, document, window: { showCloudConflict() {}, electronAPI: { cloud } }, API_BASE: 'http://localhost', + const sections = []; + const sandbox = { showSection: (id) => sections.push(id), resumeCloudDownload: false, document, window: { showCloudConflict() {}, electronAPI: { cloud } }, API_BASE: 'http://localhost', Date: { now: () => now }, setTimeout: (fn) => { poll = fn; return 1; }, clearTimeout: () => { poll = null; } }; vm.runInNewContext(fn, sandbox); - return { run: sandbox.runCloudSetup, document, tick: async (elapsed) => { now += elapsed; const fn = poll; poll = null; await fn(); } }; + return { sections, run: sandbox.runCloudSetup, document, tick: async (elapsed) => { now += elapsed; const fn = poll; poll = null; await fn(); } }; } for (const type of ['false', 'rejection', 'status failure', 'no status']) { @@ -224,3 +225,10 @@ for (const reply of [null, { deviceToken: {}, deviceId: 'device' }, { deviceToke } test('loopback development servers remain available', () => assert.equal(cloudServerUrl('http://127.0.0.1:8080/'), 'http://127.0.0.1:8080')); + +test('new cloud account continues directly to shop setup after initial sync', async t => { + const harness = wizard(t, { status: async () => ({ sync: { initialSyncComplete: true } }), checkData: async () => ({ ok: true, users: 0 }) }); + await harness.run(async () => ({ ok: true }), true); + await harness.tick(2000); + assert.deepEqual(harness.sections, ['stepQuick']); +}); diff --git a/tests/cloud-signup-in-app.test.js b/tests/cloud-signup-in-app.test.js index 49116dfe7..6ab79b972 100644 --- a/tests/cloud-signup-in-app.test.js +++ b/tests/cloud-signup-in-app.test.js @@ -19,10 +19,10 @@ test('compact cloud choice, Community setup and pairing remain available', () => }); test('trial and sign-in actions use browser authorization; pairing stays independent', async () => { const dom = new JSDOM(source, { runScripts: 'outside-only' }); - const calls = [], pending = []; + const calls = [], pending = [], pairCalls = []; dom.window.electronAPI = { cloud: { authorize: async (intent) => { calls.push(intent); return { ok: true }; }, - pair: async (details) => { calls.push(details.code); return { ok: true }; }, + pair: async (details) => { calls.push(details.code); pairCalls.push(details); return { ok: true }; }, cancelAuthorization: () => calls.push('cancel'), reopenAuthorization: async () => ({ ok: true }), } }; dom.window.showSection = () => {}; @@ -31,10 +31,12 @@ test('trial and sign-in actions use browser authorization; pairing stays indepen const end = source.indexOf(" document.getElementById('cloudBackBtn')", start); dom.window.eval(source.slice(start, end)); for (const id of ['chooseCloudBtn', 'signupLink', 'cloudSignupLink', 'browserSignInBtn']) dom.window.document.getElementById(id).click(); + dom.window.document.getElementById('pairServer').value = 'https://shop.example'; dom.window.document.getElementById('pairCode').value = 'P1-K7M4-9QX2'; dom.window.document.getElementById('pairBtn').click(); await Promise.all(pending); assert.deepEqual(calls, ['login', 'signup', 'login', 'P1-K7M4-9QX2']); + assert.equal(pairCalls[0].serverUrl, 'https://shop.example'); dom.window.document.getElementById('cancelBrowserBtn').click(); assert.equal(calls.at(-1), 'cancel'); dom.window.close(); }); From 2ac1f5edeb19252333ccfa7830eed19f52fc6dc9 Mon Sep 17 00:00:00 2001 From: Sridhar Bala Date: Fri, 16 Oct 2026 21:50:27 +0530 Subject: [PATCH 02/11] Add remove-all shortcut to uninstall data choices --- builds/installer.nsh | 51 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 45 insertions(+), 6 deletions(-) diff --git a/builds/installer.nsh b/builds/installer.nsh index 10fd392a9..bb5fc2021 100644 --- a/builds/installer.nsh +++ b/builds/installer.nsh @@ -63,6 +63,7 @@ Var POSNIC_KEEP_HARDWARE Var POSNIC_KEEP_BACKUPS Var POSNIC_BUSINESS_CHECK Var POSNIC_HARDWARE_CHECK +Var POSNIC_REMOVE_ALL_CHECK Var POSNIC_BACKUPS_CHECK Var POSNIC_REMOVAL_SUMMARY Var POSNIC_POWERSHELL @@ -253,24 +254,62 @@ Function un.PosnicDataPage !insertmacro MUI_HEADER_TEXT "Remove Posnic?" "The application will be removed. Choose what to keep." nsDialogs::Create 1018 Pop $0 - ${NSD_CreateCheckbox} 0 12u 100% 20u "Keep business data" + ${NSD_CreateCheckbox} 0 0u 100% 18u "Remove all local data" + Pop $POSNIC_REMOVE_ALL_CHECK + ${NSD_OnClick} $POSNIC_REMOVE_ALL_CHECK un.PosnicRemoveAllClick + ${NSD_CreateCheckbox} 0 30u 100% 18u "Keep business data" Pop $POSNIC_BUSINESS_CHECK ${NSD_SetState} $POSNIC_BUSINESS_CHECK $POSNIC_KEEP_BUSINESS - ${NSD_CreateLabel} 14u 34u 95% 22u "Sales, stock, customers and pending changes." + ${NSD_OnClick} $POSNIC_BUSINESS_CHECK un.PosnicKeepClick + ${NSD_CreateLabel} 14u 49u 95% 16u "Sales, stock, customers and pending changes." Pop $0 - ${NSD_CreateCheckbox} 0 62u 100% 20u "Keep hardware settings" + ${NSD_CreateCheckbox} 0 69u 100% 18u "Keep hardware settings" Pop $POSNIC_HARDWARE_CHECK ${NSD_SetState} $POSNIC_HARDWARE_CHECK $POSNIC_KEEP_HARDWARE - ${NSD_CreateLabel} 14u 84u 95% 22u "Scales, printers and kitchen screens." + ${NSD_OnClick} $POSNIC_HARDWARE_CHECK un.PosnicKeepClick + ${NSD_CreateLabel} 14u 88u 95% 16u "Scales, printers and kitchen screens." Pop $0 - ${NSD_CreateCheckbox} 0 112u 100% 20u "Keep saved backups" + ${NSD_CreateCheckbox} 0 108u 100% 18u "Keep saved backups" Pop $POSNIC_BACKUPS_CHECK ${NSD_SetState} $POSNIC_BACKUPS_CHECK $POSNIC_KEEP_BACKUPS - ${NSD_CreateLabel} 0 145u 100% 36u "Cloud data will not be deleted. Unchecked data is permanently removed from this computer. No extra backup is created." + ${NSD_OnClick} $POSNIC_BACKUPS_CHECK un.PosnicKeepClick + ${NSD_CreateLabel} 0 132u 100% 24u "Cloud data stays unchanged. Unchecked local data is permanently deleted. No extra backup is created." Pop $0 + Call un.PosnicSyncRemoveAll nsDialogs::Show FunctionEnd +Function un.PosnicRemoveAllClick + Pop $0 + ${NSD_GetState} $POSNIC_REMOVE_ALL_CHECK $1 + ${If} $1 == ${BST_CHECKED} + StrCpy $1 ${BST_UNCHECKED} + ${Else} + StrCpy $1 ${BST_CHECKED} + ${EndIf} + ${NSD_SetState} $POSNIC_BUSINESS_CHECK $1 + ${NSD_SetState} $POSNIC_HARDWARE_CHECK $1 + ${NSD_SetState} $POSNIC_BACKUPS_CHECK $1 +FunctionEnd + +Function un.PosnicKeepClick + Pop $0 + Call un.PosnicSyncRemoveAll +FunctionEnd + +Function un.PosnicSyncRemoveAll + ${NSD_GetState} $POSNIC_BUSINESS_CHECK $1 + ${NSD_GetState} $POSNIC_HARDWARE_CHECK $2 + ${NSD_GetState} $POSNIC_BACKUPS_CHECK $3 + ${If} $1 == ${BST_UNCHECKED} + ${AndIf} $2 == ${BST_UNCHECKED} + ${AndIf} $3 == ${BST_UNCHECKED} + ${NSD_SetState} $POSNIC_REMOVE_ALL_CHECK ${BST_CHECKED} + ${Else} + ${NSD_SetState} $POSNIC_REMOVE_ALL_CHECK ${BST_UNCHECKED} + ${EndIf} +FunctionEnd + Function un.PosnicDataLeave ${NSD_GetState} $POSNIC_BUSINESS_CHECK $POSNIC_KEEP_BUSINESS ${NSD_GetState} $POSNIC_HARDWARE_CHECK $POSNIC_KEEP_HARDWARE From 46d930a3bdb8e4431e7b385c4e3f9cd500d42d75 Mon Sep 17 00:00:00 2001 From: Sridhar Bala Date: Fri, 16 Oct 2026 21:51:27 +0530 Subject: [PATCH 03/11] Fit uninstall choices inside standard dialog height --- builds/installer.nsh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/builds/installer.nsh b/builds/installer.nsh index bb5fc2021..96fc98572 100644 --- a/builds/installer.nsh +++ b/builds/installer.nsh @@ -257,23 +257,23 @@ Function un.PosnicDataPage ${NSD_CreateCheckbox} 0 0u 100% 18u "Remove all local data" Pop $POSNIC_REMOVE_ALL_CHECK ${NSD_OnClick} $POSNIC_REMOVE_ALL_CHECK un.PosnicRemoveAllClick - ${NSD_CreateCheckbox} 0 30u 100% 18u "Keep business data" + ${NSD_CreateCheckbox} 0 24u 100% 18u "Keep business data" Pop $POSNIC_BUSINESS_CHECK ${NSD_SetState} $POSNIC_BUSINESS_CHECK $POSNIC_KEEP_BUSINESS ${NSD_OnClick} $POSNIC_BUSINESS_CHECK un.PosnicKeepClick - ${NSD_CreateLabel} 14u 49u 95% 16u "Sales, stock, customers and pending changes." + ${NSD_CreateLabel} 14u 42u 95% 14u "Sales, stock, customers and pending changes." Pop $0 - ${NSD_CreateCheckbox} 0 69u 100% 18u "Keep hardware settings" + ${NSD_CreateCheckbox} 0 58u 100% 18u "Keep hardware settings" Pop $POSNIC_HARDWARE_CHECK ${NSD_SetState} $POSNIC_HARDWARE_CHECK $POSNIC_KEEP_HARDWARE ${NSD_OnClick} $POSNIC_HARDWARE_CHECK un.PosnicKeepClick - ${NSD_CreateLabel} 14u 88u 95% 16u "Scales, printers and kitchen screens." + ${NSD_CreateLabel} 14u 76u 95% 14u "Scales, printers and kitchen screens." Pop $0 - ${NSD_CreateCheckbox} 0 108u 100% 18u "Keep saved backups" + ${NSD_CreateCheckbox} 0 94u 100% 18u "Keep saved backups" Pop $POSNIC_BACKUPS_CHECK ${NSD_SetState} $POSNIC_BACKUPS_CHECK $POSNIC_KEEP_BACKUPS ${NSD_OnClick} $POSNIC_BACKUPS_CHECK un.PosnicKeepClick - ${NSD_CreateLabel} 0 132u 100% 24u "Cloud data stays unchanged. Unchecked local data is permanently deleted. No extra backup is created." + ${NSD_CreateLabel} 0 116u 100% 22u "Cloud data stays unchanged. Unchecked local data is permanently deleted. No extra backup is created." Pop $0 Call un.PosnicSyncRemoveAll nsDialogs::Show From d288ef06ed4b6ce7f203c50b9e47187107c0fd00 Mon Sep 17 00:00:00 2001 From: Sridhar Bala Date: Fri, 16 Oct 2026 23:13:11 +0530 Subject: [PATCH 04/11] Apply illustrated cloud and Community setup design --- src/install-wizard.html | 81 ++++++++++++++++++++------- src/simple-setup.css | 85 +++++++++++++++++++++++++++++ tests/cloud-agent-bootstrap.test.js | 2 +- tests/cloud-signup-in-app.test.js | 2 +- 4 files changed, 149 insertions(+), 21 deletions(-) diff --git a/src/install-wizard.html b/src/install-wizard.html index 9ce569a4c..03414df78 100644 --- a/src/install-wizard.html +++ b/src/install-wizard.html @@ -797,22 +797,57 @@

🎉 Installation Complete!

-
-

Let’s set up your shop

-

Choose how you want to get started.

-
- - -
- - -
- - @@ -1380,7 +1415,11 @@

💾 Backup Configuration (Step 4 of 4)

goToLogin(); }; } - document.getElementById('chooseLocalBtn').addEventListener('click', () => showSection('stepQuick')); + document.getElementById('chooseLocalBtn').addEventListener('click', () => { + document.querySelector('#stepQuick h2').textContent = 'Create your offline shop'; + document.querySelector('#stepQuick .simple-intro').textContent = 'Your account and business data stay on this computer.'; + showSection('stepQuick'); + }); document.getElementById('qBackBtn').addEventListener('click', () => showSection('step0')); // ------------------------------------------------------------------ @@ -1699,6 +1738,7 @@

💾 Backup Configuration (Step 4 of 4)

window.showCloudConflict(null); btn.disabled = backBtn.disabled = pairBtn.disabled = true; document.getElementById('browserSignInBtn').disabled = true; + document.getElementById('cloudSignupLink').disabled = true; document.getElementById('customServerBtn').disabled = true; document.getElementById('browserWait').style.display = browser && !resumeCloudDownload ? 'block' : 'none'; errorBox.style.display = 'none'; @@ -1709,6 +1749,7 @@

💾 Backup Configuration (Step 4 of 4)

clearTimeout(poll); btn.disabled = backBtn.disabled = pairBtn.disabled = false; document.getElementById('browserSignInBtn').disabled = false; + document.getElementById('cloudSignupLink').disabled = false; document.getElementById('customServerBtn').disabled = false; document.getElementById('browserWait').style.display = 'none'; progress.style.display = 'none'; @@ -1749,6 +1790,8 @@

💾 Backup Configuration (Step 4 of 4)

btn.disabled = false; backBtn.disabled = false; // Continue directly to shop creation for a new cloud account. + document.querySelector('#stepQuick h2').textContent = 'Set up your cloud shop'; + document.querySelector('#stepQuick .simple-intro').textContent = 'Create your shop and staff login. Your data will sync to your connected cloud account.'; showSection('stepQuick'); return; } diff --git a/src/simple-setup.css b/src/simple-setup.css index f2eadfa98..a858a381f 100644 --- a/src/simple-setup.css +++ b/src/simple-setup.css @@ -80,3 +80,88 @@ body.desktop-window[data-desktop-window="setup"] { display: flex; flex-direction .wizard-body .form-section h2 { font-size: 22px; } .wizard-container .form-section > .btn-container, .setup-footer { margin-left: -18px; margin-right: -18px; padding: 15px 18px; } } + +/* Approved illustrated onboarding. Shared by stock and white-label builds. */ + +.wizard-container .setup-design{padding:20px 8px;color-scheme:light dark} +.wizard-container .setup-design .setup{--paper:light-dark(#fff,#20252e);--ink:light-dark(#172b42,#edf3fa);--sub:light-dark(#56677b,#b5c2d2);--line:light-dark(#dce4ec,#414c5b);--blue:light-dark(#0874bc,#75c5ff);--tint:light-dark(#edf7ff,#21374a);--soft:light-dark(#f6f8fb,#282f3b);background:var(--paper);color:var(--ink);font:14px/1.5 'Segoe UI',Arial,sans-serif;max-width:760px;margin:auto;border:1px solid var(--line);border-radius:16px;overflow:hidden;box-shadow:0 12px 38px #0000000a} +.wizard-container .setup-design *{box-sizing:border-box} +.wizard-container .setup-design header{padding:22px 28px;border-bottom:1px solid var(--line);display:flex;align-items:center;justify-content:space-between} +.wizard-container .setup-design .brand{font-size:23px;font-weight:600;color:var(--blue);letter-spacing:-.5px} +.wizard-container .setup-design .step{font-size:12px;color:var(--sub)} +.wizard-container .setup-design main{padding:28px} +.wizard-container .setup-design h1{font-size:26px;line-height:1.25;font-weight:600;letter-spacing:-.6px;margin:0 0 8px} +.wizard-container .setup-design .intro{color:var(--sub);margin:0 0 25px} +.wizard-container .setup-design .choices{display:grid;grid-template-columns:1fr 1fr;gap:18px} +.wizard-container .setup-design .option{border:1px solid var(--line);border-radius:12px;padding:22px;display:flex;flex-direction:column;min-width:0;background:var(--paper)} +.wizard-container .setup-design .option.cloud{border-color:var(--blue)} +.wizard-container .setup-design .graphic{height:98px;display:flex;align-items:center;justify-content:center;gap:13px;background:var(--soft);border-radius:8px;margin-bottom:20px;color:var(--sub)} +.wizard-container .setup-design .cloud .graphic{background:var(--tint);color:var(--blue)} +.wizard-container .setup-design .device{display:flex;align-items:center;flex-direction:column;gap:6px;font-size:11px;font-weight:500} +.wizard-container .setup-design .device svg{width:34px!important;height:34px!important;stroke-width:1.5} +.wizard-container .setup-design .device{background:var(--paper);border:1px solid var(--line);border-radius:10px;padding:12px 10px;min-width:84px;box-shadow:0 3px 8px #00000005} +.wizard-container .setup-design .graphic{height:132px;gap:10px} +.wizard-container .setup-design .sync{display:flex;align-items:center;justify-content:center} +.wizard-container .setup-design .features li{gap:11px;align-items:flex-start} +.wizard-container .setup-design .features li>svg{width:21px!important;height:21px!important;stroke-width:1.7;margin-top:1px} +.wizard-container .setup-design .features strong{display:block;font-weight:600;margin-bottom:2px} +.wizard-container .setup-design .features small{display:block;color:var(--sub);font-size:12px;line-height:1.5} +.wizard-container .setup-design .graphic>.sync svg{width:23px;height:23px;stroke-width:1.6} +.wizard-container .setup-design .option h2{font-size:21px;line-height:1.3;margin:0 0 8px;font-weight:600;letter-spacing:-.3px} +.wizard-container .setup-design .mode{display:flex;align-items:center;gap:7px;font-weight:600;color:var(--blue);font-size:13px;margin-bottom:14px} +.wizard-container .setup-design .mode svg{width:17px;height:17px} +.wizard-container .setup-design .local .mode{color:var(--sub)} +.wizard-container .setup-design .description{margin:0 0 18px;color:var(--sub);min-height:63px} +.wizard-container .setup-design .features{display:grid;gap:12px;margin:0 0 22px;padding:0;list-style:none} +.wizard-container .setup-design .features li{display:flex;align-items:flex-start;gap:9px;font-size:13px} +.wizard-container .setup-design .features svg{width:17px;height:17px;flex:none;margin-top:2px;color:var(--blue)} +.wizard-container .setup-design .local .features svg{color:var(--sub)} +.wizard-container .setup-design .provider{font-size:12px;color:var(--sub);border-top:1px solid var(--line);padding-top:14px;margin:auto 0 16px} +.wizard-container .setup-design button{font:600 14px 'Segoe UI',Arial,sans-serif;border:1px solid var(--line);border-radius:7px;background:var(--paper);color:var(--ink);padding:12px 14px;min-height:44px;display:flex;align-items:center;justify-content:center;gap:10px} +.wizard-container .setup-design button svg{width:17px;height:17px} +.wizard-container .setup-design .primary{background:light-dark(#0874bc,#8bd0ff);color:light-dark(#fff,#102435);border-color:transparent} +.wizard-container .setup-design button:hover{filter:brightness(.96)} +.wizard-container .setup-design footer{padding:16px 28px;border-top:1px solid var(--line);background:var(--soft);font-size:12px;color:var(--sub);display:flex;align-items:center;gap:8px} +.wizard-container .setup-design footer svg{width:16px;height:16px;flex:none} +.wizard-container .setup-design .back{border:0;padding:0;min-height:32px;color:var(--blue);margin-bottom:18px;justify-content:flex-start;font-weight:500} +.wizard-container .setup-design .connect{max-width:480px;margin:0 auto;padding:10px 0 20px} +.wizard-container .setup-design .connect>.primary{width:100%;margin:24px 0 18px} +.wizard-container .setup-design .cloud-welcome{text-align:center;margin:4px 0 24px} +.wizard-container .setup-design .cloud-emblem{width:76px;height:76px;border-radius:20px;background:var(--tint);color:var(--blue);display:flex;align-items:center;justify-content:center;margin:0 auto 16px} +.wizard-container .setup-design .cloud-emblem svg{width:42px!important;height:42px!important;stroke-width:1.5} +.wizard-container .setup-design .cloud-wordmark{color:var(--blue);font-size:15px;font-weight:600;letter-spacing:.2px;margin:0 0 8px} +.wizard-container .setup-design .cloud-welcome .note{max-width:370px;margin:12px auto 0} +.wizard-container .setup-design .account-panel{border:1px solid var(--line);border-radius:12px;padding:22px;background:var(--paper);margin-bottom:22px} +.wizard-container .setup-design .account-panel button{width:100%} +.wizard-container .setup-design .account-label{font-size:13px;font-weight:500;margin:0 0 10px;color:var(--ink)} +.wizard-container .setup-design .account-divider{display:flex;align-items:center;gap:12px;color:var(--sub);font-size:12px;margin:20px 0} +.wizard-container .setup-design .account-divider:before,.wizard-container .setup-design .account-divider:after{content:"";height:1px;background:var(--line);flex:1} +.wizard-container .setup-design .trial{color:var(--blue);border-color:var(--blue);background:var(--tint)} +.wizard-container .setup-design .account-help{text-align:center;color:var(--sub);font-size:12px;margin:10px 0 0} +.wizard-container .setup-design .offline-assurance{display:flex;gap:9px;align-items:flex-start;background:var(--soft);border-radius:8px;padding:13px 15px;margin-top:14px;color:var(--sub);font-size:12px} +.wizard-container .setup-design .offline-assurance svg{flex:none;width:18px!important;height:18px!important;margin-top:1px} +.wizard-container .setup-design details{border-top:1px solid var(--line);padding:16px 0} +.wizard-container .setup-design summary{color:var(--blue);font-weight:500;cursor:pointer;min-height:28px} +.wizard-container .setup-design label{display:block;font-size:13px;margin:12px 0 6px} +.wizard-container .setup-design input{width:100%;padding:12px;font:14px 'Segoe UI',Arial,sans-serif;background:var(--paper);color:var(--ink);border:1px solid var(--line);border-radius:6px;margin-bottom:12px} +.wizard-container .setup-design .note{color:var(--sub);font-size:13px} +.wizard-container .setup-design [hidden]{display:none!important} +@media(max-width:570px){.wizard-container .setup-design .choices{grid-template-columns:1fr}.wizard-container .setup-design main{padding:22px 18px}.wizard-container .setup-design header{padding:18px}.wizard-container .setup-design .description{min-height:0}.wizard-container .setup-design h1{font-size:24px}.wizard-container .setup-design .graphic{height:85px}} + +/* Preserve the approved preview geometry in the native setup shell. */ +body.desktop-window[data-desktop-window="setup"] .wizard-container { max-width:760px !important; } +.wizard-container .setup-design { --paper:var(--w-card,#fff);--ink:var(--w-text,#172b42);--sub:var(--w-muted,#56677b);--line:var(--w-border,#dce4ec);--blue:#0874bc;--tint:#edf7ff;--soft:var(--w-raised,#f6f8fb);font:14px/1.5 "Segoe UI",Arial,sans-serif;padding:0;color:var(--ink); } +.wizard-container .setup-design.connect{max-width:480px;margin:0 auto 28px;padding:0;} +.wizard-container .setup-design .option h2{font-size:21px;line-height:1.3;margin:0 0 8px;} +.wizard-container .setup-design h2{font-size:26px;line-height:1.25;margin:0 0 8px;} +.wizard-container .setup-design button{font-weight:600!important;text-transform:none;letter-spacing:0;box-shadow:none;} +.wizard-container .setup-design .primary{background:#0874bc!important;color:#fff!important;border-color:transparent!important;} +.wizard-container .setup-design #cloudSignupLink{font-size:14px;color:var(--blue);} +.wizard-container .setup-design .features strong{display:block;font-size:13px;font-weight:600;} +.wizard-container .setup-design .features small{display:block;font-size:12px;color:var(--sub);margin:0;} +:root[data-window-theme="dark"] .wizard-container .setup-design{--paper:#20252e;--ink:#edf3fa;--sub:#b5c2d2;--line:#414c5b;--blue:#75c5ff;--tint:#21374a;--soft:#282f3b;color-scheme:dark;} +@media(max-width:570px){.wizard-container .setup-design .choices{grid-template-columns:1fr;}.wizard-container .setup-design .description{min-height:0;}} +body.desktop-window[data-desktop-window="setup"] .wizard-container .setup-design button { font-weight:600!important;border-radius:7px!important; } +body.desktop-window .wizard-container .setup-design button.primary { background:#0874bc!important;color:#fff!important;border-color:transparent!important; } +body.desktop-window .wizard-container .setup-design button.trial { background:var(--tint)!important;color:var(--blue)!important;border-color:var(--blue)!important; } +body.desktop-window .wizard-container .setup-design button.back { border:0!important;background:transparent!important;color:var(--blue)!important;padding:0!important;min-height:32px; } diff --git a/tests/cloud-agent-bootstrap.test.js b/tests/cloud-agent-bootstrap.test.js index eb50c6c66..e0be470f4 100644 --- a/tests/cloud-agent-bootstrap.test.js +++ b/tests/cloud-agent-bootstrap.test.js @@ -130,7 +130,7 @@ function wizard(t, cloud) { const source = fs.readFileSync(path.join(__dirname, '../src/install-wizard.html'), 'utf8'); const fn = source.slice(source.indexOf(' async function runCloudSetup('), source.indexOf(' async function initApiBase(')); const elements = new Map(); - const document = { getElementById(id) { if (!elements.has(id)) elements.set(id, { style: {}, disabled: false, textContent: '' }); return elements.get(id); } }; + const document = { querySelector: () => ({ textContent: '' }), getElementById(id) { if (!elements.has(id)) elements.set(id, { style: {}, disabled: false, textContent: '' }); return elements.get(id); } }; let poll; let now = 0; const sections = []; diff --git a/tests/cloud-signup-in-app.test.js b/tests/cloud-signup-in-app.test.js index 6ab79b972..868c28d00 100644 --- a/tests/cloud-signup-in-app.test.js +++ b/tests/cloud-signup-in-app.test.js @@ -8,7 +8,7 @@ const source = fs.readFileSync(path.join(__dirname, '../src/install-wizard.html' test('compact cloud choice, Community setup and pairing remain available', () => { const dom = new JSDOM(source), doc = dom.window.document; - assert.equal(doc.querySelector('.simple-options').firstElementChild.id, 'chooseCloudBtn'); + assert.equal(doc.querySelector('.simple-options button').id, 'chooseCloudBtn'); assert.match(doc.querySelector('#chooseLocalBtn').textContent, /Set up offline/); assert.equal(doc.querySelector('#pairDetails').open, false); assert.equal(doc.querySelector('#customServerDetails').open, false); From f6b84860aa863ee035e97e4599fe37127330f29f Mon Sep 17 00:00:00 2001 From: Sridhar Bala Date: Fri, 16 Oct 2026 23:13:20 +0530 Subject: [PATCH 05/11] Clean setup markup whitespace --- src/install-wizard.html | 90 ++++++++++++++++++++--------------------- 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/src/install-wizard.html b/src/install-wizard.html index 03414df78..ea92accdd 100644 --- a/src/install-wizard.html +++ b/src/install-wizard.html @@ -737,7 +737,7 @@
- +

Setting up your account...

@@ -749,10 +749,10 @@
- +

🎉 Installation Complete!

Your Posnic account has been created successfully

- +
@@ -868,7 +868,7 @@

Choose how to continue

Connecting…
Internet drops? Keep selling after setup. Your till syncs when you're connected again.
- +
@@ -954,7 +954,7 @@

Save your recovery codes