// Backend API endpoints: // POST /auth/login body: {"username":"...","secret":"..."} // → {"access_token":"...","token_type":"bearer"} // GET /groups/me header: Authorization: Bearer TOKEN // → [{"id":"uuid","name":"...","description":"...","is_active":true}] // // LiveKit token از طریق WebSocket دریافت می‌شود: // WS /ws/groups/{id}?token={jwt} import 'dart:convert'; import 'package:http/http.dart' as http; import '../config/app_config.dart'; import '../models/channel.dart'; import 'auth_service.dart'; // ── Fake data (only used when AppConfig.debug == true) ──────────────────── const _fakeChannels = [ {'id': '1', 'name': 'تیم آلفا'}, {'id': '2', 'name': 'پشتیبانی میدانی'}, {'id': '3', 'name': 'فرماندهی'}, {'id': '4', 'name': 'گروه لجستیک'}, {'id': '5', 'name': 'واحد امنیت'}, ]; // ───────────────────────────────────────────────────────────────────────── class ApiService { final AuthService _auth; ApiService(this._auth); Future> _headers() async { final token = await _auth.getToken(); return { 'Content-Type': 'application/json', if (token != null) 'Authorization': 'Bearer $token', }; } // استخراج user_id از JWT token (بدون نیاز به کتابخانه) String? _extractUserIdFromJwt(String token) { try { final parts = token.split('.'); if (parts.length < 2) return null; // base64url decode payload var payload = parts[1]; // اضافه کردن padding اگه لازمه while (payload.length % 4 != 0) { payload += '='; } final decoded = utf8.decode(base64Url.decode(payload)); final map = jsonDecode(decoded) as Map; return map['sub']?.toString(); } catch (_) { return null; } } Future login(String username, String secret) async { if (AppConfig.debug) { await Future.delayed(const Duration(milliseconds: 600)); await _auth.saveAuth(token: 'debug_jwt', userId: 'debug_user'); return true; } try { final res = await http .post( Uri.parse('${AppConfig.baseUrl}/auth/login'), headers: {'Content-Type': 'application/json'}, body: jsonEncode({'username': username, 'secret': secret}), ) .timeout(const Duration(seconds: 10)); if (res.statusCode == 200) { final data = jsonDecode(res.body) as Map; final accessToken = data['access_token'] as String?; if (accessToken == null) return false; final userId = _extractUserIdFromJwt(accessToken); await _auth.saveAuth(token: accessToken, userId: userId); return true; } return false; } catch (_) { return false; } } Future> getChannels() async { if (AppConfig.debug) { await Future.delayed(const Duration(milliseconds: 500)); return _fakeChannels .map((e) => Channel.fromJson(e as Map)) .toList(); } try { final res = await http .get( Uri.parse('${AppConfig.baseUrl}/users/me/groups'), headers: await _headers(), ) .timeout(const Duration(seconds: 10)); if (res.statusCode == 200) { final list = jsonDecode(res.body) as List; return list .map((e) => Channel.fromJson(e as Map)) .toList(); } return []; } catch (_) { return []; } } }