From c5df292be408f6256adcdd3affa37e25a1a156ab Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Thu, 14 Mar 2024 00:20:16 +0000 Subject: [PATCH 1/2] Add ff source code --- Source-Code/ff_source_code/pubspec.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Source-Code/ff_source_code/pubspec.yaml b/Source-Code/ff_source_code/pubspec.yaml index 662a5a9..39daec9 100644 --- a/Source-Code/ff_source_code/pubspec.yaml +++ b/Source-Code/ff_source_code/pubspec.yaml @@ -97,10 +97,10 @@ dependencies: supabase: 1.11.11 supabase_flutter: 1.10.24 timeago: 3.2.2 - url_launcher: 6.1.10 - url_launcher_android: 6.0.27 - url_launcher_ios: 6.1.4 - url_launcher_platform_interface: 2.1.2 + url_launcher: 6.2.5 + url_launcher_android: 6.3.0 + url_launcher_ios: 6.2.5 + url_launcher_platform_interface: 2.3.2 video_player: 2.8.1 video_player_android: 2.4.10 video_player_avfoundation: 2.5.1 From ae532507e45fd020015299322894b033274eeb56 Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Fri, 15 Mar 2024 00:20:32 +0000 Subject: [PATCH 2/2] Add ff source code --- .../ff_source_code/firebase/firebase.json | 8 +- .../lib/backend/api_requests/api_manager.dart | 151 ++++++++++++++---- 2 files changed, 122 insertions(+), 37 deletions(-) diff --git a/Source-Code/ff_source_code/firebase/firebase.json b/Source-Code/ff_source_code/firebase/firebase.json index 8ff9fc0..39bc7aa 100644 --- a/Source-Code/ff_source_code/firebase/firebase.json +++ b/Source-Code/ff_source_code/firebase/firebase.json @@ -9,11 +9,9 @@ "codebase": "functions" } ], - "storage": [ - { - "rules": "storage.rules" - } - ], + "storage": { + "rules": "storage.rules" + }, "hosting": { "public": "public", "ignore": ["firebase.json", "**/.*", "**/node_modules/**"] diff --git a/Source-Code/ff_source_code/lib/backend/api_requests/api_manager.dart b/Source-Code/ff_source_code/lib/backend/api_requests/api_manager.dart index ba07194..9de8a13 100644 --- a/Source-Code/ff_source_code/lib/backend/api_requests/api_manager.dart +++ b/Source-Code/ff_source_code/lib/backend/api_requests/api_manager.dart @@ -1,6 +1,8 @@ +// ignore_for_file: constant_identifier_names, depend_on_referenced_packages, prefer_final_fields + import 'dart:convert'; -import 'dart:io'; import 'dart:core'; +import 'dart:io'; import 'dart:typed_data'; import 'package:collection/collection.dart'; @@ -9,7 +11,7 @@ import 'package:equatable/equatable.dart'; import 'package:http_parser/http_parser.dart'; import 'package:mime_type/mime_type.dart'; -import '../../flutter_flow/uploaded_file.dart'; +import '/flutter_flow/uploaded_file.dart'; enum ApiCallType { GET, @@ -27,19 +29,73 @@ enum BodyType { MULTIPART, } -class ApiCallRecord extends Equatable { - ApiCallRecord(this.callName, this.apiUrl, this.headers, this.params, - this.body, this.bodyType); +class ApiCallOptions extends Equatable { + const ApiCallOptions({ + this.callName = '', + required this.callType, + required this.apiUrl, + required this.headers, + required this.params, + this.bodyType, + this.body, + this.returnBody = true, + this.encodeBodyUtf8 = false, + this.decodeUtf8 = false, + this.alwaysAllowBody = false, + this.cache = false, + }); + final String callName; + final ApiCallType callType; final String apiUrl; final Map headers; final Map params; - final String? body; final BodyType? bodyType; + final String? body; + final bool returnBody; + final bool encodeBodyUtf8; + final bool decodeUtf8; + final bool alwaysAllowBody; + final bool cache; + + ApiCallOptions clone() => ApiCallOptions( + callName: callName, + callType: callType, + apiUrl: apiUrl, + headers: _cloneMap(headers), + params: _cloneMap(params), + bodyType: bodyType, + body: body, + returnBody: returnBody, + encodeBodyUtf8: encodeBodyUtf8, + decodeUtf8: decodeUtf8, + alwaysAllowBody: alwaysAllowBody, + cache: cache, + ); @override - List get props => - [callName, apiUrl, headers, params, body, bodyType]; + List get props => [ + callName, + callType.name, + apiUrl, + headers, + params, + bodyType, + body, + returnBody, + encodeBodyUtf8, + decodeUtf8, + alwaysAllowBody, + cache, + ]; + + static Map _cloneMap(Map map) { + try { + return json.decode(json.encode(map)) as Map; + } catch (_) { + return Map.from(map); + } + } } class ApiCallResponse { @@ -48,11 +104,13 @@ class ApiCallResponse { this.headers, this.statusCode, { this.response, + this.exception, }); final dynamic jsonBody; final Map headers; final int statusCode; final http.Response? response; + final Object? exception; // Whether we received a 2xx status (which generally marks success). bool get succeeded => statusCode >= 200 && statusCode < 300; String getHeader(String headerName) => headers[headerName] ?? ''; @@ -67,7 +125,7 @@ class ApiCallResponse { bool returnBody, bool decodeUtf8, ) { - var jsonBody; + dynamic jsonBody; try { final responseBody = decodeUtf8 && returnBody ? const Utf8Decoder().convert(response.bodyBytes) @@ -94,7 +152,7 @@ class ApiManager { ApiManager._(); // Cache that will ensure identical calls are not repeatedly made. - static Map _apiCache = {}; + static Map _apiCache = {}; static ApiManager? _instance; static ApiManager get instance => _instance ??= ApiManager._(); @@ -191,28 +249,31 @@ class ApiManager { (alwaysAllowBody && type == ApiCallType.DELETE), 'Invalid ApiCallType $type for request with body', ); - bool Function(dynamic) _isFile = (e) => + + bool isFile(dynamic e) => e is FFUploadedFile || e is List || (e is List && e.firstOrNull is FFUploadedFile); final nonFileParams = toStringMap( - Map.fromEntries(params.entries.where((e) => !_isFile(e.value)))); + Map.fromEntries(params.entries.where((e) => !isFile(e.value)))); List files = []; - params.entries.where((e) => _isFile(e.value)).forEach((e) { + params.entries.where((e) => isFile(e.value)).forEach((e) { final param = e.value; final uploadedFiles = param is List ? param as List : [param as FFUploadedFile]; - uploadedFiles.forEach((uploadedFile) => files.add( - http.MultipartFile.fromBytes( - e.key, - uploadedFile.bytes ?? Uint8List.fromList([]), - filename: uploadedFile.name, - contentType: _getMediaType(uploadedFile.name), - ), - )); + for (var uploadedFile in uploadedFiles) { + files.add( + http.MultipartFile.fromBytes( + e.key, + uploadedFile.bytes ?? Uint8List.fromList([]), + filename: uploadedFile.name, + contentType: _getMediaType(uploadedFile.name), + ), + ); + } }); final request = http.MultipartRequest( @@ -277,6 +338,22 @@ class ApiManager { : postBody; } + Future call(ApiCallOptions options) => makeApiCall( + callName: options.callName, + apiUrl: options.apiUrl, + callType: options.callType, + headers: options.headers, + params: options.params, + body: options.body, + bodyType: options.bodyType, + returnBody: options.returnBody, + encodeBodyUtf8: options.encodeBodyUtf8, + decodeUtf8: options.decodeUtf8, + alwaysAllowBody: options.alwaysAllowBody, + cache: options.cache, + options: options, + ); + Future makeApiCall({ required String callName, required String apiUrl, @@ -288,12 +365,26 @@ class ApiManager { bool returnBody = true, bool encodeBodyUtf8 = false, bool decodeUtf8 = false, - bool cache = false, bool alwaysAllowBody = false, + bool cache = false, + ApiCallOptions? options, http.Client? client, }) async { - final callRecord = - ApiCallRecord(callName, apiUrl, headers, params, body, bodyType); + final callOptions = options ?? + ApiCallOptions( + callName: callName, + callType: callType, + apiUrl: apiUrl, + headers: headers, + params: params, + bodyType: bodyType, + body: body, + returnBody: returnBody, + encodeBodyUtf8: encodeBodyUtf8, + decodeUtf8: decodeUtf8, + alwaysAllowBody: alwaysAllowBody, + cache: cache, + ); // Modify for your specific needs if this differs from your API. if (_accessToken != null) { headers[HttpHeaders.authorizationHeader] = 'Bearer $_accessToken'; @@ -304,8 +395,8 @@ class ApiManager { // If we've already made this exact call before and caching is on, // return the cached result. - if (cache && _apiCache.containsKey(callRecord)) { - return _apiCache[callRecord]!; + if (cache && _apiCache.containsKey(callOptions)) { + return _apiCache[callOptions]!; } ApiCallResponse result; @@ -368,14 +459,10 @@ class ApiManager { // If caching is on, cache the result (if present). if (cache) { - _apiCache[callRecord] = result; + _apiCache[callOptions] = result; } } catch (e) { - result = ApiCallResponse( - null, - {}, - -1, - ); + result = ApiCallResponse(null, {}, -1, exception: e); } return result;