mirror of
https://github.com/R0m1k3/xtremobile.git
synced 2026-10-11 17:29:26 +02:00
feat: add settings API service and IPTV settings provider with configurable options.
This commit is contained in:
1 parent
00b8ce5c64
commit
e0cdf69674
3 files changed
+52
-37
No files matched your search
@@ -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,
|
||||
|
||||
@@ -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 =====
|
||||
|
||||
Reference in new issue
Block a user