From 5ba53d7b64b181134b9c594fd9881ec626eae791 Mon Sep 17 00:00:00 2001 From: tanaka takashi Date: Tue, 1 Sep 2026 20:57:29 +0900 Subject: fix: model select showed a value that was never saved MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Root cause of "設定値が不正です (モデルが設定されていません)" despite the settings UI showing a selected model: - fillModels(models, selected="") never set option.selected when no model was saved yet. The browser then auto-selects the first option visually, so the UI displayed e.g. "glm-5.3:cloud" while storage.model remained empty. Translation therefore failed with the no-model error until the user pressed Save, which materialized the UI value into storage. Fixes - popup.js/options.js fillModels: when no model is saved and the list is non-empty, explicitly select the first model so the UI value always matches what will be used - popup.js: after the model list loads, persist the auto-selected model if storage still has none - options.js loadSettings: same sync after loadModels, so opening the options page also heals the empty-model state Results: 73 passed, 0 failed. dist rebuilt. --- src/options/options.js | 12 ++++++++++++ src/popup/popup.js | 16 ++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/src/options/options.js b/src/options/options.js index b4fc349..09d0a5f 100644 --- a/src/options/options.js +++ b/src/options/options.js @@ -102,6 +102,11 @@ function fillModels(models, selected) { $model.append(option); showStatus('保存済みモデルがOllama上に見つかりません。', true); } + if (!selected && models.length > 0) { + // No model saved yet: explicitly select the first one so the UI value + // matches what will be saved (see popup fillModels note). + $model.selectedIndex = 0; + } } async function loadModels(selected) { @@ -158,6 +163,13 @@ async function loadSettings() { const settings = result.settings || defaultSettings(); applySettings(settings); await loadModels(settings.model); + // If no model was saved yet and the list just loaded, sync the + // auto-selected first model into storage so it matches the UI. + if (!settings.model && $model.value) { + await browser.storage.local.set({ + settings: sanitizeSettings({ ...settings, model: $model.value }) + }); + } } function readForm() { diff --git a/src/popup/popup.js b/src/popup/popup.js index 612d0fd..eb213f5 100644 --- a/src/popup/popup.js +++ b/src/popup/popup.js @@ -46,6 +46,13 @@ function fillModels(models, selected) { option.selected = true; $model.append(option); } + if (!selected && models.length > 0) { + // No model saved yet: explicitly select the first one so the UI value + // matches what will be used. Otherwise the browser auto-selects the + // first option visually while storage still has an empty model, + // which made translation fail until the user pressed Save. + $model.selectedIndex = 0; + } } function showStatus(message, isError) { @@ -128,4 +135,13 @@ $openOptions.addEventListener('click', () => { void (async () => { await loadSettings(); await loadModels(); + // If the model list loaded and no model is saved yet, persist the + // auto-selected first model so the stored settings match the UI. + if (knownModels.length > 0) { + const result = await browser.storage.local.get({ settings: null }); + const stored = sanitizeSettings(result.settings || defaultSettings()); + if (!stored.model) { + await persist({ model: $model.value }); + } + } })(); \ No newline at end of file -- cgit v1.2.3