this repo has no description
at main 136 lines 4.6 kB view raw
1import 'package:flutter/cupertino.dart'; 2import 'package:flutter/material.dart'; 3import 'package:flutter/services.dart'; 4import 'package:grain/models/gallery_photo.dart'; 5import 'package:grain/widgets/app_image.dart'; 6 7class EditAltTextSheet extends StatefulWidget { 8 final List<GalleryPhoto> photos; 9 final void Function(Map<String, String?>) onSave; 10 11 const EditAltTextSheet({super.key, required this.photos, required this.onSave}); 12 13 @override 14 State<EditAltTextSheet> createState() => _EditAltTextSheetState(); 15} 16 17class _EditAltTextSheetState extends State<EditAltTextSheet> { 18 late Map<String, TextEditingController> _controllers; 19 20 @override 21 void initState() { 22 super.initState(); 23 _controllers = { 24 for (final photo in widget.photos) photo.uri: TextEditingController(text: photo.alt ?? ''), 25 }; 26 } 27 28 @override 29 void dispose() { 30 for (final c in _controllers.values) { 31 c.dispose(); 32 } 33 super.dispose(); 34 } 35 36 void _onSave() { 37 final altTexts = {for (final photo in widget.photos) photo.uri: _controllers[photo.uri]?.text}; 38 widget.onSave(altTexts); 39 Navigator.of(context).pop(); 40 } 41 42 @override 43 Widget build(BuildContext context) { 44 final theme = Theme.of(context); 45 return CupertinoPageScaffold( 46 backgroundColor: theme.colorScheme.surface, 47 navigationBar: CupertinoNavigationBar( 48 backgroundColor: theme.colorScheme.surface, 49 middle: Text( 50 'Edit alt text', 51 style: theme.textTheme.titleMedium?.copyWith(fontWeight: FontWeight.w600), 52 ), 53 leading: CupertinoButton( 54 padding: EdgeInsets.zero, 55 child: const Text('Cancel'), 56 onPressed: () => Navigator.of(context).pop(), 57 ), 58 trailing: CupertinoButton( 59 padding: EdgeInsets.zero, 60 onPressed: _onSave, 61 child: const Text('Save'), 62 ), 63 ), 64 child: SafeArea( 65 child: ListView.separated( 66 padding: const EdgeInsets.all(16), 67 itemCount: widget.photos.length, 68 separatorBuilder: (_, __) => const SizedBox(height: 12), 69 itemBuilder: (context, index) { 70 final theme = Theme.of(context); 71 final photo = widget.photos[index]; 72 final width = photo.aspectRatio?.width; 73 final height = photo.aspectRatio?.height; 74 return Row( 75 crossAxisAlignment: CrossAxisAlignment.center, 76 children: [ 77 SizedBox( 78 width: 64, 79 child: AspectRatio( 80 aspectRatio: (width != null && height != null && width > 0 && height > 0) 81 ? width / height 82 : 1.0, 83 child: AppImage( 84 url: photo.thumb ?? photo.fullsize, 85 borderRadius: BorderRadius.circular(8), 86 ), 87 ), 88 ), 89 const SizedBox(width: 16), 90 Expanded( 91 child: TextField( 92 controller: _controllers[photo.uri], 93 decoration: InputDecoration( 94 hintText: 'Enter alt text', 95 border: InputBorder.none, 96 filled: false, 97 contentPadding: const EdgeInsets.symmetric(vertical: 16, horizontal: 12), 98 hintStyle: theme.textTheme.bodyMedium?.copyWith(color: theme.hintColor), 99 ), 100 style: theme.textTheme.bodyMedium, 101 cursorColor: theme.colorScheme.primary, 102 minLines: 1, 103 maxLines: 6, 104 textAlignVertical: TextAlignVertical.top, 105 scrollPhysics: const AlwaysScrollableScrollPhysics(), 106 keyboardType: TextInputType.multiline, 107 ), 108 ), 109 ], 110 ); 111 }, 112 ), 113 ), 114 ); 115 } 116} 117 118Future<void> showEditAltTextSheet( 119 BuildContext context, { 120 required List<GalleryPhoto> photos, 121 required void Function(Map<String, String?>) onSave, 122}) async { 123 final theme = Theme.of(context); 124 await showCupertinoSheet( 125 context: context, 126 useNestedNavigation: false, 127 pageBuilder: (context) => Material( 128 type: MaterialType.transparency, 129 child: EditAltTextSheet(photos: photos, onSave: onSave), 130 ), 131 ); 132 // Restore status bar style or any other cleanup 133 SystemChrome.setSystemUIOverlayStyle( 134 theme.brightness == Brightness.dark ? SystemUiOverlayStyle.light : SystemUiOverlayStyle.dark, 135 ); 136}