import "package:flutter/foundation.dart"; import "../../src/local_state.dart"; import "../../src/project_settings_store.dart"; class SettingsProvider extends ChangeNotifier { SettingsProvider(this._settingsStore) : _globalSettings = _settingsStore.settings; static const Map _legacyModelAliases = { "google/gemini-2.0-flash": "google/gemini-2.0-flash-001", }; final SettingsStore _settingsStore; LocalSettings _globalSettings; LocalSettings? _projectSettings; String? _threadModel; String? _activeProjectDir; // Effective settings: global → project override → thread model LocalSettings get settings { var merged = _globalSettings.mergeWith(_projectSettings); if (_threadModel != null && _threadModel!.isNotEmpty) { merged = merged.copyWith(model: _threadModel); } return merged; } String normalizeModelId(String? modelId) { if (modelId == null || modelId.isEmpty) { return "anthropic/claude-sonnet-4.6"; } return _legacyModelAliases[modelId] ?? modelId; } // Called when the active project changes Future setActiveProject(String? workingDirectory) async { _activeProjectDir = workingDirectory; _projectSettings = null; _threadModel = null; if (workingDirectory != null && workingDirectory.isNotEmpty) { _projectSettings = await ProjectSettingsStore.instance.load(workingDirectory); } notifyListeners(); } // Called when a thread is loaded or cleared void setThreadModel(String? model) { _threadModel = model != null ? normalizeModelId(model) : null; notifyListeners(); } Future updateModel(String newModel) async { final normalized = normalizeModelId(newModel); // update thread model in memory _threadModel = normalized; // also persist to global settings as the new default await _settingsStore.update( (current) => current.copyWith(model: normalized), ); _globalSettings = _settingsStore.settings; notifyListeners(); } Future updateApiKey(String newKey) async { await _settingsStore.update( (current) => current.copyWith(openRouterApiKey: newKey), ); _globalSettings = _settingsStore.settings; notifyListeners(); } Future updateTheme(String newTheme) async { await _settingsStore.update((current) => current.copyWith(theme: newTheme)); _globalSettings = _settingsStore.settings; notifyListeners(); } Future updateEffortLevel(String newLevel) async { await _settingsStore.update( (current) => current.copyWith(effortLevel: newLevel), ); _globalSettings = _settingsStore.settings; notifyListeners(); } Future addAlwaysAllowRule(String toolName) async { final current = _globalSettings.alwaysAllowRules; if (current.contains(toolName)) return; await _settingsStore.update( (s) => s.copyWith(alwaysAllowRules: [...current, toolName]), ); _globalSettings = _settingsStore.settings; notifyListeners(); } Future resetToDefaults() async { await _settingsStore.update((_) => const LocalSettings()); _globalSettings = _settingsStore.settings; _projectSettings = null; _threadModel = null; notifyListeners(); } // Save project-level settings override Future updateProjectSetting(LocalSettings projectOverride) async { final dir = _activeProjectDir; if (dir == null || dir.isEmpty) return; await ProjectSettingsStore.instance.save(dir, projectOverride); _projectSettings = projectOverride; notifyListeners(); } }