mirror of
https://gitlab.com/foxixus/neomovies_mobile.git
synced 2025-10-28 01:18:50 +05:00
v0.0.3
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
# Gradle JVM settings - optimized for limited RAM
|
# Gradle JVM settings - optimized for limited RAM
|
||||||
org.gradle.jvmargs=-Xmx2G -XX:MaxMetaspaceSize=1G -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
|
org.gradle.jvmargs=-Xmx3G -XX:MaxMetaspaceSize=1G -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
|
||||||
org.gradle.daemon=true
|
org.gradle.daemon=true
|
||||||
org.gradle.parallel=true
|
org.gradle.parallel=false
|
||||||
org.gradle.caching=true
|
org.gradle.caching=true
|
||||||
org.gradle.configureondemand=true
|
org.gradle.configureondemand=true
|
||||||
|
|
||||||
|
|||||||
@@ -57,8 +57,12 @@ class ApiClient {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> removeFavorite(String mediaId) {
|
Future<void> removeFavorite(String mediaId, {String mediaType = 'movie'}) {
|
||||||
return _neoClient.removeFavorite(mediaId);
|
return _neoClient.removeFavorite(mediaId, mediaType: mediaType);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<bool> checkIsFavorite(String mediaId, {String mediaType = 'movie'}) {
|
||||||
|
return _neoClient.checkIsFavorite(mediaId, mediaType: mediaType);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---- Reactions ----
|
// ---- Reactions ----
|
||||||
|
|||||||
@@ -189,7 +189,12 @@ class NeoMoviesApiClient {
|
|||||||
final response = await _client.get(uri);
|
final response = await _client.get(uri);
|
||||||
|
|
||||||
if (response.statusCode == 200) {
|
if (response.statusCode == 200) {
|
||||||
return Movie.fromJson(json.decode(response.body));
|
final apiResponse = json.decode(response.body);
|
||||||
|
// API returns: {"success": true, "data": {...}}
|
||||||
|
final movieData = (apiResponse is Map && apiResponse['data'] != null)
|
||||||
|
? apiResponse['data']
|
||||||
|
: apiResponse;
|
||||||
|
return Movie.fromJson(movieData);
|
||||||
} else {
|
} else {
|
||||||
throw Exception('Failed to load movie: ${response.statusCode}');
|
throw Exception('Failed to load movie: ${response.statusCode}');
|
||||||
}
|
}
|
||||||
@@ -225,7 +230,12 @@ class NeoMoviesApiClient {
|
|||||||
final response = await _client.get(uri);
|
final response = await _client.get(uri);
|
||||||
|
|
||||||
if (response.statusCode == 200) {
|
if (response.statusCode == 200) {
|
||||||
return Movie.fromJson(json.decode(response.body));
|
final apiResponse = json.decode(response.body);
|
||||||
|
// API returns: {"success": true, "data": {...}}
|
||||||
|
final tvData = (apiResponse is Map && apiResponse['data'] != null)
|
||||||
|
? apiResponse['data']
|
||||||
|
: apiResponse;
|
||||||
|
return Movie.fromJson(tvData);
|
||||||
} else {
|
} else {
|
||||||
throw Exception('Failed to load TV show: ${response.statusCode}');
|
throw Exception('Failed to load TV show: ${response.statusCode}');
|
||||||
}
|
}
|
||||||
@@ -266,7 +276,11 @@ class NeoMoviesApiClient {
|
|||||||
final response = await _client.get(uri);
|
final response = await _client.get(uri);
|
||||||
|
|
||||||
if (response.statusCode == 200) {
|
if (response.statusCode == 200) {
|
||||||
final List<dynamic> data = json.decode(response.body);
|
final apiResponse = json.decode(response.body);
|
||||||
|
// API returns: {"success": true, "data": [...]}
|
||||||
|
final List<dynamic> data = (apiResponse is Map && apiResponse['data'] != null)
|
||||||
|
? (apiResponse['data'] is List ? apiResponse['data'] : [])
|
||||||
|
: (apiResponse is List ? apiResponse : []);
|
||||||
return data.map((json) => Favorite.fromJson(json)).toList();
|
return data.map((json) => Favorite.fromJson(json)).toList();
|
||||||
} else {
|
} else {
|
||||||
throw Exception('Failed to fetch favorites: ${response.body}');
|
throw Exception('Failed to fetch favorites: ${response.body}');
|
||||||
@@ -274,23 +288,17 @@ class NeoMoviesApiClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Add movie/show to favorites
|
/// Add movie/show to favorites
|
||||||
|
/// Backend automatically fetches title and poster_path from TMDB
|
||||||
Future<void> addFavorite({
|
Future<void> addFavorite({
|
||||||
required String mediaId,
|
required String mediaId,
|
||||||
required String mediaType,
|
required String mediaType,
|
||||||
required String title,
|
required String title,
|
||||||
required String posterPath,
|
required String posterPath,
|
||||||
}) async {
|
}) async {
|
||||||
final uri = Uri.parse('$apiUrl/favorites');
|
// Backend route: POST /favorites/{id}?type={mediaType}
|
||||||
final response = await _client.post(
|
final uri = Uri.parse('$apiUrl/favorites/$mediaId')
|
||||||
uri,
|
.replace(queryParameters: {'type': mediaType});
|
||||||
headers: {'Content-Type': 'application/json'},
|
final response = await _client.post(uri);
|
||||||
body: json.encode({
|
|
||||||
'mediaId': mediaId,
|
|
||||||
'mediaType': mediaType,
|
|
||||||
'title': title,
|
|
||||||
'posterPath': posterPath,
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
if (response.statusCode != 200 && response.statusCode != 201) {
|
if (response.statusCode != 200 && response.statusCode != 201) {
|
||||||
throw Exception('Failed to add favorite: ${response.body}');
|
throw Exception('Failed to add favorite: ${response.body}');
|
||||||
@@ -298,8 +306,10 @@ class NeoMoviesApiClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Remove movie/show from favorites
|
/// Remove movie/show from favorites
|
||||||
Future<void> removeFavorite(String mediaId) async {
|
Future<void> removeFavorite(String mediaId, {String mediaType = 'movie'}) async {
|
||||||
final uri = Uri.parse('$apiUrl/favorites/$mediaId');
|
// Backend route: DELETE /favorites/{id}?type={mediaType}
|
||||||
|
final uri = Uri.parse('$apiUrl/favorites/$mediaId')
|
||||||
|
.replace(queryParameters: {'type': mediaType});
|
||||||
final response = await _client.delete(uri);
|
final response = await _client.delete(uri);
|
||||||
|
|
||||||
if (response.statusCode != 200 && response.statusCode != 204) {
|
if (response.statusCode != 200 && response.statusCode != 204) {
|
||||||
@@ -307,6 +317,26 @@ class NeoMoviesApiClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check if media is in favorites
|
||||||
|
Future<bool> checkIsFavorite(String mediaId, {String mediaType = 'movie'}) async {
|
||||||
|
// Backend route: GET /favorites/{id}/check?type={mediaType}
|
||||||
|
final uri = Uri.parse('$apiUrl/favorites/$mediaId/check')
|
||||||
|
.replace(queryParameters: {'type': mediaType});
|
||||||
|
final response = await _client.get(uri);
|
||||||
|
|
||||||
|
if (response.statusCode == 200) {
|
||||||
|
final apiResponse = json.decode(response.body);
|
||||||
|
// API returns: {"success": true, "data": {"isFavorite": true}}
|
||||||
|
if (apiResponse is Map && apiResponse['data'] != null) {
|
||||||
|
final data = apiResponse['data'];
|
||||||
|
return data['isFavorite'] ?? false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
throw Exception('Failed to check favorite status: ${response.body}');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ============================================
|
// ============================================
|
||||||
// Reactions Endpoints (NEW!)
|
// Reactions Endpoints (NEW!)
|
||||||
// ============================================
|
// ============================================
|
||||||
@@ -351,7 +381,11 @@ class NeoMoviesApiClient {
|
|||||||
final response = await _client.get(uri);
|
final response = await _client.get(uri);
|
||||||
|
|
||||||
if (response.statusCode == 200) {
|
if (response.statusCode == 200) {
|
||||||
final List<dynamic> data = json.decode(response.body);
|
final apiResponse = json.decode(response.body);
|
||||||
|
// API returns: {"success": true, "data": [...]}
|
||||||
|
final List<dynamic> data = (apiResponse is Map && apiResponse['data'] != null)
|
||||||
|
? (apiResponse['data'] is List ? apiResponse['data'] : [])
|
||||||
|
: (apiResponse is List ? apiResponse : []);
|
||||||
return data.map((json) => UserReaction.fromJson(json)).toList();
|
return data.map((json) => UserReaction.fromJson(json)).toList();
|
||||||
} else {
|
} else {
|
||||||
throw Exception('Failed to get my reactions: ${response.body}');
|
throw Exception('Failed to get my reactions: ${response.body}');
|
||||||
@@ -433,8 +467,18 @@ class NeoMoviesApiClient {
|
|||||||
if (response.statusCode == 200) {
|
if (response.statusCode == 200) {
|
||||||
final decoded = json.decode(response.body);
|
final decoded = json.decode(response.body);
|
||||||
|
|
||||||
|
// API returns: {"success": true, "data": {"page": 1, "results": [...], ...}}
|
||||||
List<dynamic> results;
|
List<dynamic> results;
|
||||||
if (decoded is List) {
|
if (decoded is Map && decoded['success'] == true && decoded['data'] != null) {
|
||||||
|
final data = decoded['data'];
|
||||||
|
if (data is Map && data['results'] != null) {
|
||||||
|
results = data['results'];
|
||||||
|
} else if (data is List) {
|
||||||
|
results = data;
|
||||||
|
} else {
|
||||||
|
throw Exception('Unexpected data format in API response');
|
||||||
|
}
|
||||||
|
} else if (decoded is List) {
|
||||||
results = decoded;
|
results = decoded;
|
||||||
} else if (decoded is Map && decoded['results'] != null) {
|
} else if (decoded is Map && decoded['results'] != null) {
|
||||||
results = decoded['results'];
|
results = decoded['results'];
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
import 'package:flutter_dotenv/flutter_dotenv.dart';
|
import 'package:flutter_dotenv/flutter_dotenv.dart';
|
||||||
|
|
||||||
class Favorite {
|
class Favorite {
|
||||||
final int id;
|
final String id; // MongoDB ObjectID as string
|
||||||
final String mediaId;
|
final String mediaId;
|
||||||
final String mediaType;
|
final String mediaType; // "movie" or "tv"
|
||||||
final String title;
|
final String title;
|
||||||
final String posterPath;
|
final String posterPath;
|
||||||
|
final DateTime? createdAt;
|
||||||
|
|
||||||
Favorite({
|
Favorite({
|
||||||
required this.id,
|
required this.id,
|
||||||
@@ -13,15 +14,19 @@ class Favorite {
|
|||||||
required this.mediaType,
|
required this.mediaType,
|
||||||
required this.title,
|
required this.title,
|
||||||
required this.posterPath,
|
required this.posterPath,
|
||||||
|
this.createdAt,
|
||||||
});
|
});
|
||||||
|
|
||||||
factory Favorite.fromJson(Map<String, dynamic> json) {
|
factory Favorite.fromJson(Map<String, dynamic> json) {
|
||||||
return Favorite(
|
return Favorite(
|
||||||
id: json['id'] as int? ?? 0,
|
id: json['id'] as String? ?? '',
|
||||||
mediaId: json['mediaId'] as String? ?? '',
|
mediaId: json['mediaId'] as String? ?? '',
|
||||||
mediaType: json['mediaType'] as String? ?? '',
|
mediaType: json['mediaType'] as String? ?? 'movie',
|
||||||
title: json['title'] as String? ?? '',
|
title: json['title'] as String? ?? '',
|
||||||
posterPath: json['posterPath'] as String? ?? '',
|
posterPath: json['posterPath'] as String? ?? '',
|
||||||
|
createdAt: json['createdAt'] != null
|
||||||
|
? DateTime.tryParse(json['createdAt'] as String)
|
||||||
|
: null,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user