128 lines
3.8 KiB
Dart
128 lines
3.8 KiB
Dart
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<String, String> _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<void> 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<void> 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<void> updateApiKey(String newKey) async {
|
|
await _settingsStore.update(
|
|
(current) => current.copyWith(openRouterApiKey: newKey),
|
|
);
|
|
_globalSettings = _settingsStore.settings;
|
|
notifyListeners();
|
|
}
|
|
|
|
Future<void> updateTheme(String newTheme) async {
|
|
await _settingsStore.update((current) => current.copyWith(theme: newTheme));
|
|
_globalSettings = _settingsStore.settings;
|
|
notifyListeners();
|
|
}
|
|
|
|
Future<void> updateEffortLevel(String newLevel) async {
|
|
await _settingsStore.update(
|
|
(current) => current.copyWith(effortLevel: newLevel),
|
|
);
|
|
_globalSettings = _settingsStore.settings;
|
|
notifyListeners();
|
|
}
|
|
|
|
Future<void> updatePermissionMode(String mode) async {
|
|
await _settingsStore.update(
|
|
(current) => current.copyWith(permissionMode: mode),
|
|
);
|
|
_globalSettings = _settingsStore.settings;
|
|
notifyListeners();
|
|
}
|
|
|
|
Future<void> 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<void> resetToDefaults() async {
|
|
await _settingsStore.update((_) => const LocalSettings());
|
|
_globalSettings = _settingsStore.settings;
|
|
_projectSettings = null;
|
|
_threadModel = null;
|
|
notifyListeners();
|
|
}
|
|
|
|
// Save project-level settings override
|
|
Future<void> updateProjectSetting(LocalSettings projectOverride) async {
|
|
final dir = _activeProjectDir;
|
|
if (dir == null || dir.isEmpty) return;
|
|
|
|
await ProjectSettingsStore.instance.save(dir, projectOverride);
|
|
_projectSettings = projectOverride;
|
|
notifyListeners();
|
|
}
|
|
}
|