Chepuhagram/lib/domain/services/api_service.dart

319 lines
9.3 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'package:jwt_decoder/jwt_decoder.dart';
import 'package:flutter/material.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:chepuhagram/core/constants.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
class ApiService extends ChangeNotifier {
final _client = http.Client();
final _storage = const FlutterSecureStorage();
Future<String?> uploadMedia(List<int> bytes) async {
try {
final token = getAccessToken();
var request = http.MultipartRequest(
'POST',
Uri.parse('${AppConstants.baseUrl}/media/upload'),
);
request.headers.addAll({
'Content-Type': 'application/json',
'Authorization': 'Bearer $token',
});
// Добавляем файл в запрос
request.files.add(
http.MultipartFile.fromBytes(
'file',
bytes,
filename: 'media.enc', // Имя файла для сервера
),
);
// Добавь заголовки авторизации, если они у тебя есть (JWT и т.д.)
// request.headers.addAll({'Authorization': 'Bearer $token'});
var streamedResponse = await request.send();
var response = await http.Response.fromStream(streamedResponse);
if (response.statusCode == 200) {
// Предполагаем, что сервер возвращает JSON {"file_id": "..."}
final data = jsonDecode(response.body);
return data['file_id'];
}
return null;
} catch (e) {
print("Ошибка API при загрузке: $e");
return null;
}
}
Future<bool> refreshToken() async {
notifyListeners();
try {
final refreshToken = await _storage.read(key: 'refresh_token');
final response = await _client.post(
Uri.parse('${AppConstants.baseUrl}/auth/refresh'),
body: jsonEncode({'refresh_token': refreshToken}),
headers: {'Content-Type': 'application/json'},
);
final decodedResponse =
jsonDecode(utf8.decode(response.bodyBytes)) as Map;
if (response.statusCode == 200) {
await _storage.write(
key: 'access_token',
value: decodedResponse['access_token'],
);
await _storage.write(
key: 'refresh_token',
value: decodedResponse['refresh_token'],
);
notifyListeners();
return true;
} else {
notifyListeners();
return false;
}
} catch (e) {
notifyListeners();
rethrow;
}
}
Future<String?> getAccessToken() async {
String? token = await _storage.read(key: 'access_token');
if (token != null) {
bool isExpiredSoon =
JwtDecoder.isExpired(token) ||
JwtDecoder.getRemainingTime(token).inMinutes < 2;
if (isExpiredSoon) {
bool refreshed = await refreshToken();
if (refreshed) {
token = await _storage.read(key: 'access_token');
} else {
return null;
}
}
}
return token;
}
Future<bool> updateFcmToken(String fcmtoken) async {
notifyListeners();
try {
final token = await getAccessToken();
final response = await _client.post(
Uri.parse('${AppConstants.baseUrl}/auth/update-fcm?token=$fcmtoken'),
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer $token',
},
);
if (response.statusCode == 200) {
return true;
} else {
print("Ошибка установки ключа: ${response.statusCode}");
return false;
}
} catch (e) {
rethrow;
} finally {
notifyListeners();
}
}
Future<bool> setPublicKey(String publicKey) async {
notifyListeners();
try {
final token = await getAccessToken();
final response = await _client.post(
Uri.parse('${AppConstants.baseUrl}/auth/set-public-key'),
body: jsonEncode({'public_key': publicKey}),
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer $token',
},
);
if (response.statusCode == 200) {
return true;
} else {
print("Ошибка установки ключа: ${response.statusCode}");
return false;
}
} catch (e) {
rethrow;
} finally {
notifyListeners();
}
}
Future<Map<String, dynamic>> getMe() async {
final token = await getAccessToken();
final response = await _client.get(
Uri.parse('${AppConstants.baseUrl}/users/me'),
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer $token',
},
);
if (response.statusCode == 200) {
return jsonDecode(utf8.decode(response.bodyBytes))
as Map<String, dynamic>;
}
throw Exception('Не удалось получить данные пользователя');
}
Future<bool> updateEncryptedPrivateKey(String encryptedPrivateKey) async {
final token = await getAccessToken();
final response = await _client.put(
Uri.parse('${AppConstants.baseUrl}/users/me/encryption-key'),
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer $token',
},
body: jsonEncode({'encrypted_private_key': encryptedPrivateKey}),
);
return response.statusCode == 200;
}
Future<bool> changePassword(
String currentPassword,
String newPassword,
) async {
final token = await getAccessToken();
final response = await _client.put(
Uri.parse('${AppConstants.baseUrl}/users/me/password'),
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer $token',
},
body: jsonEncode({
'current_password': currentPassword,
'new_password': newPassword,
}),
);
return response.statusCode == 200;
}
Future<List<dynamic>> getChatHistory(int contactId) async {
final token = await getAccessToken();
final response = await _client.get(
Uri.parse(
'${AppConstants.baseUrl}/messages/history/${contactId.toString()}',
),
headers: {
'Content-Type': 'application/json',
"Authorization": "Bearer $token",
},
);
return jsonDecode(response.body) as List<dynamic>;
}
Future<Map<String, dynamic>> updateMe({
required String username,
required String firstName,
required String lastName,
String? phone,
String? email,
String? about,
}) async {
final token = await getAccessToken();
final response = await _client.put(
Uri.parse('${AppConstants.baseUrl}/users/me'),
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer $token',
},
body: jsonEncode({
'username': username,
'first_name': firstName,
'last_name': lastName,
'phone': (phone == null || phone.trim().isEmpty) ? null : phone.trim(),
'email': (email == null || email.trim().isEmpty) ? null : email.trim(),
'about': (about == null || about.trim().isEmpty) ? null : about.trim(),
}),
);
final decoded = jsonDecode(utf8.decode(response.bodyBytes));
if (response.statusCode == 200) {
return decoded as Map<String, dynamic>;
}
throw Exception(
(decoded is Map && decoded['detail'] != null)
? decoded['detail']
: 'Failed to update profile',
);
}
Future<Map<String, dynamic>> getUserById(int userId) async {
final token = await getAccessToken();
final response = await _client.get(
Uri.parse('${AppConstants.baseUrl}/users/$userId'),
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer $token',
},
);
if (response.statusCode == 200) {
return jsonDecode(utf8.decode(response.bodyBytes))
as Map<String, dynamic>;
}
throw Exception('Не удалось получить информацию о пользователе');
}
Future<bool> updatePrivacySettings({
bool? showEmail,
bool? showPhone,
bool? showAvatar,
bool? showAbout,
bool? showUsername,
}) async {
final token = await getAccessToken();
final response = await _client.put(
Uri.parse('${AppConstants.baseUrl}/users/me/privacy'),
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer $token',
},
body: jsonEncode({
if (showEmail != null) 'show_email': showEmail,
if (showPhone != null) 'show_phone': showPhone,
if (showAvatar != null) 'show_avatar': showAvatar,
if (showAbout != null) 'show_about': showAbout,
if (showUsername != null) 'show_username': showUsername,
}),
);
return response.statusCode == 200;
}
Future<Map<String, dynamic>> getPrivacySettings() async {
final token = await getAccessToken();
final response = await _client.get(
Uri.parse('${AppConstants.baseUrl}/users/me/privacy'),
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer $token',
},
);
if (response.statusCode == 200) {
return jsonDecode(utf8.decode(response.bodyBytes))
as Map<String, dynamic>;
}
throw Exception('Не удалось получить настройки конфиденциальности');
}
}