107 lines
2.6 KiB
Dart
107 lines
2.6 KiB
Dart
import 'dart:convert';
|
|
import 'package:http/http.dart' as http;
|
|
import '../models/models.dart';
|
|
|
|
class ApiService {
|
|
String baseUrl;
|
|
String? _token;
|
|
|
|
ApiService({required this.baseUrl});
|
|
|
|
String? get token => _token;
|
|
bool get isAuthenticated => _token != null;
|
|
|
|
void setToken(String token) {
|
|
_token = token;
|
|
}
|
|
|
|
Map<String, String> get _headers => {
|
|
if (_token != null) 'Authorization': 'Bearer $_token',
|
|
'Content-Type': 'application/json',
|
|
'Accept': 'application/json',
|
|
};
|
|
|
|
Future<AuthResponse> login(String email, String password) async {
|
|
final response = await http.post(
|
|
Uri.parse('$baseUrl/api/v1/auth'),
|
|
headers: {'Content-Type': 'application/json'},
|
|
body: jsonEncode({'email': email, 'password': password}),
|
|
);
|
|
|
|
if (response.statusCode == 200) {
|
|
final data = AuthResponse.fromJson(jsonDecode(response.body));
|
|
setToken(data.token);
|
|
return data;
|
|
}
|
|
|
|
final body = jsonDecode(response.body);
|
|
throw ApiException(
|
|
statusCode: response.statusCode,
|
|
message: body['error'] ?? 'Unknown error',
|
|
);
|
|
}
|
|
|
|
Future<AppsResponse> getApps() async {
|
|
final response = await http.get(
|
|
Uri.parse('$baseUrl/api/v1/apps'),
|
|
headers: _headers,
|
|
);
|
|
|
|
if (response.statusCode == 200) {
|
|
return AppsResponse.fromJson(jsonDecode(response.body));
|
|
}
|
|
|
|
if (response.statusCode == 401) {
|
|
throw AuthException();
|
|
}
|
|
|
|
final body = jsonDecode(response.body);
|
|
throw ApiException(
|
|
statusCode: response.statusCode,
|
|
message: body['error'] ?? 'Unknown error',
|
|
);
|
|
}
|
|
|
|
Future<http.StreamedResponse> downloadVersion(String versionId) async {
|
|
final request = http.Request(
|
|
'GET',
|
|
Uri.parse('$baseUrl/api/v1/versions/$versionId/download'),
|
|
);
|
|
request.headers.addAll(_headers);
|
|
|
|
final response = await http.Client().send(request);
|
|
|
|
if (response.statusCode == 200) {
|
|
return response;
|
|
}
|
|
|
|
if (response.statusCode == 401) {
|
|
throw AuthException();
|
|
}
|
|
|
|
response.stream.drain();
|
|
final body = await response.stream.bytesToString();
|
|
final parsed = jsonDecode(body);
|
|
throw ApiException(
|
|
statusCode: response.statusCode,
|
|
message: parsed['error'] ?? 'Download failed',
|
|
);
|
|
}
|
|
|
|
String iconUrl(String iconPath) {
|
|
if (iconPath.startsWith('http')) return iconPath;
|
|
return '$baseUrl$iconPath';
|
|
}
|
|
}
|
|
|
|
class ApiException implements Exception {
|
|
final int statusCode;
|
|
final String message;
|
|
|
|
ApiException({required this.statusCode, required this.message});
|
|
|
|
@override
|
|
String toString() => message;
|
|
}
|
|
|
|
class AuthException implements Exception {}
|