Qwen Code
Desktop workspace
diff --git a/packages/desktop-shell/bootstrap/bootstrap.js b/packages/desktop-shell/bootstrap/bootstrap.js index c728fb35735..8545ca3bf17 100644 --- a/packages/desktop-shell/bootstrap/bootstrap.js +++ b/packages/desktop-shell/bootstrap/bootstrap.js @@ -13,6 +13,8 @@ const logs = document.querySelector('#logs'); const update = document.querySelector('#update'); const version = document.querySelector('#version'); +let currentWorkspace = ''; +let snapshotOverrideStatus; let updateVersion; function setWorkspace(path) { @@ -21,6 +23,7 @@ function setWorkspace(path) { } function setStatus(kind, heading, message, failure = '') { + document.body.dataset.state = kind; title.textContent = heading; detail.textContent = message; pulse.className = `pulse ${kind === 'starting' ? '' : kind}`; @@ -29,10 +32,12 @@ function setStatus(kind, heading, message, failure = '') { retry.hidden = kind !== 'error'; choose.hidden = kind === 'starting'; choose.disabled = kind === 'starting'; + setWorkspace(kind === 'starting' ? '' : currentWorkspace); } async function chooseWorkspace() { if (!invoke) return; + snapshotOverrideStatus = 'starting'; setStatus( 'starting', 'Opening workspace', @@ -40,7 +45,7 @@ async function chooseWorkspace() { ); try { const path = await invoke('choose_workspace'); - if (path) setWorkspace(path); + if (path) currentWorkspace = path; else setStatus('idle', 'Choose another workspace', 'No folder was selected.'); } catch (failure) { @@ -55,6 +60,7 @@ async function chooseWorkspace() { async function retryRuntime() { if (!invoke) return; + snapshotOverrideStatus = 'starting'; setStatus( 'starting', 'Restarting Qwen Code', @@ -123,7 +129,8 @@ async function initialize() { await Promise.all([ listen('runtime-starting', ({ payload }) => { - setWorkspace(payload); + snapshotOverrideStatus = 'starting'; + currentWorkspace = String(payload || ''); setStatus( 'starting', 'Starting Qwen Code', @@ -131,6 +138,7 @@ async function initialize() { ); }), listen('runtime-failed', ({ payload }) => { + snapshotOverrideStatus = 'failed'; setStatus( 'error', 'Qwen Code could not start', @@ -147,7 +155,11 @@ async function initialize() { const state = await invoke('bootstrap_state'); version.textContent = `Desktop ${state.desktopVersion}`; - setWorkspace(state.workspace); + currentWorkspace ||= String(state.workspace || ''); + if (snapshotOverrideStatus) { + if (snapshotOverrideStatus === 'failed') setWorkspace(currentWorkspace); + return; + } if (state.status === 'starting') { setStatus( 'starting', diff --git a/packages/desktop-shell/bootstrap/index.html b/packages/desktop-shell/bootstrap/index.html index 26ae4310f8d..f7a1de00777 100644 --- a/packages/desktop-shell/bootstrap/index.html +++ b/packages/desktop-shell/bootstrap/index.html @@ -80,16 +80,75 @@ gap: 18px; } .mark { - display: grid; - place-items: center; width: 58px; height: 58px; - border-radius: 18px; - background: linear-gradient(145deg, #7f6dff, #4d34df); - box-shadow: 0 14px 34px rgba(88, 63, 226, 0.38); - font: - 700 26px/1 ui-monospace, - monospace; + object-fit: contain; + filter: drop-shadow(0 14px 24px rgba(88, 63, 226, 0.38)); + } + body[data-state='starting'] { + background: #070b12; + } + body[data-state='starting']::before, + body[data-state='starting'] .brand-copy, + body[data-state='starting'] .actions, + body[data-state='starting'] footer { + display: none; + } + body[data-state='starting'] .shell { + width: auto; + border: 0; + padding: 0; + background: none; + box-shadow: none; + backdrop-filter: none; + } + body[data-state='starting'] .mark { + animation: mark-pulse 1.6s ease-in-out infinite; + } + body[data-state='starting'] .status { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + border: 0; + clip: rect(0, 0, 0, 0); + clip-path: inset(50%); + white-space: nowrap; + } + @keyframes mark-pulse { + 50% { + opacity: 0.55; + transform: scale(0.94); + } + } + @media (prefers-reduced-motion: reduce) { + body[data-state='starting'] .mark { + animation: none; + } + body[data-state='starting'] .status { + position: static; + width: auto; + height: auto; + margin: 18px 0 0; + overflow: visible; + clip: auto; + clip-path: none; + white-space: normal; + grid-template-columns: 1fr; + color: #8d98aa; + background: none; + text-align: center; + } + body[data-state='starting'] .status > :first-child, + body[data-state='starting'] .status > div > :not(#title) { + display: none; + } + body[data-state='starting'] #title { + font-size: 13px; + font-weight: 500; + } } h1 { margin: 0; @@ -105,7 +164,7 @@ } .status { display: grid; - grid-template-columns: 22px 1fr; + grid-template-columns: 22px minmax(0, 1fr); gap: 14px; margin-top: 40px; padding: 22px 24px; @@ -232,12 +291,12 @@ } -
+Desktop workspace