kopia lustrzana https://gitlab.com/mysocialportal/relatica
206 wiersze
6.0 KiB
Dart
206 wiersze
6.0 KiB
Dart
import 'package:flutter/foundation.dart';
|
|
import 'package:result_monad/result_monad.dart';
|
|
|
|
import '../friendica_client/friendica_client.dart';
|
|
import '../friendica_client/paging_data.dart';
|
|
import '../models/auth/profile.dart';
|
|
import '../models/exec_error.dart';
|
|
import '../models/gallery_data.dart';
|
|
import '../models/image_entry.dart';
|
|
|
|
class GalleryService extends ChangeNotifier {
|
|
static const IMAGES_PER_PAGE = 50;
|
|
final _galleries = <String, GalleryData>{};
|
|
final _galleryPages = <String, List<PagingData>>{};
|
|
final _images = <String, List<ImageEntry>>{};
|
|
var _loaded = false;
|
|
|
|
final Profile profile;
|
|
|
|
GalleryService(this.profile);
|
|
|
|
bool get loaded => _loaded;
|
|
|
|
void clear() {
|
|
_galleries.clear();
|
|
_galleryPages.clear();
|
|
_images.clear();
|
|
_loaded = false;
|
|
notifyListeners();
|
|
}
|
|
|
|
List<GalleryData> getGalleries() {
|
|
if (_galleries.isEmpty) {
|
|
updateGalleries();
|
|
}
|
|
|
|
return _galleries.values.toList(growable: false);
|
|
}
|
|
|
|
Result<GalleryData, ExecError> getGallery(String galleryName) {
|
|
final gallery = _galleries[galleryName];
|
|
|
|
if (gallery == null) {
|
|
return buildErrorResult(
|
|
type: ErrorType.notFound,
|
|
message: 'Gallery $galleryName not found',
|
|
);
|
|
}
|
|
|
|
return Result.ok(gallery);
|
|
}
|
|
|
|
FutureResult<List<GalleryData>, ExecError> updateGalleries() async {
|
|
final result = await GalleryClient(profile).getGalleryData();
|
|
if (result.isFailure) {
|
|
return result.errorCast();
|
|
}
|
|
|
|
final galleriesReturned = result.value.map((g) => g.name).toList();
|
|
_galleries.clear();
|
|
_galleryPages.removeWhere((key, value) => !galleriesReturned.contains(key));
|
|
_images.removeWhere((key, value) => !galleriesReturned.contains(key));
|
|
|
|
for (final gallery in result.value) {
|
|
_galleries[gallery.name] = gallery;
|
|
}
|
|
|
|
_loaded = true;
|
|
notifyListeners();
|
|
return Result.ok(_galleries.values.toList(growable: false));
|
|
}
|
|
|
|
Result<List<ImageEntry>, ExecError> getGalleryImageList(String galleryName) {
|
|
if (!_galleries.containsKey(galleryName)) {
|
|
return Result.error(
|
|
ExecError(
|
|
type: ErrorType.localError,
|
|
message: 'Unknown Gallery: $galleryName',
|
|
),
|
|
);
|
|
}
|
|
|
|
if (!_images.containsKey(galleryName)) {
|
|
updateGalleryImageList(galleryName: galleryName, withNextPage: true);
|
|
return Result.ok([]);
|
|
} else {
|
|
return Result.ok(_images[galleryName]!.toList(growable: false));
|
|
}
|
|
}
|
|
|
|
FutureResult<GalleryData, ExecError> renameGallery(
|
|
GalleryData gallery, String newName) async {
|
|
if (!_galleries.containsKey(gallery.name)) {
|
|
return buildErrorResult(
|
|
type: ErrorType.notFound,
|
|
message: 'Unknown gallery: ${gallery.name}');
|
|
}
|
|
final result = await GalleryClient(profile)
|
|
.renameGallery(gallery.name, newName)
|
|
.transform((_) => gallery.copy(name: newName))
|
|
.withResultAsync((_) async => await updateGalleries());
|
|
|
|
return result.execErrorCast();
|
|
}
|
|
|
|
//TODO Paging
|
|
FutureResult<List<ImageEntry>, ExecError> updateGalleryImageList(
|
|
{required String galleryName,
|
|
required bool withNextPage,
|
|
bool nextPageOnly = true}) async {
|
|
final pages = _galleryPages.putIfAbsent(galleryName, () => []);
|
|
if (pages.isEmpty) {
|
|
pages.add(PagingData(offset: 0, limit: IMAGES_PER_PAGE));
|
|
} else if (withNextPage) {
|
|
final offset = pages.last.offset! + IMAGES_PER_PAGE;
|
|
pages.add(PagingData(offset: offset, limit: IMAGES_PER_PAGE));
|
|
}
|
|
|
|
final imageSet = nextPageOnly
|
|
? _images.putIfAbsent(galleryName, () => []).toSet()
|
|
: <ImageEntry>{};
|
|
|
|
final pagesToUse = nextPageOnly ? [pages.last] : pages;
|
|
for (final page in pagesToUse) {
|
|
final result =
|
|
await GalleryClient(profile).getGalleryImages(galleryName, page);
|
|
if (result.isFailure) {
|
|
return result.errorCast();
|
|
}
|
|
|
|
imageSet.addAll(result.value);
|
|
}
|
|
|
|
_images[galleryName] = imageSet.toList();
|
|
notifyListeners();
|
|
return Result.ok(imageSet.toList(growable: false));
|
|
}
|
|
|
|
Result<ImageEntry, ExecError> getImage(String galleryName, String id) {
|
|
if (!_images.containsKey(galleryName)) {
|
|
return buildErrorResult(
|
|
type: ErrorType.notFound,
|
|
message: 'Image gallery $galleryName not known.',
|
|
);
|
|
}
|
|
|
|
final potentialImages =
|
|
_images[galleryName]?.where((i) => i.id == id).toList() ?? [];
|
|
|
|
if (potentialImages.isEmpty) {
|
|
return buildErrorResult(
|
|
type: ErrorType.notFound,
|
|
message: 'Image $id not found in gallery $galleryName',
|
|
);
|
|
}
|
|
|
|
return Result.ok(potentialImages.first);
|
|
}
|
|
|
|
FutureResult<ImageEntry, ExecError> updateImage(ImageEntry image) async {
|
|
final images = _images[image.album];
|
|
if (images == null) {
|
|
buildErrorResult(
|
|
type: ErrorType.notFound, message: 'Album not found ${image.album}');
|
|
}
|
|
|
|
final index = _images[image.album]!.indexOf(image);
|
|
if (index < 0) {
|
|
return buildErrorResult(
|
|
type: ErrorType.notFound,
|
|
message: 'Image ${image.id} does not exist for ${image.album}');
|
|
}
|
|
final result =
|
|
await ImageClient(profile).editImageData(image).withResult((_) {
|
|
images!.removeAt(index);
|
|
images.insert(index, image);
|
|
});
|
|
notifyListeners();
|
|
return result.execErrorCast();
|
|
}
|
|
|
|
FutureResult<ImageEntry, ExecError> deleteImage(ImageEntry image) async {
|
|
final images = _images[image.album];
|
|
if (images == null) {
|
|
buildErrorResult(
|
|
type: ErrorType.notFound, message: 'Album not found ${image.album}');
|
|
}
|
|
|
|
final index = _images[image.album]!.indexOf(image);
|
|
if (index < 0) {
|
|
return buildErrorResult(
|
|
type: ErrorType.notFound,
|
|
message: 'Image ${image.id} does not exist for ${image.album}');
|
|
}
|
|
final result = await ImageClient(profile)
|
|
.deleteImage(image)
|
|
.withResultAsync((_) async {
|
|
images!.removeAt(index);
|
|
await updateGalleries();
|
|
notifyListeners();
|
|
});
|
|
|
|
return result.execErrorCast();
|
|
}
|
|
}
|