@@ -17,12 +17,13 @@ import 'package:piwigo_ng/components/dialogs/confirm_dialog.dart';
1717import 'package:piwigo_ng/services/preferences_service.dart' ;
1818import 'package:piwigo_ng/services/upload_notifier.dart' ;
1919import 'package:piwigo_ng/utils/localizations.dart' ;
20+ import 'package:piwigo_ng/views/upload/upload_status_page.dart' ;
2021import 'package:provider/provider.dart' ;
2122
2223import '../services/chunked_uploader.dart' ;
2324import '../services/notification_service.dart' ;
2425
25- Future <void > _showUploadNotification ({ bool success = true } ) async {
26+ Future <void > _showUploadNotification ([ int nbError = 0 , int nbImage = 0 ] ) async {
2627 if (! Preferences .getUploadNotification) return ;
2728 final android = AndroidNotificationDetails (
2829 'piwigo-ng-upload' ,
@@ -32,20 +33,33 @@ Future<void> _showUploadNotification({bool success = true}) async {
3233 importance: Importance .high,
3334 );
3435 final platform = NotificationDetails (android: android);
35- await localNotification.show (
36- 1 ,
37- success ? 'Success' : 'Failure' ,
38- success ? appStrings.imageUploadCompleted_message : appStrings.uploadError_message,
39- platform,
40- );
36+ late String title;
37+ String ? message;
38+ if (nbError == 0 && nbImage == 0 ) {
39+ // Upload cancelled
40+ title = appStrings.uploadCancelled_title;
41+ } else if (nbError == 0 && nbImage > 0 ) {
42+ // Upload completed
43+ title = appStrings.imageUploadCompleted_title;
44+ message = nbImage == 1 ? appStrings.imageUploadCompleted_message : appStrings.imageUploadCompleted_message1;
45+ } else if (nbError > 0 && nbImage != nbError) {
46+ // Upload partially completed
47+ title = appStrings.coreDataStore_WarningTitle;
48+ message = appStrings.imageUploadCompleted_warning;
49+ } else {
50+ // Upload failed
51+ title = appStrings.uploadError_title;
52+ message = appStrings.uploadError_message;
53+ }
54+ await localNotification.show (1 , title, message, platform);
4155}
4256
43- Future <List <Map < String , dynamic > >> uploadPhotos (
57+ Future <List <int >> uploadPhotos (
4458 List <XFile > photos,
4559 int albumId, {
4660 Map <String , dynamic > info = const {},
4761}) async {
48- /// Check if Wifi is enabled and working
62+ // Check if Wifi is enabled and working
4963 if (Preferences .getWifiUpload) {
5064 var connectivity = await Connectivity ().checkConnectivity ();
5165 if (connectivity != ConnectivityResult .wifi) {
@@ -60,17 +74,17 @@ Future<List<Map<String, dynamic>>> uploadPhotos(
6074 }
6175 }
6276
63- List <Map <String , dynamic >> result = [];
64- List <int > uploadCompletedList = [];
77+ List <int > result = [];
6578 List <UploadItem > items = [];
6679 FlutterSecureStorage storage = const FlutterSecureStorage ();
6780 String ? url = await storage.read (key: 'SERVER_URL' );
6881 if (url == null ) return [];
6982 String ? username = await storage.read (key: 'SERVER_USERNAME' );
7083 String ? password = await storage.read (key: 'SERVER_PASSWORD' );
7184 UploadNotifier uploadNotifier = App .appKey.currentContext! .read <UploadNotifier >();
85+ int nbError = 0 ;
7286
73- /// Creates Upload Item list for the upload notifier
87+ // Creates Upload Item list for the upload notifier
7488 for (var photo in photos) {
7589 File ? compressedFile;
7690 if (Preferences .getRemoveMetadata) {
@@ -86,52 +100,55 @@ Future<List<Map<String, dynamic>>> uploadPhotos(
86100
87101 uploadNotifier.addItems (items);
88102
89- /// Upload loop
90- for (var item in items) {
103+ App .navigatorKey.currentState? .popAndPushNamed (UploadStatusPage .routeName);
104+
105+ await Future .wait (List <Future <void >>.generate (items.length, (index) async {
106+ UploadItem item = items[index];
91107 try {
92- /// Make Request
108+ // Make Request
93109 Response ? response = await uploadChunk (
94110 photo: item.file,
95111 category: albumId,
96112 url: url,
97113 username: username,
98114 password: password,
99115 info: info,
116+ cancelToken: item.cancelToken,
100117 onProgress: (progress) {
101- // debugPrint("$progress");
102118 item.progress.sink.add (progress);
103119 },
104120 );
105- if (response != null ) {
106- var data = json.decode (response.data);
107- if (data['stat' ] != 'fail' ) {
108- result.add ({
109- 'id' : data['result' ]['id' ],
110- 'url' : data['result' ]['element_url' ],
111- });
112121
113- /// Notify provider upload completed
114- uploadNotifier.itemUploadCompleted (item);
115- if (Preferences .getDeleteAfterUpload) {
116- // todo: delete real file path, not the cached one.
117- }
118- } else {
122+ // Handle result
123+ if (response == null || json.decode (response.data)['stat' ] == 'fail' ) {
124+ if (! item.cancelToken.isCancelled) {
119125 uploadNotifier.itemUploadCompleted (item, error: true );
126+ nbError++ ;
120127 }
121128 } else {
122- uploadNotifier.itemUploadCompleted (item, error: true );
129+ var data = json.decode (response.data);
130+ result.add (data['result' ]['id' ]);
131+
132+ // Notify provider upload completed
133+ uploadNotifier.itemUploadCompleted (item);
134+ if (Preferences .getDeleteAfterUpload) {
135+ // todo: delete real file path, not the cached one.
136+ }
123137 }
138+ } on DioError catch (e) {
139+ debugPrint ("${e .type }" );
124140 } catch (e) {
125141 debugPrint ("$e " );
142+ nbError++ ;
126143 }
127- }
128- _showUploadNotification (success: result.isNotEmpty);
144+ }));
145+
146+ _showUploadNotification (nbError, result.length);
129147 if (result.isEmpty) return [];
130- uploadCompletedList = result.map <int >((e) => e['id' ]).toList ();
131148 try {
132- await uploadCompleted (uploadCompletedList , albumId);
149+ await uploadCompleted (result , albumId);
133150 if (await methodExist ('community.images.uploadCompleted' )) {
134- await communityUploadCompleted (uploadCompletedList , albumId);
151+ await communityUploadCompleted (result , albumId);
135152 }
136153 } on DioError catch (e) {
137154 debugPrint (e.message);
@@ -148,6 +165,7 @@ Future<Response?> uploadChunk({
148165 Function (double )? onProgress,
149166 String ? username,
150167 String ? password,
168+ CancelToken ? cancelToken,
151169}) async {
152170 Map <String , String > queries = {
153171 'format' : 'json' ,
@@ -178,6 +196,7 @@ Future<Response?> uploadChunk({
178196 params: queries,
179197 method: 'POST' ,
180198 data: fields,
199+ cancelToken: cancelToken,
181200 contentType: Headers .formUrlEncodedContentType,
182201 onUploadProgress: (value) {
183202 if (onProgress != null ) onProgress (value);
0 commit comments