feat: separate default model for the app
This commit is contained in:
@@ -31,6 +31,9 @@ sealed class UserSettings with _$UserSettings {
|
||||
@Default(false) bool reduceMotion,
|
||||
@Default(true) bool hapticFeedback,
|
||||
|
||||
// Model preferences
|
||||
String? defaultModelId,
|
||||
|
||||
// Advanced settings
|
||||
@Default({}) Map<String, dynamic> customSettings,
|
||||
}) = _UserSettings;
|
||||
|
||||
@@ -18,6 +18,7 @@ import '../models/folder.dart';
|
||||
import '../models/user_settings.dart';
|
||||
import '../models/file_info.dart';
|
||||
import '../models/knowledge_base.dart';
|
||||
import '../services/settings_service.dart';
|
||||
import '../services/optimized_storage_service.dart';
|
||||
|
||||
// Storage providers
|
||||
@@ -500,8 +501,10 @@ final loadConversationProvider = FutureProvider.family<Conversation, String>((
|
||||
return fullConversation;
|
||||
});
|
||||
|
||||
// Provider to automatically load and set the default model from OpenWebUI
|
||||
// Provider to automatically load and set the default model from user settings or OpenWebUI
|
||||
final defaultModelProvider = FutureProvider<Model?>((ref) async {
|
||||
// Watch user settings to refresh when default model changes
|
||||
ref.watch(appSettingsProvider);
|
||||
// Handle reviewer mode first
|
||||
final reviewerMode = ref.watch(reviewerModeProvider);
|
||||
if (reviewerMode) {
|
||||
@@ -562,45 +565,71 @@ final defaultModelProvider = FutureProvider<Model?>((ref) async {
|
||||
|
||||
Model? selectedModel;
|
||||
|
||||
// Try to get the server's default model configuration
|
||||
try {
|
||||
final defaultModelId = await api.getDefaultModel();
|
||||
// First check user's preferred default model
|
||||
final userSettings = ref.read(appSettingsProvider);
|
||||
final userDefaultModelId = userSettings.defaultModel;
|
||||
|
||||
if (userDefaultModelId != null && userDefaultModelId.isNotEmpty) {
|
||||
try {
|
||||
selectedModel = models.firstWhere(
|
||||
(model) =>
|
||||
model.id == userDefaultModelId ||
|
||||
model.name == userDefaultModelId ||
|
||||
model.id.contains(userDefaultModelId) ||
|
||||
model.name.contains(userDefaultModelId),
|
||||
);
|
||||
foundation.debugPrint(
|
||||
'DEBUG: Found user default model: ${selectedModel.name}',
|
||||
);
|
||||
} catch (e) {
|
||||
foundation.debugPrint(
|
||||
'DEBUG: User default model "$userDefaultModelId" not found in available models',
|
||||
);
|
||||
selectedModel = null; // Will fall back to server default or first model
|
||||
}
|
||||
}
|
||||
|
||||
if (defaultModelId != null && defaultModelId.isNotEmpty) {
|
||||
// Find the model that matches the default model ID
|
||||
try {
|
||||
selectedModel = models.firstWhere(
|
||||
(model) =>
|
||||
model.id == defaultModelId ||
|
||||
model.name == defaultModelId ||
|
||||
model.id.contains(defaultModelId) ||
|
||||
model.name.contains(defaultModelId),
|
||||
);
|
||||
foundation.debugPrint(
|
||||
'DEBUG: Found server default model: ${selectedModel.name}',
|
||||
);
|
||||
} catch (e) {
|
||||
foundation.debugPrint(
|
||||
'DEBUG: Default model "$defaultModelId" not found in available models',
|
||||
);
|
||||
// If no user default or user default not found, try server's default model
|
||||
if (selectedModel == null) {
|
||||
try {
|
||||
final defaultModelId = await api.getDefaultModel();
|
||||
|
||||
if (defaultModelId != null && defaultModelId.isNotEmpty) {
|
||||
// Find the model that matches the default model ID
|
||||
try {
|
||||
selectedModel = models.firstWhere(
|
||||
(model) =>
|
||||
model.id == defaultModelId ||
|
||||
model.name == defaultModelId ||
|
||||
model.id.contains(defaultModelId) ||
|
||||
model.name.contains(defaultModelId),
|
||||
);
|
||||
foundation.debugPrint(
|
||||
'DEBUG: Found server default model: ${selectedModel.name}',
|
||||
);
|
||||
} catch (e) {
|
||||
foundation.debugPrint(
|
||||
'DEBUG: Server default model "$defaultModelId" not found in available models',
|
||||
);
|
||||
selectedModel = models.first;
|
||||
}
|
||||
} else {
|
||||
// No server default, use first available model
|
||||
selectedModel = models.first;
|
||||
foundation.debugPrint(
|
||||
'DEBUG: No server default model, using first available: ${selectedModel.name}',
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// No server default, use first available model
|
||||
} catch (apiError) {
|
||||
foundation.debugPrint(
|
||||
'DEBUG: Failed to get default model from server: $apiError',
|
||||
);
|
||||
// Use first available model as fallback
|
||||
selectedModel = models.first;
|
||||
foundation.debugPrint(
|
||||
'DEBUG: No server default model, using first available: ${selectedModel.name}',
|
||||
'DEBUG: Using first available model as fallback: ${selectedModel.name}',
|
||||
);
|
||||
}
|
||||
} catch (apiError) {
|
||||
foundation.debugPrint(
|
||||
'DEBUG: Failed to get default model from server: $apiError',
|
||||
);
|
||||
// Use first available model as fallback
|
||||
selectedModel = models.first;
|
||||
foundation.debugPrint(
|
||||
'DEBUG: Using first available model as fallback: ${selectedModel.name}',
|
||||
);
|
||||
}
|
||||
|
||||
// Defer the state update to avoid modifying providers during initialization
|
||||
|
||||
@@ -3,7 +3,7 @@ import 'package:flutter/services.dart';
|
||||
// ThemedDialogs handles theming; no direct use of extensions here
|
||||
import '../../features/chat/views/chat_page.dart';
|
||||
import '../../features/auth/views/connect_signin_page.dart';
|
||||
import '../../features/settings/views/searchable_settings_page.dart';
|
||||
|
||||
import '../../features/profile/views/profile_page.dart';
|
||||
import '../../features/files/views/files_page.dart';
|
||||
|
||||
@@ -148,10 +148,7 @@ class NavigationService {
|
||||
return navigateTo(Routes.login, clearStack: true);
|
||||
}
|
||||
|
||||
/// Navigate to settings
|
||||
static Future<void> navigateToSettings() {
|
||||
return navigateTo(Routes.settings);
|
||||
}
|
||||
|
||||
|
||||
/// Navigate to profile
|
||||
static Future<void> navigateToProfile() {
|
||||
@@ -202,9 +199,7 @@ class NavigationService {
|
||||
page = const ConnectAndSignInPage();
|
||||
break;
|
||||
|
||||
case Routes.settings:
|
||||
page = const SearchableSettingsPage();
|
||||
break;
|
||||
|
||||
|
||||
case Routes.profile:
|
||||
page = const ProfilePage();
|
||||
@@ -244,7 +239,7 @@ class NavigationService {
|
||||
class Routes {
|
||||
static const String chat = '/chat';
|
||||
static const String login = '/login';
|
||||
static const String settings = '/settings';
|
||||
|
||||
static const String profile = '/profile';
|
||||
static const String serverConnection = '/server-connection';
|
||||
static const String search = '/search';
|
||||
|
||||
@@ -11,6 +11,7 @@ class SettingsService {
|
||||
static const String _highContrastKey = 'high_contrast';
|
||||
static const String _largeTextKey = 'large_text';
|
||||
static const String _darkModeKey = 'dark_mode';
|
||||
static const String _defaultModelKey = 'default_model';
|
||||
|
||||
/// Get reduced motion preference
|
||||
static Future<bool> getReduceMotion() async {
|
||||
@@ -84,6 +85,22 @@ class SettingsService {
|
||||
await prefs.setBool(_darkModeKey, value);
|
||||
}
|
||||
|
||||
/// Get default model preference
|
||||
static Future<String?> getDefaultModel() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
return prefs.getString(_defaultModelKey);
|
||||
}
|
||||
|
||||
/// Set default model preference
|
||||
static Future<void> setDefaultModel(String? modelId) async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
if (modelId != null) {
|
||||
await prefs.setString(_defaultModelKey, modelId);
|
||||
} else {
|
||||
await prefs.remove(_defaultModelKey);
|
||||
}
|
||||
}
|
||||
|
||||
/// Load all settings
|
||||
static Future<AppSettings> loadSettings() async {
|
||||
return AppSettings(
|
||||
@@ -93,6 +110,7 @@ class SettingsService {
|
||||
highContrast: await getHighContrast(),
|
||||
largeText: await getLargeText(),
|
||||
darkMode: await getDarkMode(),
|
||||
defaultModel: await getDefaultModel(),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -105,6 +123,7 @@ class SettingsService {
|
||||
setHighContrast(settings.highContrast),
|
||||
setLargeText(settings.largeText),
|
||||
setDarkMode(settings.darkMode),
|
||||
setDefaultModel(settings.defaultModel),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -151,6 +170,7 @@ class AppSettings {
|
||||
final bool highContrast;
|
||||
final bool largeText;
|
||||
final bool darkMode;
|
||||
final String? defaultModel;
|
||||
|
||||
const AppSettings({
|
||||
this.reduceMotion = false,
|
||||
@@ -159,6 +179,7 @@ class AppSettings {
|
||||
this.highContrast = false,
|
||||
this.largeText = false,
|
||||
this.darkMode = true,
|
||||
this.defaultModel,
|
||||
});
|
||||
|
||||
AppSettings copyWith({
|
||||
@@ -168,6 +189,7 @@ class AppSettings {
|
||||
bool? highContrast,
|
||||
bool? largeText,
|
||||
bool? darkMode,
|
||||
String? defaultModel,
|
||||
}) {
|
||||
return AppSettings(
|
||||
reduceMotion: reduceMotion ?? this.reduceMotion,
|
||||
@@ -176,6 +198,7 @@ class AppSettings {
|
||||
highContrast: highContrast ?? this.highContrast,
|
||||
largeText: largeText ?? this.largeText,
|
||||
darkMode: darkMode ?? this.darkMode,
|
||||
defaultModel: defaultModel ?? this.defaultModel,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -188,7 +211,8 @@ class AppSettings {
|
||||
other.hapticFeedback == hapticFeedback &&
|
||||
other.highContrast == highContrast &&
|
||||
other.largeText == largeText &&
|
||||
other.darkMode == darkMode;
|
||||
other.darkMode == darkMode &&
|
||||
other.defaultModel == defaultModel;
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -200,6 +224,7 @@ class AppSettings {
|
||||
highContrast,
|
||||
largeText,
|
||||
darkMode,
|
||||
defaultModel,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -250,6 +275,11 @@ class AppSettingsNotifier extends StateNotifier<AppSettings> {
|
||||
await SettingsService.setDarkMode(value);
|
||||
}
|
||||
|
||||
Future<void> setDefaultModel(String? modelId) async {
|
||||
state = state.copyWith(defaultModel: modelId);
|
||||
await SettingsService.setDefaultModel(modelId);
|
||||
}
|
||||
|
||||
Future<void> resetToDefaults() async {
|
||||
const defaultSettings = AppSettings();
|
||||
await SettingsService.saveSettings(defaultSettings);
|
||||
|
||||
Reference in New Issue
Block a user