Neda/Front/lib/services/api_service.dart
2026-03-05 23:08:50 +03:30

164 lines
5.1 KiB
Dart

// Expected API:
// POST /api/auth/login body: {"token":"..."} → {"user_id":"..."}
// GET /api/channels header: Authorization: Bearer TOKEN
// → [{"id":"1","name":"Alpha","member_count":3}]
// POST /api/channels/join body: {"key":"..."} → {"id":"...","name":"..."}
// GET /api/channels/{id}/livekit-token → {"url":"wss://...","token":"eyJ..."}
import 'dart:convert';
import 'package:http/http.dart' as http;
import '../config/app_config.dart';
import '../models/channel.dart';
import 'auth_service.dart';
// ── LiveKit credentials model ─────────────────────────────────────────────
class LivekitCredentials {
final String url;
final String token;
const LivekitCredentials({required this.url, required this.token});
}
// ── Fake data (only used when AppConfig.debug == true) ────────────────────
const _fakeChannels = [
{'id': '1', 'name': 'تیم آلفا', 'member_count': 4},
{'id': '2', 'name': 'پشتیبانی میدانی', 'member_count': 2},
{'id': '3', 'name': 'فرماندهی', 'member_count': 7},
{'id': '4', 'name': 'گروه لجستیک', 'member_count': 3},
{'id': '5', 'name': 'واحد امنیت', 'member_count': 5},
];
// ─────────────────────────────────────────────────────────────────────────
class ApiService {
final AuthService _auth;
ApiService(this._auth);
Future<Map<String, String>> _headers() async {
final token = await _auth.getToken();
return {
'Content-Type': 'application/json',
if (token != null) 'Authorization': 'Bearer $token',
};
}
Future<bool> login(String token) async {
if (AppConfig.debug) {
await Future.delayed(const Duration(milliseconds: 600));
await _auth.saveAuth(token: token, userId: 'debug_user');
return true;
}
try {
final res = await http
.post(
Uri.parse('${AppConfig.baseUrl}/api/auth/login'),
headers: {'Content-Type': 'application/json'},
body: jsonEncode({'token': token}),
)
.timeout(const Duration(seconds: 10));
if (res.statusCode == 200) {
final data = jsonDecode(res.body) as Map<String, dynamic>;
await _auth.saveAuth(
token: token,
userId: data['user_id']?.toString(),
);
return true;
}
return false;
} catch (_) {
return false;
}
}
Future<List<Channel>> getChannels() async {
if (AppConfig.debug) {
await Future.delayed(const Duration(milliseconds: 500));
return _fakeChannels
.map((e) => Channel.fromJson(e as Map<String, dynamic>))
.toList();
}
try {
final res = await http
.get(
Uri.parse('${AppConfig.baseUrl}/api/channels'),
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<String, dynamic>))
.toList();
}
return [];
} catch (_) {
return [];
}
}
Future<Channel?> joinPrivateChannel(String key) async {
if (AppConfig.debug) {
await Future.delayed(const Duration(milliseconds: 700));
// کلید صحیح در حالت دیباگ: هر چیزی غیر از "wrong"
if (key.toLowerCase() == 'wrong') return null;
return Channel(
id: 'private_${key.hashCode}',
name: 'کانال خصوصی ($key)',
memberCount: 1,
);
}
try {
final res = await http
.post(
Uri.parse('${AppConfig.baseUrl}/api/channels/join'),
headers: await _headers(),
body: jsonEncode({'key': key}),
)
.timeout(const Duration(seconds: 10));
if (res.statusCode == 200) {
return Channel.fromJson(
jsonDecode(res.body) as Map<String, dynamic>);
}
return null;
} catch (_) {
return null;
}
}
Future<LivekitCredentials?> getLivekitToken(String channelId) async {
if (AppConfig.debug) {
await Future.delayed(const Duration(milliseconds: 300));
return const LivekitCredentials(
url: 'wss://fake.livekit.io',
token: 'debug_livekit_token',
);
}
try {
final res = await http
.get(
Uri.parse(
'${AppConfig.baseUrl}/api/channels/$channelId/livekit-token'),
headers: await _headers(),
)
.timeout(const Duration(seconds: 10));
if (res.statusCode == 200) {
final data = jsonDecode(res.body) as Map<String, dynamic>;
return LivekitCredentials(
url: data['url'] as String,
token: data['token'] as String,
);
}
return null;
} catch (_) {
return null;
}
}
}