relatica/lib/services/gallery_service.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();
}
}