Fresh installs no longer start a full library scan (with per-file SHA256 and sidecar writes) automatically at startup. Instead a welcome page lists the configured model roots, estimates the scan cost from a quick hash-free walk, and lets the user pick the sidecar storage layout and UI language before confirming. Deferring shows an empty library; the existing refresh button starts the scan later. Upgrading installs are detected via a non-empty persisted cache snapshot (row-count check, so the empty file created by scanner construction no longer masquerades as an existing library) and keep the old behavior. Bundled fixes surfaced by the new flow: - broadcast an init-progress error when the startup scan fails instead of silently landing on an empty library; the initialization page now shows the error with a retry button - skip the onboarding language modal/tutorial while the welcome or initialization page is up (its spotlight targets don't exist there, so the tour was silently auto-completed and never shown) - promotional banners wait until onboarding is completed or skipped; alert banners (startup messages, cache health) are unaffected - honor the hidden attribute in first-run/initialization CSS so the no-roots hint and error boxes don't render as empty frames
75 lines
3.3 KiB
HTML
75 lines
3.3 KiB
HTML
<!-- First Run Welcome Component -->
|
|
<div class="first-run-container" id="firstRunContainer">
|
|
<div class="first-run-content">
|
|
<div class="first-run-language">
|
|
<label for="firstRunLanguage"><i class="fas fa-globe"></i> {{ t('firstRun.language.label') }}</label>
|
|
<select id="firstRunLanguage">
|
|
<option value="en">English</option>
|
|
<option value="zh-CN">简体中文</option>
|
|
<option value="zh-TW">繁體中文</option>
|
|
<option value="ja">日本語</option>
|
|
<option value="ko">한국어</option>
|
|
<option value="es">Español</option>
|
|
<option value="fr">Français</option>
|
|
<option value="de">Deutsch</option>
|
|
<option value="ru">Русский</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="first-run-header">
|
|
<h2 id="firstRunTitle">{{ t('firstRun.title') }}</h2>
|
|
<p class="first-run-subtitle" id="firstRunSubtitle">{{ t('firstRun.description') }}</p>
|
|
</div>
|
|
|
|
<div class="first-run-libraries" id="firstRunLibraries">
|
|
<!-- Library summary rows are rendered by first_run.js -->
|
|
</div>
|
|
|
|
<div class="first-run-estimate" id="firstRunEstimate" hidden>
|
|
<i class="fas fa-clock"></i>
|
|
<span id="firstRunEstimateText"></span>
|
|
</div>
|
|
|
|
<div class="first-run-no-roots" id="firstRunNoRoots" hidden>
|
|
<i class="fas fa-exclamation-triangle"></i>
|
|
<p id="firstRunNoRootsText"></p>
|
|
</div>
|
|
|
|
<div class="first-run-sidecar">
|
|
<h3>{{ t('firstRun.sidecar.title') }}</h3>
|
|
<label class="first-run-sidecar-option">
|
|
<input type="radio" name="sidecarStorageMode" value="alongside" checked>
|
|
<span class="first-run-sidecar-option-text">
|
|
<strong>{{ t('firstRun.sidecar.alongside.label') }}</strong>
|
|
<small>{{ t('firstRun.sidecar.alongside.description') }}</small>
|
|
</span>
|
|
</label>
|
|
<label class="first-run-sidecar-option">
|
|
<input type="radio" name="sidecarStorageMode" value="centralized">
|
|
<span class="first-run-sidecar-option-text">
|
|
<strong>{{ t('firstRun.sidecar.centralized.label') }}</strong>
|
|
<small>{{ t('firstRun.sidecar.centralized.description') }}</small>
|
|
</span>
|
|
</label>
|
|
<div class="first-run-sidecar-path" id="firstRunSidecarPathRow" hidden>
|
|
<input type="text" id="firstRunSidecarPath"
|
|
placeholder="{{ t('firstRun.sidecar.centralized.pathPlaceholder') }}">
|
|
</div>
|
|
</div>
|
|
|
|
<div class="first-run-actions">
|
|
<button type="button" class="primary-btn" id="firstRunStart">
|
|
<i class="fas fa-play"></i> {{ t('firstRun.actions.start') }}
|
|
</button>
|
|
<button type="button" class="secondary-btn" id="firstRunDefer">
|
|
{{ t('firstRun.actions.defer') }}
|
|
</button>
|
|
</div>
|
|
|
|
<div class="first-run-error" id="firstRunError" hidden>
|
|
<i class="fas fa-exclamation-circle"></i>
|
|
<span id="firstRunErrorText"></span>
|
|
</div>
|
|
</div>
|
|
</div>
|