Skip to content

Commit 87f496b

Browse files
authored
Merge pull request #5 from tassid/feat/profile
Feat/profile
2 parents 2876dbf + 446ec7b commit 87f496b

File tree

22 files changed

+1032
-187
lines changed

22 files changed

+1032
-187
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
.history
1010
.svn/
1111
migrate_working_dir/
12+
user-profile-api/firebase-adminsdk.json
13+
GoogleService-Info.plist
1214

1315
# IntelliJ related
1416
*.iml

ios/Podfile.lock

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ PODS:
6767
- FlutterMacOS
6868
- url_launcher_ios (0.0.1):
6969
- Flutter
70+
- webview_flutter_wkwebview (0.0.1):
71+
- Flutter
7072

7173
DEPENDENCIES:
7274
- firebase_auth (from `.symlinks/plugins/firebase_auth/ios`)
@@ -76,6 +78,7 @@ DEPENDENCIES:
7678
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
7779
- sqflite (from `.symlinks/plugins/sqflite/darwin`)
7880
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
81+
- webview_flutter_wkwebview (from `.symlinks/plugins/webview_flutter_wkwebview/ios`)
7982

8083
SPEC REPOS:
8184
trunk:
@@ -105,6 +108,8 @@ EXTERNAL SOURCES:
105108
:path: ".symlinks/plugins/sqflite/darwin"
106109
url_launcher_ios:
107110
:path: ".symlinks/plugins/url_launcher_ios/ios"
111+
webview_flutter_wkwebview:
112+
:path: ".symlinks/plugins/webview_flutter_wkwebview/ios"
108113

109114
SPEC CHECKSUMS:
110115
Firebase: 0312a2352584f782ea56f66d91606891d4607f06
@@ -124,6 +129,7 @@ SPEC CHECKSUMS:
124129
RecaptchaInterop: 7d1a4a01a6b2cb1610a47ef3f85f0c411434cb21
125130
sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec
126131
url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe
132+
webview_flutter_wkwebview: 2a23822e9039b7b1bc52e5add778e5d89ad488d1
127133

128134
PODFILE CHECKSUM: 819463e6a0290f5a72f145ba7cde16e8b6ef0796
129135

ios/Runner/Info.plist

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,5 +45,11 @@
4545
<true/>
4646
<key>UIApplicationSupportsIndirectInputEvents</key>
4747
<true/>
48+
<key>NSAppTransportSecurity</key>
49+
<dict>
50+
<key>NSAllowsArbitraryLoads</key>
51+
<true/>
52+
</dict>
53+
4854
</dict>
4955
</plist>

lib/models/movie.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ class Movie {
4040
);
4141
}
4242

43+
get imageUrl => null;
44+
4345
String getPosterUrl() {
4446
return posterPath.isNotEmpty
4547
? 'https://image.tmdb.org/t/p/w500$posterPath'

lib/services/api_service.dart

Lines changed: 68 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,72 @@
11
import 'dart:convert';
22
import 'package:flutter/foundation.dart';
33
import 'package:http/http.dart' as http;
4+
import 'package:firebase_auth/firebase_auth.dart';
45
import 'package:app_streaming/models/movie.dart';
56

67
class ApiService {
78
final String apiKey = '36fd01cdc2a54f3273838051a253d2f5';
89
final String baseUrl = 'https://api.themoviedb.org/3';
910
final String language = 'pt-BR'; // Define o idioma para português do Brasil
11+
final String flaskApiUrl = "http://172.17.0.2:5000/";
12+
13+
Future<Map<String, String>> _getHeaders() async {
14+
String? token = await FirebaseAuth.instance.currentUser?.getIdToken();
15+
return {
16+
'Authorization': 'Bearer $token',
17+
'Content-Type': 'application/json',
18+
};
19+
}
20+
21+
Future<List<Movie>> fetchMoviesFromFlaskAPI(int profileId) async {
22+
final headers = await _getHeaders();
23+
final response = await http.get(
24+
Uri.parse('$flaskApiUrl/profiles/$profileId/movies'),
25+
headers: headers);
26+
27+
if (response.statusCode == 200) {
28+
final List moviesJson = jsonDecode(response.body);
29+
return moviesJson.map((json) => Movie.fromJson(json)).toList();
30+
} else {
31+
throw Exception('Failed to load movies from Flask API');
32+
}
33+
}
34+
35+
// Adicionar um filme à lista de filmes do perfil
36+
Future<void> addMovieToList(int profileId, int movieId, bool liked) async {
37+
final headers = await _getHeaders();
38+
final response = await http.post(
39+
Uri.parse('$flaskApiUrl/profiles/$profileId/movies'),
40+
headers: headers,
41+
body: json.encode({
42+
'title': movieId.toString(),
43+
'liked': liked,
44+
}),
45+
);
46+
47+
if (response.statusCode != 201) {
48+
throw Exception('Failed to add movie to list');
49+
}
50+
}
51+
52+
// Método para verificar ou criar o perfil no backend Flask
53+
Future<void> verifyOrCreateUserProfile(String email) async {
54+
final headers = await _getHeaders();
55+
final response = await http.post(
56+
Uri.parse('$flaskApiUrl/verify_or_create_profile'),
57+
headers: headers,
58+
body: json.encode({'email': email}),
59+
);
60+
61+
if (response.statusCode != 200) {
62+
throw Exception('Failed to verify or create profile');
63+
}
64+
}
1065

1166
Future<List<Movie>> fetchMovies(String genreId) async {
1267
final response = await http.get(Uri.parse(
1368
'$baseUrl/discover/movie?api_key=$apiKey&language=$language&with_genres=$genreId'));
1469

15-
// Add debugging information
1670
if (kDebugMode) {
1771
print('Fetching movies for genre ID: $genreId');
1872
print(
@@ -26,24 +80,18 @@ class ApiService {
2680

2781
if (jsonResponse['results'] != null && jsonResponse['results'] is List) {
2882
final List results = jsonResponse['results'];
29-
30-
if (results.isNotEmpty) {
31-
return results.map((movie) => Movie.fromJson(movie)).toList();
32-
} else {
33-
return []; // No results
34-
}
83+
return results.map((movie) => Movie.fromJson(movie)).toList();
3584
} else {
3685
if (kDebugMode) {
3786
print('Results is null or not a list');
3887
}
39-
return []; // Results is null or not a list
88+
return [];
4089
}
4190
} else {
4291
throw Exception('Failed to load movies');
4392
}
4493
}
4594

46-
// Função para buscar os detalhes de um filme
4795
Future<Movie> fetchMovieDetails(int movieId) async {
4896
final response = await http.get(Uri.parse(
4997
'$baseUrl/movie/$movieId?api_key=$apiKey&language=$language&append_to_response=videos'));
@@ -56,7 +104,6 @@ class ApiService {
56104
}
57105
}
58106

59-
// Função para buscar o trailer de um filme
60107
Future<String> fetchTrailer(int movieId) async {
61108
final response = await http.get(Uri.parse(
62109
'$baseUrl/movie/$movieId/videos?api_key=$apiKey&language=$language'));
@@ -73,22 +120,19 @@ class ApiService {
73120
}
74121
}
75122

76-
// Método para buscar filmes relacionados
77123
Future<List<Movie>> fetchRelatedMovies(int movieId) async {
78124
final response = await http.get(Uri.parse(
79125
'$baseUrl/movie/$movieId/similar?api_key=$apiKey&language=$language'));
80126

81127
if (response.statusCode == 200) {
82128
final jsonResponse = jsonDecode(response.body);
83129
final List results = jsonResponse['results'];
84-
85130
return results.map((movie) => Movie.fromJson(movie)).toList();
86131
} else {
87132
throw Exception('Failed to load related movies');
88133
}
89134
}
90135

91-
// Função para buscar todos os gêneros de filmes
92136
Future<Map<int, String>> fetchGenres() async {
93137
final response = await http.get(Uri.parse(
94138
'$baseUrl/genre/movie/list?api_key=$apiKey&language=$language'));
@@ -97,7 +141,7 @@ class ApiService {
97141
final jsonResponse = jsonDecode(response.body);
98142
final List genres = jsonResponse['genres'];
99143

100-
// Converta a lista de gêneros em um mapa de ID para nome
144+
// Convert the list of genres into a map of ID to name
101145
return {for (var genre in genres) genre['id']: genre['name']};
102146
} else {
103147
throw Exception('Failed to load genres');
@@ -109,11 +153,9 @@ class ApiService {
109153
String url;
110154

111155
if (isGenre) {
112-
// If it's a genre, use the discover endpoint with genres
113156
url =
114157
'$baseUrl/discover/movie?api_key=$apiKey&language=$language&with_genres=$categoryOrGenreId';
115158
} else {
116-
// If it's a predefined category (e.g., popular), use the specific endpoint
117159
url =
118160
'$baseUrl/movie/$categoryOrGenreId?api_key=$apiKey&language=$language';
119161
}
@@ -132,12 +174,7 @@ class ApiService {
132174

133175
if (jsonResponse['results'] != null && jsonResponse['results'] is List) {
134176
final List results = jsonResponse['results'];
135-
136-
if (results.isNotEmpty) {
137-
return results.map((movie) => Movie.fromJson(movie)).toList();
138-
} else {
139-
return [];
140-
}
177+
return results.map((movie) => Movie.fromJson(movie)).toList();
141178
} else {
142179
return [];
143180
}
@@ -146,14 +183,15 @@ class ApiService {
146183
}
147184
}
148185

149-
Future<List<Movie>> searchMoviesByTitle(
150-
{required String title,
151-
bool includeAdult = false,
152-
String language = 'pt-BR',
153-
int page = 1,
154-
String? region,
155-
String? year,
156-
String? primaryReleaseYear}) async {
186+
Future<List<Movie>> searchMoviesByTitle({
187+
required String title,
188+
bool includeAdult = false,
189+
String language = 'pt-BR',
190+
int page = 1,
191+
String? region,
192+
String? year,
193+
String? primaryReleaseYear,
194+
}) async {
157195
final Uri uri = Uri.parse(
158196
'$baseUrl/search/movie',
159197
).replace(queryParameters: {

lib/views/home/bars/app_bar_extra.dart

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import 'package:app_streaming/views/home/search/search_page.dart';
2+
import 'package:app_streaming/views/home/settings_page.dart';
13
import 'package:flutter/material.dart';
24
import 'dart:ui';
35

@@ -46,18 +48,28 @@ class AppBarExtra extends StatelessWidget implements PreferredSizeWidget {
4648
),
4749
Row(
4850
children: [
49-
IconButton(
50-
icon: const Icon(Icons.cast, color: Colors.white),
51-
onPressed: () {},
52-
),
5351
IconButton(
5452
icon: const Icon(Icons.search, color: Colors.white),
55-
onPressed: () {},
53+
onPressed: () {
54+
Navigator.push(
55+
context,
56+
MaterialPageRoute(
57+
builder: (context) => const SearchPage(),
58+
),
59+
);
60+
},
5661
),
5762
IconButton(
5863
icon: const Icon(Icons.account_circle,
5964
color: Colors.white),
60-
onPressed: () {},
65+
onPressed: () {
66+
Navigator.push(
67+
context,
68+
MaterialPageRoute(
69+
builder: (context) => const SettingsPage(),
70+
),
71+
);
72+
},
6173
),
6274
],
6375
),

0 commit comments

Comments
 (0)