diff --git a/changedetectionio/blueprint/browser_steps/__init__.py b/changedetectionio/blueprint/browser_steps/__init__.py index 58be9a95..b9e2a307 100644 --- a/changedetectionio/blueprint/browser_steps/__init__.py +++ b/changedetectionio/blueprint/browser_steps/__init__.py @@ -266,9 +266,8 @@ def construct_blueprint(datastore: ChangeDetectionStore): # Resolve the fetcher backend for this watch so we can ask it to launch its own browser # if it supports that (e.g. CloakBrowser, which runs locally rather than via CDP) watch = datastore.data['watching'][watch_uuid] - fetcher_name = watch.get_fetch_backend or 'system' - if fetcher_name == 'system': - fetcher_name = datastore.data['settings']['application'].get('fetch_backend', 'html_requests') + # get_fetch_backend is fully resolved (group override / watch / 'system' -> global default). + fetcher_name = watch.get_fetch_backend browser, playwright_context = await acquire_browser_for_fetcher(fetcher_name, proxy=proxy, keepalive_ms=keepalive_ms) diff --git a/changedetectionio/blueprint/settings/__init__.py b/changedetectionio/blueprint/settings/__init__.py index 164436a6..9a1c76a4 100644 --- a/changedetectionio/blueprint/settings/__init__.py +++ b/changedetectionio/blueprint/settings/__init__.py @@ -66,17 +66,10 @@ def construct_blueprint(datastore: ChangeDetectionStore): extra_notification_tokens=datastore.get_unique_notification_tokens_available() ) - # The global default fetch method is now the "Default browser": the always-present - # built-in engines + the user's saved browsers (no 'system' - this IS the system - # default). Everything else in the app resolves 'system' back to this value. - from changedetectionio.model.browser_config import list_builtin_browsers - default_browser_choices = [(b['id'], b['label']) for b in list_builtin_browsers()] - default_browser_choices += [(cid, e.get('label') or cid) - for cid, e in datastore.browser_config_store.all().items()] - form.application.form.fetch_backend.choices = default_browser_choices - form.application.form.fetch_backend.label.text = gettext('Default browser') - # Accept legacy raw-engine values / ids not in the (dynamic) choice list. - form.application.form.fetch_backend.validate_choice = False + # The global "Default browser" was migrated to the /browsers tab (its per-row radio + # writes settings.application.fetch_backend). Drop the inherited fetch_backend field so a + # settings save never renders, validates, or clobbers the default - /browsers owns it now. + del form.application.form.fetch_backend # Remove the last option 'System default' form.application.form.notification_format.choices.pop() @@ -260,8 +253,18 @@ def construct_blueprint(datastore: ChangeDetectionStore): # Cost display: only when user configured their own key (not hosted/operator-managed) llm_show_costs = not llm_env_configured + # Read-only label for the global "Default browser" (managed on the /browsers tab). + from changedetectionio.model.browser_config import list_builtin_browsers + _default_id = datastore.get_default_backend() + _default_entry = datastore.browser_config_store.get(_default_id) + if _default_entry: + default_browser_label = _default_entry.get('label') or _default_id + else: + default_browser_label = dict((b['id'], b['label']) for b in list_builtin_browsers()).get(_default_id, _default_id) + output = render_template("settings.html", active_plugins=active_plugins, + default_browser_label=default_browser_label, api_key=datastore.data['settings']['application'].get('api_access_token'), llm_config=llm_config, llm_env_configured=llm_env_configured, diff --git a/changedetectionio/blueprint/settings/templates/settings.html b/changedetectionio/blueprint/settings/templates/settings.html index 1d5ffa63..5aadb105 100644 --- a/changedetectionio/blueprint/settings/templates/settings.html +++ b/changedetectionio/blueprint/settings/templates/settings.html @@ -100,14 +100,18 @@