kopia lustrzana https://gitlab.com/mysocialportal/relatica
167 wiersze
5.3 KiB
Dart
167 wiersze
5.3 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
import 'package:go_router/go_router.dart';
|
|
import 'package:result_monad/result_monad.dart';
|
|
|
|
import '../controls/login_aware_cached_network_image.dart';
|
|
import '../controls/padding.dart';
|
|
import '../controls/responsive_max_width.dart';
|
|
import '../controls/standard_appbar.dart';
|
|
import '../globals.dart';
|
|
import '../models/exec_error.dart';
|
|
import '../models/image_entry.dart';
|
|
import '../models/visibility.dart';
|
|
import '../riverpod_controllers/account_services.dart';
|
|
import '../riverpod_controllers/gallery_services.dart';
|
|
import '../utils/snackbar_builder.dart';
|
|
|
|
class ImageEditorScreen extends ConsumerStatefulWidget {
|
|
final String galleryName;
|
|
final String imageId;
|
|
|
|
const ImageEditorScreen({
|
|
super.key,
|
|
required this.galleryName,
|
|
required this.imageId,
|
|
});
|
|
|
|
@override
|
|
ConsumerState<ImageEditorScreen> createState() => _ImageEditorScreenState();
|
|
}
|
|
|
|
class _ImageEditorScreenState extends ConsumerState<ImageEditorScreen> {
|
|
Result<ImageEntry, ExecError>? originalImageResult;
|
|
final altTextController = TextEditingController();
|
|
|
|
bool get changed =>
|
|
originalImageResult
|
|
?.transform((image) => image.description != altTextController.text)
|
|
.getValueOrElse(() => false) ??
|
|
false;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final profile = ref.watch(activeProfileProvider);
|
|
ref
|
|
.watch(galleryImageProvider(profile, widget.galleryName, widget.imageId)
|
|
.future)
|
|
.then((value) {
|
|
if (originalImageResult == value) {
|
|
return;
|
|
}
|
|
|
|
setState(() {
|
|
originalImageResult = value;
|
|
altTextController.text = value.isSuccess ? value.value.description : '';
|
|
});
|
|
});
|
|
return Scaffold(
|
|
appBar: StandardAppBar.build(
|
|
context,
|
|
'Edit Image',
|
|
withDrawer: true,
|
|
),
|
|
body: SingleChildScrollView(
|
|
child: ResponsiveMaxWidth(
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(8.0),
|
|
child: Column(
|
|
children: [
|
|
...originalImageResult?.fold(
|
|
onSuccess: (image) => buildEditor(image),
|
|
onError: (error) => buildError(error),
|
|
) ??
|
|
[const CircularProgressIndicator()],
|
|
const VerticalPadding(),
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
ElevatedButton(
|
|
onPressed: () async {
|
|
if (!changed) {
|
|
return;
|
|
}
|
|
|
|
if (originalImageResult?.isFailure ?? true) {
|
|
return;
|
|
}
|
|
final result = await ref
|
|
.read(galleryImagesProvider(
|
|
profile, widget.galleryName)
|
|
.notifier)
|
|
.updateImage(originalImageResult!.value.copy(
|
|
description: altTextController.text,
|
|
));
|
|
|
|
if (!mounted) {
|
|
return;
|
|
}
|
|
|
|
result.match(
|
|
onSuccess: (_) => context.pop(),
|
|
onError: (error) => buildSnackbar(context,
|
|
'Error attempting to update image: $error'),
|
|
);
|
|
},
|
|
child: const Text('Save')),
|
|
const HorizontalPadding(),
|
|
ElevatedButton(
|
|
onPressed: () async {
|
|
if (!changed) {
|
|
context.pop();
|
|
}
|
|
|
|
final ok = await showYesNoDialog(
|
|
context,
|
|
'Cancel changes?',
|
|
);
|
|
if (ok == true && context.mounted) {
|
|
context.pop();
|
|
}
|
|
},
|
|
child: const Text('Cancel')),
|
|
],
|
|
)
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
List<Widget> buildEditor(ImageEntry originalImage) {
|
|
return [
|
|
Row(
|
|
children: [
|
|
const Text('Visibility:'),
|
|
const HorizontalPadding(),
|
|
originalImage.visibility.type == VisibilityType.public
|
|
? const Icon(Icons.public)
|
|
: const Icon(Icons.lock),
|
|
],
|
|
),
|
|
const VerticalPadding(),
|
|
LoginAwareCachedNetworkImage(imageUrl: originalImage.thumbnailUrl),
|
|
const VerticalPadding(),
|
|
TextField(
|
|
controller: altTextController,
|
|
maxLines: 10,
|
|
textCapitalization: TextCapitalization.sentences,
|
|
decoration: InputDecoration(
|
|
labelText: 'ALT Text',
|
|
alignLabelWithHint: true,
|
|
border: OutlineInputBorder(
|
|
borderSide: const BorderSide(),
|
|
borderRadius: BorderRadius.circular(5.0),
|
|
),
|
|
),
|
|
),
|
|
];
|
|
}
|
|
|
|
List<Widget> buildError(ExecError error) {
|
|
return [Text('Error loading image: $error')];
|
|
}
|
|
}
|