relatica/lib/screens/gallery_browsers_screen.dart

174 wiersze
5.6 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import 'package:logging/logging.dart';
import '../controls/async_value_widget.dart';
import '../controls/error_message_widget.dart';
import '../controls/padding.dart';
import '../controls/standard_appbar.dart';
import '../controls/status_and_refresh_button.dart';
import '../models/auth/profile.dart';
import '../riverpod_controllers/account_services.dart';
import '../riverpod_controllers/gallery_services.dart';
class GalleryBrowsersScreen extends ConsumerWidget {
static final _logger = Logger('$GalleryBrowsersScreen');
const GalleryBrowsersScreen({super.key});
String? validNameChecker(String? text) {
final newName = text ?? '';
if (newName.isEmpty) {
return 'Name cannot be empty';
}
if (!RegExp(
r"^[a-zA-Z0-9 ]+$",
).hasMatch(newName)) {
return 'Name must be only letters and numbers';
}
return null;
}
Future<void> renameGallery(
BuildContext context,
WidgetRef ref,
Profile profile,
String galleryName,
) async {
final newName = await showDialog<String>(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
var controller = TextEditingController(text: galleryName);
return Form(
child: AlertDialog(
title: const Text('Rename Gallery'),
content: TextFormField(
controller: controller,
autovalidateMode: AutovalidateMode.always,
validator: validNameChecker,
),
actions: <Widget>[
ElevatedButton(
child: const Text('OK'),
onPressed: () {
if (validNameChecker(controller.text) != null) {
return;
}
Navigator.pop(context,
controller.text); // showDialog() returns true
},
),
ElevatedButton(
child: const Text('Cancel'),
onPressed: () {
Navigator.pop(
context, galleryName); // showDialog() returns true
},
),
],
),
);
},
) ??
'';
if (newName.isEmpty || newName == galleryName) {
return;
}
await ref
.read(galleryProvider(profile, galleryName).notifier)
.rename(newName);
}
@override
Widget build(BuildContext context, WidgetRef ref) {
_logger.finer('Building');
final profile = ref.watch(activeProfileProvider);
final loading = switch (ref.watch(galleryListProvider(profile))) {
AsyncData() => false,
_ => true,
};
return Scaffold(
appBar: StandardAppBar.build(context, 'Galleries', actions: [
StatusAndRefreshButton3(
executing: loading,
refreshFunction: () async => await ref
.read(galleryListProvider(profile).notifier)
.updateGalleries(),
busyColor: Theme.of(context).colorScheme.surface,
),
]),
body: RefreshIndicator(
onRefresh: () async {
await ref
.read(galleryListProvider(profile).notifier)
.updateGalleries();
},
child: buildBody(context, ref, profile),
),
);
}
Widget buildBody(BuildContext context, WidgetRef ref, Profile profile) {
return AsyncValueWidget(ref.watch(galleryListProvider(profile)),
loadingBuilder: (_, __) => const Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text('Loading galleries'),
VerticalPadding(),
CircularProgressIndicator(),
],
),
),
valueBuilder: (context, ref, galleryListResult) {
return galleryListResult.fold(
onSuccess: (galleries) {
if (galleries.isEmpty) {
return const SingleChildScrollView(
child: Center(
child: Text('No Galleries'),
),
);
}
return ListView.separated(
itemBuilder: (context, index) {
final gallery = galleries[index];
return ListTile(
onTap: () =>
context.push('/gallery/show', extra: gallery.name),
title: Text(gallery.name),
subtitle: Text(
'#Photos: ${gallery.count}, Created: ${gallery.created}',
style: Theme.of(context).textTheme.bodySmall,
),
trailing: ElevatedButton(
onPressed: () async => await renameGallery(
context,
ref,
profile,
gallery.name,
),
child: const Text('Rename'),
),
);
},
separatorBuilder: (context, index) {
return const Divider();
},
itemCount: galleries.length,
);
},
onError: (error) => ErrorMessageWidget(message: error.message),
);
});
}
}