Skip to content

Commit b3d3de4

Browse files
authored
Merge pull request #1 from Piwigo/master
updating
2 parents 5917049 + fe7c975 commit b3d3de4

53 files changed

Lines changed: 7934 additions & 3686 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@
77
/.flutter-plugins-dependencies
88
/.packages
99

10+
*.env

README.md

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,26 @@ If you face trouble please [create tickets](https://github.com/Piwigo/piwigo-flu
1010

1111
# Installation
1212

13-
For now, this application is in Beta. In order to try it, you will need to install the APK:
13+
For now, this application is in Beta. You can download the latest version either from Github or from Google Play Store:
1414

15-
## Download the APK
15+
## Download from Play Store
16+
17+
On your Android phone:
18+
1. Go to **Play Store**.
19+
2. Search for **Piwigo NG** on search-bar.
20+
3. Find the listing with the name **Piwigo NG (Early Access)** and click **Install**.
21+
22+
Alternatively, you can directly go to the [Play Store page of Piwigo NG app](https://play.google.com/store/apps/details?id=com.piwigo.piwigo_ng).
23+
24+
## Download from Github
25+
26+
### Download the APK
1627

1728
In Github, Go to [piwigo-flutter-app releases](https://github.com/Piwigo/piwigo-flutter-app/releases), choose the version (latest is recommanded) and download the .apk file.
1829

19-
## Install the APK
30+
### Install the APK
2031

21-
In your Android phone:
32+
On your Android phone:
2233
1. Go to **Settings** > **security** > **install unknown apps**.
2334
2. Go to **files** and enable **Allow from this source**.
2435
*Don't forget to disable it when you have finished*

android/app/src/main/AndroidManifest.xml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,4 +46,17 @@
4646
android:name="flutterEmbedding"
4747
android:value="2" />
4848
</application>
49+
50+
<queries>
51+
<!-- If your app opens https URLs -->
52+
<intent>
53+
<action android:name="android.intent.action.VIEW" />
54+
<data android:scheme="https" />
55+
</intent>
56+
<!-- If your app makes calls -->
57+
<intent>
58+
<action android:name="android.intent.action.DIAL" />
59+
<data android:scheme="tel" />
60+
</intent>
61+
</queries>
4962
</manifest>

crowdin.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
files:
2+
- source: /lib/l10n/app_en.arb
3+
translation: /lib/l10n/app_%two_letters_code%.arb

l10n.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
arb-dir: lib/l10n
2+
template-arb-file: app_en.arb
3+
output-localization-file: app_localizations.dart

lib/api/API.dart

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import 'package:cookie_jar/cookie_jar.dart';
22
import 'package:dio/dio.dart';
33
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
4-
import 'package:piwigo_ng/views/UploadGalleryViewPage.dart';
4+
import 'package:piwigo_ng/services/upload/Uploader.dart';
55
import 'package:shared_preferences/shared_preferences.dart';
6+
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
67

78
class API {
89
static final API _singleton = API._internal();
@@ -17,5 +18,9 @@ class API {
1718
return _singleton;
1819
}
1920

21+
AppLocalizations strings(context) {
22+
return AppLocalizations.of(context);
23+
}
24+
2025
API._internal();
2126
}

lib/api/CategoryAPI.dart

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ Future<Map<String,dynamic>> fetchAlbums(String albumID) async {
88
Map<String, String> queries = {
99
"format": "json",
1010
"method": "pwg.categories.getList",
11-
"cat_id": albumID
11+
"cat_id": albumID,
12+
"thumbnail_size": API.prefs.getString('thumbnail_size'),
1213
};
1314

1415
try {
@@ -23,10 +24,10 @@ Future<Map<String,dynamic>> fetchAlbums(String albumID) async {
2324
};
2425
}
2526
} catch(e) {
26-
var error = e as DioError;
27+
//var error = e as DioError;
2728
return {
2829
'stat': 'fail',
29-
'result': error.message
30+
'result': e.toString(),
3031
};
3132
}
3233
}
@@ -83,14 +84,15 @@ Future<dynamic> addCategory(String catName, String catDesc, String parent) async
8384
};
8485
}
8586
}
86-
Future<dynamic> deleteCategory(String catId) async {
87+
Future<dynamic> deleteCategory(String catId, {String deletionMode = "delete_orphans"}) async {
8788
Map<String, String> queries = {
8889
"format": "json",
8990
"method": "pwg.categories.delete",
9091
};
9192
FormData formData = FormData.fromMap({
9293
"category_id": catId,
9394
"pwg_token": API.prefs.getString("pwg_token"),
95+
'photo_deletion_mode': deletionMode,
9496
});
9597
try {
9698
Response response = await API.dio.post('ws.php',

lib/api/ImageAPI.dart

Lines changed: 151 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import 'package:flutter_local_notifications/flutter_local_notifications.dart';
99
import 'package:path_provider/path_provider.dart';
1010
import 'package:permission_handler/permission_handler.dart';
1111
import 'package:path/path.dart' as path;
12-
import 'package:piwigo_ng/views/components/SnackBars.dart';
12+
import 'package:piwigo_ng/views/components/snackbars.dart';
1313

1414
import 'API.dart';
1515

@@ -42,6 +42,38 @@ Future<Map<String,dynamic>> fetchImages(String albumID, int page) async {
4242
}
4343
}
4444

45+
Future<dynamic> getImageInfo(int imageId) async {
46+
Map<String, String> queries = {
47+
"format": "json",
48+
"method": "pwg.images.getInfo",
49+
};
50+
FormData formData = FormData.fromMap({
51+
"image_id": imageId
52+
});
53+
try {
54+
Response response = await API.dio.post('ws.php',
55+
data: formData,
56+
queryParameters: queries
57+
);
58+
59+
if (response.statusCode == 200) {
60+
return json.decode(response.data);
61+
} else {
62+
return {
63+
'stat': 'fail',
64+
'result': response.statusMessage
65+
};
66+
}
67+
} catch (e) {
68+
var error = e as DioError;
69+
return {
70+
'stat': 'fail',
71+
'result': error.message
72+
};
73+
}
74+
}
75+
76+
4577
Future<bool> _requestPermissions() async {
4678
var permission = await Permission.storage.status;
4779
print(permission.isGranted);
@@ -145,9 +177,11 @@ Future<int> deleteImages(BuildContext context, List<int> imageIdList) async {
145177
var response = await deleteImage(id);
146178
if(response['stat'] == 'fail') {
147179
print(response);
180+
ScaffoldMessenger.of(context).hideCurrentSnackBar();
148181
ScaffoldMessenger.of(context).showSnackBar(
149182
errorSnackBar(context, '${response['result']}'),
150183
);
184+
break;
151185
} else {
152186
nbSuccess++;
153187
}
@@ -186,14 +220,81 @@ Future<dynamic> deleteImage(int imageId) async {
186220
}
187221
}
188222

223+
Future<int> removeImages(BuildContext context, List<int> imageIdList, String catId) async {
224+
int nbSuccess = 0;
225+
for(int id in imageIdList) {
226+
var response = await removeImage(id, catId);
227+
if(response['stat'] == 'fail') {
228+
print(response);
229+
ScaffoldMessenger.of(context).hideCurrentSnackBar();
230+
ScaffoldMessenger.of(context).showSnackBar(
231+
errorSnackBar(context, '${response['result']}'),
232+
);
233+
break;
234+
} else {
235+
nbSuccess++;
236+
}
237+
}
238+
return nbSuccess;
239+
}
240+
Future<dynamic> removeImage(int imageId, String catId) async {
241+
var imageInfo = await getImageInfo(imageId);
242+
if(imageInfo['stat'] == 'fail') return imageInfo;
243+
244+
List<String> categories = imageInfo['result']['categories'].map<String>(
245+
(cat) => cat['id'].toString()
246+
).toList();
247+
categories.removeWhere((cat) => cat == catId);
248+
249+
if(categories.isEmpty) {
250+
return await deleteImage(imageId);
251+
}
252+
253+
Map<String, String> queries = {
254+
"format": "json",
255+
"method": "pwg.images.setInfo",
256+
};
257+
FormData formData = FormData.fromMap({
258+
"image_id": imageId,
259+
"categories": categories,
260+
"multiple_value_mode": "replace"
261+
});
262+
263+
try {
264+
Response response = await API.dio.post('ws.php',
265+
data: formData,
266+
queryParameters: queries
267+
);
268+
269+
print(response.data);
270+
271+
if (response.statusCode == 200) {
272+
return json.decode(response.data);
273+
} else {
274+
return {
275+
'stat': 'fail',
276+
'result': response.statusMessage
277+
};
278+
}
279+
} catch (e) {
280+
var error = e as DioError;
281+
return {
282+
'stat': 'fail',
283+
'result': error.message
284+
};
285+
}
286+
}
287+
189288
Future<int> moveImages(BuildContext context, List<dynamic> images, int category) async {
190289
int nbMoved = 0;
191290
for(var image in images) {
192291
var response = await moveImage(image['id'], [category]);
193292
if(response['stat'] == 'fail') {
293+
ScaffoldMessenger.of(context).hideCurrentSnackBar();
194294
ScaffoldMessenger.of(context).showSnackBar(
195295
errorSnackBar(context, '${response['result']}')
196296
);
297+
break;
197298
} else {
198299
nbMoved++;
199300
}
@@ -245,9 +346,11 @@ Future<int> assignImages(BuildContext context, List<dynamic> images, int categor
245346
categories.add(category);
246347
var response = await assignImage(image['id'], categories);
247348
if(response['stat'] == 'fail') {
349+
ScaffoldMessenger.of(context).hideCurrentSnackBar();
248350
ScaffoldMessenger.of(context).showSnackBar(
249351
errorSnackBar(context, '${response['result']}')
250352
);
353+
break;
251354
} else {
252355
nbAssigned++;
253356
}
@@ -294,11 +397,7 @@ Future<int> editImages(BuildContext context, List<Map<String, dynamic>> images,
294397
int nbEdited = 0;
295398
for(var image in images) {
296399
var response = await editImage(image['id'], image['name'], image['desc'], tags, level);
297-
if(response['stat'] == 'fail') {
298-
ScaffoldMessenger.of(context).showSnackBar(
299-
errorSnackBar(context, '${response['result']}')
300-
);
301-
} else {
400+
if(response['stat'] != 'fail') {
302401
nbEdited++;
303402
}
304403
}
@@ -309,15 +408,55 @@ Future<dynamic> editImage(int imageId, String name, String desc, List<int> tags,
309408
"format": "json",
310409
"method": "pwg.images.setInfo",
311410
};
312-
FormData formData = FormData.fromMap({
411+
412+
Map<String,dynamic> form = {
313413
"image_id": imageId,
314-
"name": name,
315-
"comment": desc,
316-
"tag_ids": tags,
317-
"level": level,
318414
"single_value_mode": "replace",
319415
"multiple_value_mode": "append"
320-
});
416+
};
417+
if(name != "" && name != null) form["name"] = name;
418+
if(desc != "" && desc != null) form["comment"] = desc;
419+
if(tags.isNotEmpty) form["tag_ids"] = tags;
420+
if(level != -1) form["level"] = level;
421+
422+
FormData formData = FormData.fromMap(form);
423+
424+
try {
425+
Response response = await API.dio.post('ws.php',
426+
data: formData,
427+
queryParameters: queries
428+
);
429+
430+
if (response.statusCode == 200) {
431+
return json.decode(response.data);
432+
} else {
433+
return {
434+
'stat': 'fail',
435+
'result': response.statusMessage
436+
};
437+
}
438+
} catch (e) {
439+
var error = e as DioError;
440+
return {
441+
'stat': 'fail',
442+
'result': error.message
443+
};
444+
}
445+
}
446+
447+
Future<dynamic> renameImage(int imageId, String name) async {
448+
Map<String, String> queries = {
449+
"format": "json",
450+
"method": "pwg.images.setInfo",
451+
};
452+
453+
Map<String,dynamic> form = {
454+
"image_id": imageId,
455+
"name": name,
456+
"single_value_mode": "replace"
457+
};
458+
459+
FormData formData = FormData.fromMap(form);
321460

322461
try {
323462
Response response = await API.dio.post('ws.php',

lib/api/SessionAPI.dart

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ Future<String> loginUser(String url, String username, String password) async {
2929
var status = await sessionStatus();
3030
print(status);
3131
if(status["stat"] == "ok") {
32+
print("$url, $username");
3233
savePreferences(status["result"], url: url, username: username, password: password, isLogged: true, isGuest: false);
3334
return null;
3435
}
@@ -77,13 +78,13 @@ void saveStatus(Map<String, dynamic> status) async {
7778
API.prefs.setString("status", status["status"]);
7879
API.prefs.setString("version", status["version"]);
7980
API.prefs.setStringList("available_sizes", status["available_sizes"].cast<String>());
80-
if(API.prefs.getBool("is_logged") && !API.prefs.getBool("is_guest")) {
81+
if(API.prefs.getString("user_status") == "admin" || API.prefs.getString("user_status") == "webmaster") {
8182
API.prefs.setInt('upload_form_chunk_size', status['upload_form_chunk_size']);
8283
API.prefs.setString("file_types", status["upload_file_types"]);
8384
}
84-
if(API.prefs.getString('miniature_size') == null) {
85-
API.prefs.setString('miniature_size', 'medium');
86-
}
85+
if(API.prefs.getString('thumbnail_size') == null) API.prefs.setString('thumbnail_size', 'medium');
86+
if(API.prefs.getString('full_screen_image_size') == null) API.prefs.setString('full_screen_image_size', 'medium');
87+
if(API.prefs.getString('album_thumbnail_size') == null) API.prefs.setString('album_thumbnail_size', 'medium');
8788
}
8889

8990
void savePreferences(Map<String, dynamic> status, {
@@ -98,14 +99,15 @@ void savePreferences(Map<String, dynamic> status, {
9899
API.prefs.setString('password', password);
99100
API.prefs.setBool("is_logged", isLogged);
100101
API.prefs.setBool("is_guest", isGuest);
102+
API.prefs.setString("user_status", status["status"]);
101103
API.prefs.setString("base_url", url);
102104

103105
API.prefs.setString("default_album", "Root Album");
104-
if(API.prefs.getInt("default_miniatures_size") == null) API.prefs.setInt("default_miniatures_size", 0);
106+
if(API.prefs.getInt("default_thumbnails_size") == null) API.prefs.setInt("default_thumbnails_size", 0);
105107
if(API.prefs.getInt("sort") == null) API.prefs.setInt("sort", 0);
106108
if(API.prefs.getInt("recent_albums") == null) API.prefs.setInt("recent_albums", 5);
107109
if(API.prefs.getDouble("portrait_image_count") == null) API.prefs.setDouble("portrait_image_count", 4);
108110
if(API.prefs.getDouble("landscape_image_count") == null) API.prefs.setDouble("landscape_image_count", 6);
109-
if(API.prefs.getBool("show_miniature_title") == null) API.prefs.setBool("show_miniature_title", false);
111+
if(API.prefs.getBool("show_thumbnail_title") == null) API.prefs.setBool("show_thumbnail_title", false);
110112
saveStatus(status);
111113
}

0 commit comments

Comments
 (0)