kopia lustrzana https://gitlab.com/mysocialportal/relatica
Add preliminary gallery browser screen and gallery screen
rodzic
3da3762324
commit
aa8758c0c0
|
@ -10,6 +10,7 @@ enum NavBarButtons {
|
||||||
timelines,
|
timelines,
|
||||||
notifications,
|
notifications,
|
||||||
messages,
|
messages,
|
||||||
|
gallery,
|
||||||
contacts,
|
contacts,
|
||||||
profile,
|
profile,
|
||||||
}
|
}
|
||||||
|
@ -49,6 +50,9 @@ class AppBottomNavBar extends StatelessWidget {
|
||||||
case NavBarButtons.profile:
|
case NavBarButtons.profile:
|
||||||
context.pushNamed(ScreenPaths.profile);
|
context.pushNamed(ScreenPaths.profile);
|
||||||
break;
|
break;
|
||||||
|
case NavBarButtons.gallery:
|
||||||
|
context.pushNamed(ScreenPaths.gallery);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
type: BottomNavigationBarType.fixed,
|
type: BottomNavigationBarType.fixed,
|
||||||
|
@ -65,12 +69,14 @@ class AppBottomNavBar extends StatelessWidget {
|
||||||
return 0;
|
return 0;
|
||||||
case NavBarButtons.notifications:
|
case NavBarButtons.notifications:
|
||||||
return 1;
|
return 1;
|
||||||
case NavBarButtons.messages:
|
case NavBarButtons.gallery:
|
||||||
return 2;
|
return 2;
|
||||||
case NavBarButtons.contacts:
|
case NavBarButtons.messages:
|
||||||
return 3;
|
return 3;
|
||||||
case NavBarButtons.profile:
|
case NavBarButtons.contacts:
|
||||||
return 4;
|
return 4;
|
||||||
|
case NavBarButtons.profile:
|
||||||
|
return 5;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,14 +90,18 @@ class AppBottomNavBar extends StatelessWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (index == 2) {
|
if (index == 2) {
|
||||||
return NavBarButtons.messages;
|
return NavBarButtons.gallery;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (index == 3) {
|
if (index == 3) {
|
||||||
return NavBarButtons.contacts;
|
return NavBarButtons.messages;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (index == 4) {
|
if (index == 4) {
|
||||||
|
return NavBarButtons.contacts;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index == 5) {
|
||||||
return NavBarButtons.profile;
|
return NavBarButtons.profile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,6 +124,11 @@ class AppBottomNavBar extends StatelessWidget {
|
||||||
? Icons.notifications_active
|
? Icons.notifications_active
|
||||||
: Icons.notifications),
|
: Icons.notifications),
|
||||||
),
|
),
|
||||||
|
const BottomNavigationBarItem(
|
||||||
|
label: 'Gallery',
|
||||||
|
icon: Icon(Icons.photo_library_outlined),
|
||||||
|
activeIcon: Icon(Icons.photo_library),
|
||||||
|
),
|
||||||
const BottomNavigationBarItem(
|
const BottomNavigationBarItem(
|
||||||
label: 'Messages',
|
label: 'Messages',
|
||||||
icon: Icon(Icons.messenger_outline),
|
icon: Icon(Icons.messenger_outline),
|
||||||
|
|
|
@ -8,10 +8,14 @@ import 'models/TimelineIdentifiers.dart';
|
||||||
import 'models/connection.dart';
|
import 'models/connection.dart';
|
||||||
import 'models/credentials.dart';
|
import 'models/credentials.dart';
|
||||||
import 'models/exec_error.dart';
|
import 'models/exec_error.dart';
|
||||||
|
import 'models/gallery_data.dart';
|
||||||
import 'models/group_data.dart';
|
import 'models/group_data.dart';
|
||||||
|
import 'models/image_entry.dart';
|
||||||
import 'models/timeline_entry.dart';
|
import 'models/timeline_entry.dart';
|
||||||
import 'models/user_notification.dart';
|
import 'models/user_notification.dart';
|
||||||
import 'serializers/friendica/connection_friendica_extensions.dart';
|
import 'serializers/friendica/connection_friendica_extensions.dart';
|
||||||
|
import 'serializers/friendica/gallery_data_friendica_extensions.dart';
|
||||||
|
import 'serializers/friendica/image_entry_friendica_extensions.dart';
|
||||||
import 'serializers/mastodon/group_data_mastodon_extensions.dart';
|
import 'serializers/mastodon/group_data_mastodon_extensions.dart';
|
||||||
import 'serializers/mastodon/notification_mastodon_extension.dart';
|
import 'serializers/mastodon/notification_mastodon_extension.dart';
|
||||||
import 'serializers/mastodon/timeline_entry_mastodon_extensions.dart';
|
import 'serializers/mastodon/timeline_entry_mastodon_extensions.dart';
|
||||||
|
@ -68,6 +72,34 @@ class FriendicaClient {
|
||||||
return response.mapValue((value) => true);
|
return response.mapValue((value) => true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FutureResult<List<GalleryData>, ExecError> getGalleryData() async {
|
||||||
|
_logger.finest(() => 'Getting gallery data');
|
||||||
|
final url = 'https://$serverName/api/friendica/photoalbums';
|
||||||
|
final request = Uri.parse(url);
|
||||||
|
return (await _getApiListRequest(request).andThenSuccessAsync(
|
||||||
|
(albumsJson) async => albumsJson
|
||||||
|
.map((json) => GalleryDataFriendicaExtensions.fromJson(json))
|
||||||
|
.toList()))
|
||||||
|
.mapError((error) => error is ExecError
|
||||||
|
? error
|
||||||
|
: ExecError(type: ErrorType.localError, message: error.toString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
FutureResult<List<ImageEntry>, ExecError> getGalleryImages(
|
||||||
|
String galleryName) async {
|
||||||
|
_logger.finest(() => 'Getting gallery data');
|
||||||
|
final url =
|
||||||
|
'https://$serverName/api/friendica/photoalbum?album=$galleryName';
|
||||||
|
final request = Uri.parse(url);
|
||||||
|
return (await _getApiListRequest(request).andThenSuccessAsync(
|
||||||
|
(imagesJson) async => imagesJson
|
||||||
|
.map((json) => ImageEntryFriendicaExtension.fromJson(json))
|
||||||
|
.toList()))
|
||||||
|
.mapError((error) => error is ExecError
|
||||||
|
? error
|
||||||
|
: ExecError(type: ErrorType.localError, message: error.toString()));
|
||||||
|
}
|
||||||
|
|
||||||
FutureResult<List<GroupData>, ExecError> getGroups() async {
|
FutureResult<List<GroupData>, ExecError> getGroups() async {
|
||||||
_logger.finest(() => 'Getting group (Mastodon List) data');
|
_logger.finest(() => 'Getting group (Mastodon List) data');
|
||||||
final url = 'https://$serverName/api/v1/lists';
|
final url = 'https://$serverName/api/v1/lists';
|
||||||
|
|
|
@ -14,6 +14,7 @@ import 'routes.dart';
|
||||||
import 'services/auth_service.dart';
|
import 'services/auth_service.dart';
|
||||||
import 'services/connections_manager.dart';
|
import 'services/connections_manager.dart';
|
||||||
import 'services/entry_manager_service.dart';
|
import 'services/entry_manager_service.dart';
|
||||||
|
import 'services/gallery_service.dart';
|
||||||
import 'services/notifications_manager.dart';
|
import 'services/notifications_manager.dart';
|
||||||
import 'services/secrets_service.dart';
|
import 'services/secrets_service.dart';
|
||||||
import 'services/timeline_manager.dart';
|
import 'services/timeline_manager.dart';
|
||||||
|
@ -39,6 +40,7 @@ void main() async {
|
||||||
final entryManagerService = EntryManagerService();
|
final entryManagerService = EntryManagerService();
|
||||||
final timelineManager = TimelineManager();
|
final timelineManager = TimelineManager();
|
||||||
getIt.registerLazySingleton<ConnectionsManager>(() => ConnectionsManager());
|
getIt.registerLazySingleton<ConnectionsManager>(() => ConnectionsManager());
|
||||||
|
getIt.registerLazySingleton<GalleryService>(() => GalleryService());
|
||||||
getIt.registerSingleton<EntryManagerService>(entryManagerService);
|
getIt.registerSingleton<EntryManagerService>(entryManagerService);
|
||||||
getIt.registerSingleton<SecretsService>(secretsService);
|
getIt.registerSingleton<SecretsService>(secretsService);
|
||||||
getIt.registerSingleton<AuthService>(authService);
|
getIt.registerSingleton<AuthService>(authService);
|
||||||
|
@ -83,6 +85,10 @@ class App extends StatelessWidget {
|
||||||
create: (_) => getIt<EntryManagerService>(),
|
create: (_) => getIt<EntryManagerService>(),
|
||||||
lazy: true,
|
lazy: true,
|
||||||
),
|
),
|
||||||
|
ChangeNotifierProvider<GalleryService>(
|
||||||
|
create: (_) => getIt<GalleryService>(),
|
||||||
|
lazy: true,
|
||||||
|
),
|
||||||
ChangeNotifierProvider<TimelineManager>(
|
ChangeNotifierProvider<TimelineManager>(
|
||||||
create: (_) => getIt<TimelineManager>(),
|
create: (_) => getIt<TimelineManager>(),
|
||||||
),
|
),
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
class GalleryData {
|
||||||
|
final int count;
|
||||||
|
final String name;
|
||||||
|
final DateTime created;
|
||||||
|
|
||||||
|
GalleryData({required this.count, required this.name, required this.created});
|
||||||
|
}
|
|
@ -1,19 +1,29 @@
|
||||||
class ImageEntry {
|
class ImageEntry {
|
||||||
final String postId;
|
final String id;
|
||||||
final String localFilename;
|
final String album;
|
||||||
final String url;
|
final String filename;
|
||||||
|
final String description;
|
||||||
|
final String thumbnailUrl;
|
||||||
|
final DateTime created;
|
||||||
|
final int height;
|
||||||
|
final int width;
|
||||||
|
|
||||||
ImageEntry(
|
ImageEntry({
|
||||||
{required this.postId, required this.localFilename, required this.url});
|
required this.id,
|
||||||
|
required this.album,
|
||||||
|
required this.filename,
|
||||||
|
required this.description,
|
||||||
|
required this.thumbnailUrl,
|
||||||
|
required this.created,
|
||||||
|
required this.height,
|
||||||
|
required this.width,
|
||||||
|
});
|
||||||
|
|
||||||
ImageEntry.fromJson(Map<String, dynamic> json)
|
@override
|
||||||
: postId = json['postId'] ?? '',
|
bool operator ==(Object other) =>
|
||||||
localFilename = json['localFilename'] ?? '',
|
identical(this, other) ||
|
||||||
url = json['url'] ?? '';
|
other is ImageEntry && runtimeType == other.runtimeType && id == other.id;
|
||||||
|
|
||||||
Map<String, dynamic> toJson() => {
|
@override
|
||||||
'postId': postId,
|
int get hashCode => id.hashCode;
|
||||||
'localFilename': localFilename,
|
|
||||||
'url': url,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,8 @@ import 'package:go_router/go_router.dart';
|
||||||
|
|
||||||
import 'globals.dart';
|
import 'globals.dart';
|
||||||
import 'screens/editor.dart';
|
import 'screens/editor.dart';
|
||||||
|
import 'screens/gallery_browsers_screen.dart';
|
||||||
|
import 'screens/gallery_screen.dart';
|
||||||
import 'screens/home.dart';
|
import 'screens/home.dart';
|
||||||
import 'screens/notifications_screen.dart';
|
import 'screens/notifications_screen.dart';
|
||||||
import 'screens/post_screen.dart';
|
import 'screens/post_screen.dart';
|
||||||
|
@ -15,6 +17,7 @@ import 'services/auth_service.dart';
|
||||||
class ScreenPaths {
|
class ScreenPaths {
|
||||||
static String splash = '/splash';
|
static String splash = '/splash';
|
||||||
static String timelines = '/';
|
static String timelines = '/';
|
||||||
|
static String gallery = '/gallery';
|
||||||
static String profile = '/profile';
|
static String profile = '/profile';
|
||||||
static String notifications = '/notifications';
|
static String notifications = '/notifications';
|
||||||
static String signin = '/signin';
|
static String signin = '/signin';
|
||||||
|
@ -73,6 +76,21 @@ final appRouter = GoRouter(
|
||||||
child: ProfileScreen(),
|
child: ProfileScreen(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
GoRoute(
|
||||||
|
path: ScreenPaths.gallery,
|
||||||
|
name: ScreenPaths.gallery,
|
||||||
|
pageBuilder: (context, state) => NoTransitionPage(
|
||||||
|
child: GalleryBrowsersScreen(),
|
||||||
|
),
|
||||||
|
routes: [
|
||||||
|
GoRoute(
|
||||||
|
path: 'show/:name',
|
||||||
|
builder: (context, state) => GalleryScreen(
|
||||||
|
galleryName: state.params['name']!,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
GoRoute(
|
GoRoute(
|
||||||
path: ScreenPaths.notifications,
|
path: ScreenPaths.notifications,
|
||||||
name: ScreenPaths.notifications,
|
name: ScreenPaths.notifications,
|
||||||
|
|
|
@ -0,0 +1,82 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
|
import 'package:logging/logging.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
import '../controls/app_bottom_nav_bar.dart';
|
||||||
|
import '../controls/padding.dart';
|
||||||
|
import '../services/gallery_service.dart';
|
||||||
|
|
||||||
|
class GalleryBrowsersScreen extends StatelessWidget {
|
||||||
|
static final _logger = Logger('$GalleryBrowsersScreen');
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
_logger.finest('Building');
|
||||||
|
final service = context.watch<GalleryService>();
|
||||||
|
return Scaffold(
|
||||||
|
body: RefreshIndicator(
|
||||||
|
onRefresh: () async {
|
||||||
|
print('Refresh gallery list');
|
||||||
|
},
|
||||||
|
child: RefreshIndicator(
|
||||||
|
onRefresh: () async {
|
||||||
|
await service.updateGalleries();
|
||||||
|
},
|
||||||
|
child: buildBody(context, service)),
|
||||||
|
),
|
||||||
|
bottomNavigationBar: AppBottomNavBar(
|
||||||
|
currentButton: NavBarButtons.gallery,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget buildBody(BuildContext context, GalleryService service) {
|
||||||
|
final galleries = service.getGalleries();
|
||||||
|
|
||||||
|
if (galleries.isEmpty && service.loaded) {
|
||||||
|
return const SingleChildScrollView(
|
||||||
|
child: Center(
|
||||||
|
child: Text('No Galleries'),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (galleries.isEmpty) {
|
||||||
|
return Center(
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: const [
|
||||||
|
Text('Loading galleries'),
|
||||||
|
VerticalPadding(),
|
||||||
|
CircularProgressIndicator(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ListView.separated(
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
final gallery = galleries[index];
|
||||||
|
return InkWell(
|
||||||
|
onTap: () {
|
||||||
|
context.push('/gallery/show/${gallery.name}');
|
||||||
|
},
|
||||||
|
child: ListTile(
|
||||||
|
title: Text(gallery.name),
|
||||||
|
subtitle: Text(
|
||||||
|
'Created: ${gallery.created}',
|
||||||
|
style: Theme.of(context).textTheme.caption,
|
||||||
|
),
|
||||||
|
trailing: Text('${gallery.count} Images'),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
separatorBuilder: (context, index) {
|
||||||
|
return const Divider();
|
||||||
|
},
|
||||||
|
itemCount: galleries.length,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,102 @@
|
||||||
|
import 'package:cached_network_image/cached_network_image.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:logging/logging.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
import '../controls/padding.dart';
|
||||||
|
import '../serializers/friendica/image_entry_friendica_extensions.dart';
|
||||||
|
import '../services/gallery_service.dart';
|
||||||
|
import 'image_viewer_screen.dart';
|
||||||
|
|
||||||
|
class GalleryScreen extends StatelessWidget {
|
||||||
|
static const thumbnailDimension = 100.0;
|
||||||
|
static final _logger = Logger('$GalleryScreen');
|
||||||
|
final String galleryName;
|
||||||
|
|
||||||
|
const GalleryScreen({super.key, required this.galleryName});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
_logger.finest('Building');
|
||||||
|
final service = context.watch<GalleryService>();
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: Text(galleryName),
|
||||||
|
),
|
||||||
|
body: RefreshIndicator(
|
||||||
|
onRefresh: () async {
|
||||||
|
print('Refresh $galleryName image list');
|
||||||
|
},
|
||||||
|
child: RefreshIndicator(
|
||||||
|
onRefresh: () async {
|
||||||
|
await service.updateGalleryImageList(galleryName);
|
||||||
|
},
|
||||||
|
child: buildBody(context, service)),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget buildBody(BuildContext context, GalleryService service) {
|
||||||
|
final imageResult = service.getGalleryImageList(galleryName);
|
||||||
|
if (imageResult.isFailure) {
|
||||||
|
return SingleChildScrollView(
|
||||||
|
child: Center(
|
||||||
|
child: Text('Error getting images for gallery: ${imageResult.error}'),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
final images = imageResult.value;
|
||||||
|
if (images.isEmpty && service.loaded) {
|
||||||
|
return const SingleChildScrollView(
|
||||||
|
child: Center(
|
||||||
|
child: Text('No images'),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (images.isEmpty) {
|
||||||
|
return Center(
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: const [
|
||||||
|
Text('Loading images'),
|
||||||
|
VerticalPadding(),
|
||||||
|
CircularProgressIndicator(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ListView.separated(
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
final image = images[index];
|
||||||
|
return InkWell(
|
||||||
|
onTap: () {
|
||||||
|
Navigator.push(context, MaterialPageRoute(builder: (context) {
|
||||||
|
return ImageViewerScreen(attachment: image.toMediaAttachment());
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
child: ListTile(
|
||||||
|
leading: CachedNetworkImage(
|
||||||
|
width: thumbnailDimension,
|
||||||
|
height: thumbnailDimension,
|
||||||
|
imageUrl: image.thumbnailUrl,
|
||||||
|
),
|
||||||
|
title: Text(image.filename),
|
||||||
|
subtitle: Text(
|
||||||
|
image.description,
|
||||||
|
style: Theme.of(context).textTheme.caption,
|
||||||
|
),
|
||||||
|
trailing: Text(image.created.toString()),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
separatorBuilder: (context, index) {
|
||||||
|
return const Divider();
|
||||||
|
},
|
||||||
|
itemCount: images.length,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
import '../../models/gallery_data.dart';
|
||||||
|
|
||||||
|
extension GalleryDataFriendicaExtensions on GalleryData {
|
||||||
|
static GalleryData fromJson(Map<String, dynamic> json) => GalleryData(
|
||||||
|
count: json['count'] ?? -1,
|
||||||
|
name: json['name'] ?? 'Unknown',
|
||||||
|
created: DateTime.tryParse(json['created']) ?? DateTime(0));
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
import '../../models/attachment_media_type_enum.dart';
|
||||||
|
import '../../models/image_entry.dart';
|
||||||
|
import '../../models/media_attachment.dart';
|
||||||
|
|
||||||
|
extension ImageEntryFriendicaExtension on ImageEntry {
|
||||||
|
static ImageEntry fromJson(Map<String, dynamic> json) => ImageEntry(
|
||||||
|
id: json['id'],
|
||||||
|
album: json['album'],
|
||||||
|
filename: json['filename'],
|
||||||
|
description: json['desc'],
|
||||||
|
thumbnailUrl: json['thumb'],
|
||||||
|
created: DateTime.tryParse(json['created']) ?? DateTime(0),
|
||||||
|
height: json['height'],
|
||||||
|
width: json['width'],
|
||||||
|
);
|
||||||
|
|
||||||
|
MediaAttachment toMediaAttachment() {
|
||||||
|
final thumbUri = Uri.parse(thumbnailUrl);
|
||||||
|
final extension = thumbUri.pathSegments.last.split('.').last;
|
||||||
|
final newFileName = '$id-0.$extension';
|
||||||
|
final fullFileUri = Uri.https(thumbUri.authority, '/photo/$newFileName');
|
||||||
|
return MediaAttachment(
|
||||||
|
uri: fullFileUri,
|
||||||
|
creationTimestamp: created.millisecondsSinceEpoch,
|
||||||
|
metadata: {},
|
||||||
|
thumbnailUri: thumbUri,
|
||||||
|
title: filename,
|
||||||
|
explicitType: AttachmentMediaType.image,
|
||||||
|
description: description);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,90 @@
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:logging/logging.dart';
|
||||||
|
import 'package:result_monad/result_monad.dart';
|
||||||
|
|
||||||
|
import '../globals.dart';
|
||||||
|
import '../models/exec_error.dart';
|
||||||
|
import '../models/gallery_data.dart';
|
||||||
|
import '../models/image_entry.dart';
|
||||||
|
import 'auth_service.dart';
|
||||||
|
|
||||||
|
class GalleryService extends ChangeNotifier {
|
||||||
|
static final _logger = Logger('$GalleryService');
|
||||||
|
final _galleries = <String, GalleryData>{};
|
||||||
|
final _images = <String, Set<ImageEntry>>{};
|
||||||
|
var _loaded = false;
|
||||||
|
|
||||||
|
bool get loaded => _loaded;
|
||||||
|
|
||||||
|
List<GalleryData> getGalleries() {
|
||||||
|
if (_galleries.isEmpty) {
|
||||||
|
updateGalleries();
|
||||||
|
}
|
||||||
|
|
||||||
|
return _galleries.values.toList(growable: false);
|
||||||
|
}
|
||||||
|
|
||||||
|
FutureResult<List<GalleryData>, ExecError> updateGalleries() async {
|
||||||
|
final auth = getIt<AuthService>();
|
||||||
|
final clientResult = auth.currentClient;
|
||||||
|
if (clientResult.isFailure) {
|
||||||
|
_logger.severe('Error getting Friendica client: ${clientResult.error}');
|
||||||
|
return clientResult.errorCast();
|
||||||
|
}
|
||||||
|
|
||||||
|
final client = clientResult.value;
|
||||||
|
final result = await client.getGalleryData();
|
||||||
|
if (result.isFailure) {
|
||||||
|
return result.errorCast();
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
return Result.ok([]);
|
||||||
|
} else {
|
||||||
|
return Result.ok(_images[galleryName]!.toList(growable: false));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO Paging
|
||||||
|
FutureResult<List<ImageEntry>, ExecError> updateGalleryImageList(
|
||||||
|
String galleryName) async {
|
||||||
|
final auth = getIt<AuthService>();
|
||||||
|
final clientResult = auth.currentClient;
|
||||||
|
if (clientResult.isFailure) {
|
||||||
|
_logger.severe('Error getting Friendica client: ${clientResult.error}');
|
||||||
|
return clientResult.errorCast();
|
||||||
|
}
|
||||||
|
|
||||||
|
final client = clientResult.value;
|
||||||
|
final result = await client.getGalleryImages(galleryName);
|
||||||
|
if (result.isFailure) {
|
||||||
|
return result.errorCast();
|
||||||
|
}
|
||||||
|
|
||||||
|
final imageSet = _images.putIfAbsent(galleryName, () => {});
|
||||||
|
imageSet.addAll(result.value);
|
||||||
|
|
||||||
|
notifyListeners();
|
||||||
|
return Result.ok(imageSet.toList(growable: false));
|
||||||
|
}
|
||||||
|
}
|
Ładowanie…
Reference in New Issue