feat: add settings API service and IPTV settings provider with configurable options.

This commit is contained in:
Michael committed 2025-12-08 22:58:43 +01:00
1 parent 00b8ce5c64
commit e0cdf69674
3 files changed
+52 -37

No files matched your search

+8 -7
View File
@@ -2,7 +2,6 @@ import 'dart:convert';
import 'package:shelf/shelf.dart';
import 'package:shelf_router/shelf_router.dart';
import '../database/database.dart';
import '../models/user.dart';
class SettingsHandler {
final AppDatabase db;
@@ -14,12 +13,13 @@ class SettingsHandler {
// GET /api/settings
router.get('/', (Request req) {
final user = req.context['user'] as User?;
if (user == null) {
// Get userId from context (set by auth middleware)
final userId = req.context['userId'] as String?;
if (userId == null) {
return Response.forbidden(jsonEncode({'error': 'Authentication required'}));
}
final settingsJson = db.getUserSettings(user.id);
final settingsJson = db.getUserSettings(userId);
// If no settings exist, return empty object or default
return Response.ok(
@@ -30,8 +30,9 @@ class SettingsHandler {
// POST /api/settings
router.post('/', (Request req) async {
final user = req.context['user'] as User?;
if (user == null) {
// Get userId from context (set by auth middleware)
final userId = req.context['userId'] as String?;
if (userId == null) {
return Response.forbidden(jsonEncode({'error': 'Authentication required'}));
}
@@ -44,7 +45,7 @@ class SettingsHandler {
return Response.badRequest(body: jsonEncode({'error': 'Invalid JSON'}));
}
db.updateUserSettings(user.id, body);
db.updateUserSettings(userId, body);
return Response.ok(
body,
+37 -28
View File
@@ -1,50 +1,59 @@
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'dart:html' as html;
import '../models/app_user.dart';
import '../api/api_client.dart';
/// Service for user settings API
class SettingsApiService {
final String _baseUrl = html.window.location.origin;
final ApiClient _api = ApiClient();
/// Get settings from API
Future<Map<String, dynamic>?> getSettings() async {
final token = html.window.localStorage['auth_token'];
if (token == null) return null;
// Restore token from localStorage before making the request
_api.restoreToken();
if (_api.getStoredToken() == null) {
print('[SettingsAPI] getSettings: No auth token found');
return null;
}
try {
final response = await http.get(
Uri.parse('$_baseUrl/api/settings'),
headers: {
'Authorization': 'Bearer $token',
'Content-Type': 'application/json',
},
);
print('[SettingsAPI] getSettings: Fetching settings...');
final response = await _api.get('/api/settings');
print('[SettingsAPI] getSettings: Response status ${response.statusCode}');
if (response.statusCode == 200) {
if (response.body.isEmpty) return {};
return jsonDecode(response.body) as Map<String, dynamic>;
if (response.data == null) return {};
final decoded = response.data as Map<String, dynamic>;
print('[SettingsAPI] getSettings: Loaded ${decoded.length} settings');
return decoded;
}
print('[SettingsAPI] getSettings: Failed with data: ${response.data}');
return null;
} catch (e) {
print('[SettingsAPI] getSettings: Exception: $e');
return null;
}
}
/// Save settings to API
Future<bool> saveSettings(Map<String, dynamic> settings) async {
final token = html.window.localStorage['auth_token'];
if (token == null) return false;
// Restore token from localStorage before making the request
_api.restoreToken();
if (_api.getStoredToken() == null) {
print('[SettingsAPI] saveSettings: No auth token found');
return false;
}
try {
final response = await http.post(
Uri.parse('$_baseUrl/api/settings'),
headers: {
'Authorization': 'Bearer $token',
'Content-Type': 'application/json',
},
body: jsonEncode(settings),
);
print('[SettingsAPI] saveSettings: Saving ${settings.length} settings...');
final response = await _api.post('/api/settings', data: settings);
print('[SettingsAPI] saveSettings: Response status ${response.statusCode}');
if (response.statusCode != 200) {
print('[SettingsAPI] saveSettings: Failed with data: ${response.data}');
}
return response.statusCode == 200;
} catch (e) {
print('[SettingsAPI] saveSettings: Exception: $e');
return false;
}
}
@@ -295,7 +295,10 @@ class IptvSettingsNotifier extends StateNotifier<IptvSettings> {
Future<void> _saveToApi() async {
final authState = _ref.read(authProvider);
if (!authState.isAuthenticated) return;
if (!authState.isAuthenticated) {
print('[SettingsProvider] _saveToApi: Not authenticated, skipping save');
return;
}
// Create map from state
final settingsMap = {
@@ -313,7 +316,9 @@ class IptvSettingsNotifier extends StateNotifier<IptvSettings> {
_SettingsKeys.preferredAspectRatio: state.preferredAspectRatio,
};
await _apiService.saveSettings(settingsMap);
print('[SettingsProvider] _saveToApi: Saving settings...');
final success = await _apiService.saveSettings(settingsMap);
print('[SettingsProvider] _saveToApi: Save result: $success');
}
// ===== Setters with Auto-Save =====