Skip to content

Commit fb49ef1

Browse files
authored
Merge pull request #2 from Piwigo/master
updating
2 parents 53c9784 + 51f9e14 commit fb49ef1

27 files changed

Lines changed: 1911 additions & 571 deletions

LICENCE.txt

Lines changed: 339 additions & 0 deletions
Large diffs are not rendered by default.

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,3 +100,9 @@ The connection to the server is made with the Piwigo's API.
100100
## Upload
101101

102102
For the upload, we are using the **uploadAsync** method of the API. This method requires to **chunk** the image with a size given by the server. All chunks are uploaded simultaneously and reorganized by the server.
103+
104+
105+
# Licence
106+
107+
Piwigo is a free software, it can be redistributed it and / or modified under the terms of the GNU General Public License
108+
[see more here](./LICENCE.txt)

android/app/src/main/AndroidManifest.xml

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,13 @@
77
<uses-permission android:name="android.permission.INTERNET"/>
88

99
<application
10-
android:label="piwigo_ng"
10+
android:label="Piwigo NG"
1111
android:usesCleartextTraffic="true"
1212
android:requestLegacyExternalStorage="true"
1313
android:icon="@mipmap/ic_launcher">
1414
<activity
1515
android:name=".MainActivity"
16+
android:exported="true"
1617
android:launchMode="singleTop"
1718
android:theme="@style/LaunchTheme"
1819
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
@@ -26,15 +27,6 @@
2627
android:name="io.flutter.embedding.android.NormalTheme"
2728
android:resource="@style/NormalTheme"
2829
/>
29-
<!-- Displays an Android View that continues showing the launch screen
30-
Drawable until Flutter paints its first frame, then this splash
31-
screen fades out. A splash screen is useful to avoid any visual
32-
gap between the end of Android's launch screen and the painting of
33-
Flutter's first frame. -->
34-
<meta-data
35-
android:name="io.flutter.embedding.android.SplashScreenDrawable"
36-
android:resource="@drawable/launch_background"
37-
/>
3830
<intent-filter>
3931
<action android:name="android.intent.action.MAIN"/>
4032
<category android:name="android.intent.category.LAUNCHER"/>

lib/api/API.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import 'package:flutter_local_notifications/flutter_local_notifications.dart';
44
import 'package:piwigo_ng/services/upload/Uploader.dart';
55
import 'package:shared_preferences/shared_preferences.dart';
66
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
7+
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
78

89
class API {
910
static final API _singleton = API._internal();
@@ -12,6 +13,7 @@ class API {
1213
static CookieJar cookieJar = CookieJar();
1314
static Uploader uploader;
1415
static SharedPreferences prefs;
16+
static final storage = FlutterSecureStorage();
1517
static FlutterLocalNotificationsPlugin localNotification;
1618

1719
factory API() {

lib/api/CategoryAPI.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,10 @@ Future<Map<String,dynamic>> fetchAlbums(String albumID) async {
2424
};
2525
}
2626
} catch(e) {
27-
//var error = e as DioError;
27+
var error = e as DioError;
2828
return {
2929
'stat': 'fail',
30-
'result': e.toString(),
30+
'result': error.message,
3131
};
3232
}
3333
}

lib/api/ImageAPI.dart

Lines changed: 63 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import 'dart:io';
33

44
import 'package:dio/dio.dart';
55
import 'package:ext_storage/ext_storage.dart';
6-
import 'package:flutter/cupertino.dart';
76
import 'package:flutter/material.dart';
87
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
98
import 'package:path_provider/path_provider.dart';
@@ -76,7 +75,6 @@ Future<dynamic> getImageInfo(int imageId) async {
7675

7776
Future<bool> _requestPermissions() async {
7877
var permission = await Permission.storage.status;
79-
print(permission.isGranted);
8078
if (permission != PermissionStatus.granted) {
8179
await Permission.storage.request();
8280
permission = await Permission.storage.status;
@@ -176,7 +174,6 @@ Future<int> deleteImages(BuildContext context, List<int> imageIdList) async {
176174
for(int id in imageIdList) {
177175
var response = await deleteImage(id);
178176
if(response['stat'] == 'fail') {
179-
print(response);
180177
ScaffoldMessenger.of(context).hideCurrentSnackBar();
181178
ScaffoldMessenger.of(context).showSnackBar(
182179
errorSnackBar(context, '${response['result']}'),
@@ -225,7 +222,6 @@ Future<int> removeImages(BuildContext context, List<int> imageIdList, String cat
225222
for(int id in imageIdList) {
226223
var response = await removeImage(id, catId);
227224
if(response['stat'] == 'fail') {
228-
print(response);
229225
ScaffoldMessenger.of(context).hideCurrentSnackBar();
230226
ScaffoldMessenger.of(context).showSnackBar(
231227
errorSnackBar(context, '${response['result']}'),
@@ -266,8 +262,6 @@ Future<dynamic> removeImage(int imageId, String catId) async {
266262
queryParameters: queries
267263
);
268264

269-
print(response.data);
270-
271265
if (response.statusCode == 200) {
272266
return json.decode(response.data);
273267
} else {
@@ -464,6 +458,69 @@ Future<dynamic> renameImage(int imageId, String name) async {
464458
queryParameters: queries
465459
);
466460

461+
if (response.statusCode == 200) {
462+
return json.decode(response.data);
463+
} else {
464+
return {
465+
'stat': 'fail',
466+
'result': response.statusMessage
467+
};
468+
}
469+
} catch (e) {
470+
var error = e as DioError;
471+
return {
472+
'stat': 'fail',
473+
'result': error.message
474+
};
475+
}
476+
}
477+
478+
Future<dynamic> uploadCompleted(List<int> imageId, int categoryId) async {
479+
Map<String, String> queries = {
480+
"format": "json",
481+
"method": "pwg.images.uploadCompleted",
482+
};
483+
FormData formData = FormData.fromMap({
484+
"image_id": imageId,
485+
"pwg_token": API.prefs.getString("pwg_token"),
486+
"category_id": categoryId,
487+
});
488+
try {
489+
Response response = await API().dio.post('ws.php',
490+
data: formData,
491+
queryParameters: queries
492+
);
493+
if (response.statusCode == 200) {
494+
return json.decode(response.data);
495+
} else {
496+
return {
497+
'stat': 'fail',
498+
'result': response.statusMessage
499+
};
500+
}
501+
} catch (e) {
502+
var error = e as DioError;
503+
return {
504+
'stat': 'fail',
505+
'result': error.message
506+
};
507+
}
508+
}
509+
Future<dynamic> communityUploadCompleted(List<int> imageId, int categoryId) async {
510+
Map<String, String> queries = {
511+
"format": "json",
512+
"method": "community.images.uploadCompleted",
513+
};
514+
FormData formData = FormData.fromMap({
515+
"image_id": imageId,
516+
"pwg_token": API.prefs.getString("pwg_token"),
517+
"category_id": categoryId,
518+
});
519+
try {
520+
Response response = await API().dio.post('ws.php',
521+
data: formData,
522+
queryParameters: queries
523+
);
467524
if (response.statusCode == 200) {
468525
return json.decode(response.data);
469526
} else {

lib/api/SessionAPI.dart

Lines changed: 38 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,7 @@ Future<String> loginUser(String url, String username, String password) async {
2727
if(response.statusCode == 200) {
2828
if(json.decode(response.data)['stat'] == 'ok') {
2929
var status = await sessionStatus();
30-
print(status);
3130
if(status["stat"] == "ok") {
32-
print("$url, $username");
3331
savePreferences(status["result"], url: url, username: username, password: password, isLogged: true, isGuest: false);
3432
return null;
3533
}
@@ -38,22 +36,26 @@ Future<String> loginUser(String url, String username, String password) async {
3836
return 'Invalid username / password';
3937
}
4038

41-
} catch(e) {
42-
return 'Dio: Invalid url';
39+
} on DioError catch(e) {
40+
return e.message;
4341
}
4442
return 'Something happened';
4543
}
4644
Future<String> loginGuest(String url) async {
4745

4846
API().dio.options.baseUrl = url;
4947

50-
var status = await sessionStatus();
48+
try {
49+
var status = await sessionStatus();
5150

52-
if(status["stat"] == "ok") {
53-
savePreferences(status["result"], url: url, username: "", password: "", isLogged: true, isGuest: true);
54-
return null;
51+
if(status["stat"] == "ok") {
52+
savePreferences(status["result"], url: url, username: "", password: "", isLogged: true, isGuest: true);
53+
return null;
54+
}
55+
return status["message"];
56+
} on DioError catch(e) {
57+
return e.message;
5558
}
56-
return 'Invalid url';
5759
}
5860

5961
Future<Map<String, dynamic>> sessionStatus() async {
@@ -65,14 +67,15 @@ Future<Map<String, dynamic>> sessionStatus() async {
6567
try {
6668
Response response = await API().dio.get('ws.php', queryParameters: queries);
6769
return json.decode(response.data);
68-
} catch (e) {
70+
} on DioError catch (e) {
6971
print('Dio error $e');
70-
return {"stat": "KO"};
72+
return {"stat": "KO",
73+
"message": e.message,
74+
};
7175
}
7276
}
7377

7478
void saveStatus(Map<String, dynamic> status) async {
75-
print(status);
7679
API.prefs.setString("account_username", status["username"]);
7780
API.prefs.setString('pwg_token', status['pwg_token']);
7881
API.prefs.setString("status", status["status"]);
@@ -94,9 +97,8 @@ void savePreferences(Map<String, dynamic> status, {
9497
bool isLogged,
9598
bool isGuest
9699
}) async {
97-
API.prefs.setString('username', url);
98-
API.prefs.setString('username', username);
99-
API.prefs.setString('password', password);
100+
API.storage.write(key: 'username', value: username);
101+
API.storage.write(key: 'password', value: password);
100102
API.prefs.setBool("is_logged", isLogged);
101103
API.prefs.setBool("is_guest", isGuest);
102104
API.prefs.setString("user_status", status["status"]);
@@ -110,4 +112,25 @@ void savePreferences(Map<String, dynamic> status, {
110112
if(API.prefs.getDouble("landscape_image_count") == null) API.prefs.setDouble("landscape_image_count", 6);
111113
if(API.prefs.getBool("show_thumbnail_title") == null) API.prefs.setBool("show_thumbnail_title", false);
112114
saveStatus(status);
115+
}
116+
117+
Future<Map<String, dynamic>> getMethods() async {
118+
Map<String, String> queries = {
119+
'format': 'json',
120+
'method': 'reflection.getMethodList'
121+
};
122+
123+
try {
124+
Response response = await API().dio.get('ws.php', queryParameters: queries);
125+
return json.decode(response.data);
126+
} catch (e) {
127+
print('Dio error $e');
128+
return {"stat": "KO"};
129+
}
130+
}
131+
132+
Future<bool> methodExist(String method) async {
133+
var result = await getMethods();
134+
135+
return result["result"]["methods"].contains(method);
113136
}

lib/constants/SettingsConstants.dart

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,16 @@ class Constants {
3131
8: 'Admins',
3232
};
3333

34-
static double CONFIRM_DIALOG_MAX_WIDTH = 500.0;
34+
static double confirmDialogMaxWidth = 500.0;
3535

36-
static double ALBUM_MIN_WIDTH = 400.0;
36+
static double albumMinWidth = 400.0;
3737

38-
static double PORTRAIT_IMAGE_COUNT_MIN = 1.0;
39-
static double PORTRAIT_IMAGE_COUNT_MAX = 6.0;
40-
static double LANDSCAPE_IMAGE_COUNT_MIN = 4.0;
41-
static double LANDSCAPE_IMAGE_COUNT_MAX = 10.0;
38+
static double portraitImageCountMin = 1.0;
39+
static double portraitImageCountMax = 6.0;
40+
static double landscapeImageCountMin = 4.0;
41+
static double landscapeImageCountMax = 10.0;
42+
43+
static String privacyPoliciesUrl = "https://piwigo.org/mobile-apps-privacy-policy&webview";
4244
}
4345

4446
AppLocalizations appStrings(context) {

0 commit comments

Comments
 (0)