Skip to content

Commit 81e200a

Browse files
committed
added sort methods and added a parse json method to remove html returned by the API on error
1 parent c3c31f6 commit 81e200a

6 files changed

Lines changed: 195 additions & 29 deletions

File tree

lib/api/albums.dart

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,18 @@ import 'package:piwigo_ng/services/preferences_service.dart';
99
import 'api_client.dart';
1010
import 'authentication.dart';
1111

12+
Map<String, dynamic> tryParseJson(String data) {
13+
try {
14+
return json.decode(data);
15+
} on FormatException catch (e) {
16+
debugPrint('Invalid json data');
17+
int start = data.indexOf('{');
18+
int end = data.lastIndexOf('}');
19+
String parsedData = data.substring(start, end + 1);
20+
return json.decode(parsedData);
21+
}
22+
}
23+
1224
Future<ApiResult<List<AlbumModel>>> fetchAlbums(int albumID) async {
1325
final Map<String, dynamic> queries = {
1426
'format': 'json',
@@ -35,8 +47,11 @@ Future<ApiResult<List<AlbumModel>>> fetchAlbums(int albumID) async {
3547
queryParameters: queries,
3648
);
3749

50+
debugPrint('hello');
51+
debugPrint(response.data.toString());
52+
3853
if (response.statusCode == 200) {
39-
List<dynamic> jsonAlbums = json.decode(response.data)['result']['categories'];
54+
List<dynamic> jsonAlbums = tryParseJson(response.data)['result']['categories'];
4055
List<AlbumModel> albums = List<AlbumModel>.from(jsonAlbums.map(
4156
(album) {
4257
bool canUpload = false;

lib/api/images.dart

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import 'package:piwigo_ng/models/image_model.dart';
1414
import 'package:piwigo_ng/services/notification_service.dart';
1515
import 'package:piwigo_ng/services/preferences_service.dart';
1616
import 'package:piwigo_ng/utils/localizations.dart';
17+
import 'package:piwigo_ng/utils/settings.dart';
1718
import 'package:share_plus/share_plus.dart';
1819

1920
import 'albums.dart';
@@ -48,11 +49,12 @@ Future<ApiResult<ImageModel>> getImage(int imageId) async {
4849

4950
Future<ApiResult<List<ImageModel>>> fetchImages(int albumID, int page) async {
5051
Map<String, dynamic> queries = {
51-
"format": "json",
52-
"method": "pwg.categories.getImages",
53-
"cat_id": albumID,
54-
"per_page": "100",
55-
"page": page.toString(),
52+
'format': 'json',
53+
'method': 'pwg.categories.getImages',
54+
'cat_id': albumID,
55+
'order': Preferences.getImageSort.value,
56+
'per_page': Settings.defaultElementPerPage,
57+
'page': page,
5658
};
5759

5860
try {

lib/services/preferences_service.dart

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,15 @@ class Preferences {
5858
return appPreferences.getString(imageThumbnailSizeKey) ?? Settings.defaultImageThumbnailSize;
5959
}
6060

61+
static const String imageSortKey = 'IMAGE_SORT';
62+
static SortMethods get getImageSort {
63+
String? sortValue = appPreferences.getString(imageSortKey);
64+
if (sortValue == null) {
65+
return Settings.defaultImageSort;
66+
}
67+
return Settings.sortFromValue(sortValue);
68+
}
69+
6170
static const String albumThumbnailSizeKey = 'ALBUM_THUMBNAIL_SIZE';
6271
static String get getAlbumThumbnailSize {
6372
return appPreferences.getString(albumThumbnailSizeKey) ?? Settings.defaultAlbumThumbnailSize;

lib/utils/settings.dart

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,92 @@
11
import 'package:flutter/material.dart';
22
import 'package:piwigo_ng/services/preferences_service.dart';
3+
import 'package:piwigo_ng/utils/localizations.dart';
4+
5+
enum SortMethods {
6+
nameAsc,
7+
nameDesc,
8+
fileAsc,
9+
fileDesc,
10+
dateCreatedAsc,
11+
dateCreatedDesc,
12+
dateAvailableAsc,
13+
dateAvailableDesc,
14+
rateAsc,
15+
rateDesc,
16+
hitAsc,
17+
hitDesc,
18+
random,
19+
}
20+
21+
extension SortMethodsExtension on SortMethods {
22+
String get label {
23+
switch (this) {
24+
case SortMethods.nameAsc:
25+
return appStrings.categorySort_nameAscending;
26+
case SortMethods.nameDesc:
27+
return appStrings.categorySort_nameDescending;
28+
case SortMethods.fileAsc:
29+
return appStrings.categorySort_fileNameAscending;
30+
case SortMethods.fileDesc:
31+
return appStrings.categorySort_fileNameDescending;
32+
case SortMethods.dateCreatedAsc:
33+
return appStrings.categorySort_dateCreatedAscending;
34+
case SortMethods.dateCreatedDesc:
35+
return appStrings.categorySort_dateCreatedDescending;
36+
case SortMethods.dateAvailableAsc:
37+
return appStrings.categorySort_datePostedAscending;
38+
case SortMethods.dateAvailableDesc:
39+
return appStrings.categorySort_datePostedDescending;
40+
case SortMethods.rateAsc:
41+
return appStrings.categorySort_ratingScoreAscending;
42+
case SortMethods.rateDesc:
43+
return appStrings.categorySort_ratingScoreDescending;
44+
case SortMethods.hitAsc:
45+
return appStrings.categorySort_visitsAscending;
46+
case SortMethods.hitDesc:
47+
return appStrings.categorySort_visitsDescending;
48+
case SortMethods.random:
49+
return appStrings.categorySort_random;
50+
}
51+
}
52+
53+
String get value {
54+
switch (this) {
55+
case SortMethods.nameAsc:
56+
return 'name ASC';
57+
case SortMethods.nameDesc:
58+
return 'name DESC';
59+
case SortMethods.fileAsc:
60+
return 'file ASC';
61+
case SortMethods.fileDesc:
62+
return 'file DESC';
63+
case SortMethods.dateCreatedAsc:
64+
return 'date_creation ASC';
65+
case SortMethods.dateCreatedDesc:
66+
return 'date_creation DESC';
67+
case SortMethods.dateAvailableAsc:
68+
return 'date_available ASC';
69+
case SortMethods.dateAvailableDesc:
70+
return 'date_available DESC';
71+
case SortMethods.rateAsc:
72+
return 'rating_score ASC';
73+
case SortMethods.rateDesc:
74+
return 'rating_score DESC';
75+
case SortMethods.hitAsc:
76+
return 'hit ASC';
77+
case SortMethods.hitDesc:
78+
return 'hit DESC';
79+
case SortMethods.random:
80+
return 'random';
81+
}
82+
}
83+
}
384

485
class Settings {
586
static const String defaultAlbumThumbnailSize = 'medium';
687
static const String defaultImageThumbnailSize = 'medium';
788
static const String defaultImageFullScreenSize = 'medium';
89+
static const SortMethods defaultImageSort = SortMethods.nameAsc;
890
static const bool defaultRemoveMetadata = false;
991
static const bool defaultCompress = false;
1092
static const bool defaultDeleteAfterUpload = false;
@@ -13,6 +95,7 @@ class Settings {
1395
static const int defaultImageRowCount = 4;
1496
static const int minImageRowCount = 1; // Settings slider min range
1597
static const int maxImageRowCount = 6; // Settings slider max range
98+
static const int defaultElementPerPage = 100; // API requests
1699
static const double defaultAlbumGridSize = 448.0;
17100
static const double defaultUploadQuality = 1.0;
18101

@@ -56,4 +139,35 @@ class Settings {
56139
return '';
57140
}
58141
}
142+
143+
static SortMethods sortFromValue(value) {
144+
switch (value) {
145+
case 'name ASC':
146+
return SortMethods.nameAsc;
147+
case 'name DESC':
148+
return SortMethods.nameDesc;
149+
case 'file ASC':
150+
return SortMethods.fileAsc;
151+
case 'file DESC':
152+
return SortMethods.fileDesc;
153+
case 'date_creation ASC':
154+
return SortMethods.dateCreatedAsc;
155+
case 'date_creation DESC':
156+
return SortMethods.dateCreatedDesc;
157+
case 'date_available ASC':
158+
return SortMethods.dateAvailableAsc;
159+
case 'date_available DESC':
160+
return SortMethods.dateAvailableDesc;
161+
case 'rating_score ASC':
162+
return SortMethods.rateAsc;
163+
case 'rating_score DESC':
164+
return SortMethods.rateDesc;
165+
case 'hit ASC':
166+
return SortMethods.hitAsc;
167+
case 'hit DESC':
168+
return SortMethods.hitDesc;
169+
default:
170+
return SortMethods.random;
171+
}
172+
}
59173
}

lib/views/album/album_view_page.dart

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ class _AlbumViewPageState extends State<AlbumViewPage> {
185185
child: Padding(
186186
padding: const EdgeInsets.all(8),
187187
child: Text(
188-
appStrings.imageCount(_currentAlbum.nbImages),
188+
appStrings.imageCount(_currentAlbum.nbTotalImages),
189189
style: Theme.of(context).textTheme.titleSmall,
190190
),
191191
),
@@ -392,9 +392,10 @@ class _AlbumViewPageState extends State<AlbumViewPage> {
392392
Widget _albumGrid(AsyncSnapshot snapshot) {
393393
if (_albumList.isEmpty) {
394394
final ApiResult<List<AlbumModel>> result = snapshot.data!.first as ApiResult<List<AlbumModel>>;
395+
List<AlbumModel> albums = _parseAlbums(result.data!);
396+
if (albums.isEmpty) return const SizedBox();
395397
_albumList = _parseAlbums(result.data!);
396398
}
397-
if (_albumList.isEmpty) return const SizedBox();
398399
return AlbumGridView(
399400
isAdmin: widget.isAdmin,
400401
albumList: _albumList,
@@ -410,17 +411,18 @@ class _AlbumViewPageState extends State<AlbumViewPage> {
410411
final ApiResult<List<ImageModel>> result = snapshot.data!.last as ApiResult<List<ImageModel>>;
411412
if (result.hasError || !result.hasData) {
412413
return Center(
413-
child: Text(appStrings.noImages),
414+
child: Text(appStrings.categoryImageList_noDataError),
414415
);
415416
}
416417
_imageList = result.data!;
417418
WidgetsBinding.instance.addPostFrameCallback((timeStamp) => setState(() {}));
418419
}
419-
if (_imageList.isEmpty) {
420-
return Center(
421-
child: Text(appStrings.noImages),
422-
);
423-
}
420+
// todo: useless display
421+
// if (_imageList.isEmpty) {
422+
// return Center(
423+
// child: Text(appStrings.noImages),
424+
// );
425+
// }
424426
_selectedList = _imageList.where((image) => _selectedList.contains(image)).toList();
425427
return ImageGridView(
426428
imageList: _imageList,

lib/views/settings/settings_view_page.dart

Lines changed: 39 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ class _SettingsViewPageState extends State<SettingsViewPage> {
4242
late String _imageThumbnailSize;
4343
late String _albumThumbnailSize;
4444
late String _imageFullScreenSize;
45+
late SortMethods _imageSort;
4546
late bool _stripMetadata;
4647
late String _author;
4748
late bool _compressBeforeUpload;
@@ -57,6 +58,7 @@ class _SettingsViewPageState extends State<SettingsViewPage> {
5758
_thumbnailTitle = Preferences.getShowThumbnailTitle;
5859
_imageThumbnailSize = Preferences.getImageThumbnailSize;
5960
_imageFullScreenSize = Preferences.getImageFullScreenSize;
61+
_imageSort = Preferences.getImageSort;
6062
_albumThumbnailSize = Preferences.getAlbumThumbnailSize;
6163
_availableSizes = Preferences.getAvailableSizes;
6264
_author = Preferences.getUploadAuthor ?? '';
@@ -263,12 +265,11 @@ class _SettingsViewPageState extends State<SettingsViewPage> {
263265
title: appStrings.defaultThumbnailFile320px,
264266
value: _imageThumbnailSize,
265267
onChanged: (size) {
266-
if (size != null) {
267-
setState(() {
268-
_imageThumbnailSize = size;
269-
appPreferences.setString(Preferences.imageThumbnailSizeKey, _imageThumbnailSize);
270-
});
271-
}
268+
if (size == null) return;
269+
setState(() {
270+
_imageThumbnailSize = size;
271+
appPreferences.setString(Preferences.imageThumbnailSizeKey, _imageThumbnailSize);
272+
});
272273
},
273274
selectedItemBuilder: (context) {
274275
return List.generate(_availableSizes.length, (index) {
@@ -291,15 +292,11 @@ class _SettingsViewPageState extends State<SettingsViewPage> {
291292
title: appStrings.defaultPreviewFile320px,
292293
value: _imageFullScreenSize,
293294
onChanged: (size) {
294-
if (size != null) {
295-
setState(() {
296-
_imageFullScreenSize = size;
297-
appPreferences.setString(
298-
Preferences.imageFullScreenSizeKey,
299-
_imageFullScreenSize,
300-
);
301-
});
302-
}
295+
if (size == null) return;
296+
setState(() {
297+
_imageFullScreenSize = size;
298+
appPreferences.setString(Preferences.imageFullScreenSizeKey, _imageFullScreenSize);
299+
});
303300
},
304301
selectedItemBuilder: (context) {
305302
return List.generate(_availableSizes.length, (index) {
@@ -318,6 +315,33 @@ class _SettingsViewPageState extends State<SettingsViewPage> {
318315
);
319316
}),
320317
),
318+
SettingsSectionDropdown<SortMethods>(
319+
title: appStrings.defaultImageSort,
320+
value: _imageSort,
321+
onChanged: (sort) {
322+
if (sort == null) return;
323+
setState(() {
324+
_imageSort = sort;
325+
appPreferences.setString(Preferences.imageSortKey, _imageSort.value);
326+
});
327+
},
328+
selectedItemBuilder: (context) {
329+
return List.generate(SortMethods.values.length, (index) {
330+
SortMethods method = SortMethods.values[index];
331+
return Center(child: Text("${method.label}"));
332+
});
333+
},
334+
items: List.generate(SortMethods.values.length, (index) {
335+
SortMethods method = SortMethods.values[index];
336+
return DropdownMenuItem<SortMethods>(
337+
value: method,
338+
child: Text(
339+
"${method.label}",
340+
style: Theme.of(context).textTheme.bodyMedium,
341+
),
342+
);
343+
}),
344+
),
321345
Builder(builder: (context) {
322346
final orientation = MediaQuery.of(context).orientation;
323347
final int nbImages = Settings.getImageCrossAxisCount(context, _imageRowNumber);

0 commit comments

Comments
 (0)