feat: Enhance gallery editing by managing loading states and disabling actions during deletions

Changed files
+43 -21
lib
+43 -21
lib/screens/gallery_edit_photos_sheet.dart
··· 30 30 class _GalleryEditPhotosSheetState extends ConsumerState<GalleryEditPhotosSheet> { 31 31 late List<GalleryPhoto> _photos; 32 32 bool _loading = false; 33 + int? _deletingPhotoIndex; 33 34 34 35 @override 35 36 void initState() { ··· 40 41 @override 41 42 Widget build(BuildContext context) { 42 43 final theme = Theme.of(context); 43 - // ...existing code... 44 44 return CupertinoPageScaffold( 45 45 backgroundColor: theme.colorScheme.surface, 46 46 navigationBar: CupertinoNavigationBar( ··· 52 52 ), 53 53 leading: CupertinoButton( 54 54 padding: EdgeInsets.zero, 55 - onPressed: _loading ? null : () => Navigator.of(context).maybePop(), 55 + onPressed: (_loading || _deletingPhotoIndex != null) 56 + ? null 57 + : () => Navigator.of(context).maybePop(), 56 58 child: Text( 57 59 'Cancel', 58 - style: TextStyle(color: theme.colorScheme.primary, fontWeight: FontWeight.w600), 60 + style: TextStyle( 61 + color: _deletingPhotoIndex != null ? theme.disabledColor : theme.colorScheme.primary, 62 + fontWeight: FontWeight.w600, 63 + ), 59 64 ), 60 65 ), 61 66 ), ··· 80 85 ), 81 86 itemBuilder: (context, index) { 82 87 final photo = _photos[index]; 88 + final isDeleting = _deletingPhotoIndex == index; 83 89 return Stack( 84 90 fit: StackFit.expand, 85 91 children: [ ··· 97 103 top: 8, 98 104 right: 8, 99 105 child: GestureDetector( 100 - onTap: _loading 106 + onTap: (_loading || _deletingPhotoIndex != null || isDeleting) 101 107 ? null 102 108 : () async { 103 109 final confirm = await showDialog<bool>( ··· 120 126 ), 121 127 ); 122 128 if (confirm == true && photo.gallery?.item != null) { 129 + if (!mounted) return; 130 + setState(() { 131 + _deletingPhotoIndex = index; 132 + }); 123 133 await ref 124 134 .read(galleryCacheProvider.notifier) 125 135 .removePhotoFromGallery( 126 136 widget.galleryUri, 127 137 photo.gallery!.item, 128 138 ); 139 + if (!mounted) return; 129 140 setState(() { 130 141 _photos.removeAt(index); 142 + _deletingPhotoIndex = null; 131 143 }); 132 144 } 133 145 }, ··· 137 149 shape: BoxShape.circle, 138 150 ), 139 151 padding: const EdgeInsets.all(4), 140 - child: const Icon(Icons.close, color: Colors.white, size: 20), 152 + child: isDeleting 153 + ? SizedBox( 154 + width: 20, 155 + height: 20, 156 + child: CircularProgressIndicator( 157 + strokeWidth: 2, 158 + valueColor: AlwaysStoppedAnimation<Color>(Colors.white), 159 + ), 160 + ) 161 + : const Icon(Icons.close, color: Colors.white, size: 20), 141 162 ), 142 163 ), 143 164 ), ··· 155 176 child: AppButton( 156 177 label: 'Upload photos', 157 178 loading: _loading, 158 - onPressed: _loading 179 + onPressed: (_loading || _deletingPhotoIndex != null) 159 180 ? null 160 181 : () async { 161 182 final picker = ImagePicker(); ··· 186 207 child: AppButton( 187 208 label: 'Add from library', 188 209 variant: AppButtonVariant.secondary, 189 - onPressed: () async { 190 - if (_loading) return; 191 - final actorDid = apiService.currentUser?.did; 192 - if (actorDid == null) return; 193 - await showLibraryPhotosSelectSheet( 194 - context, 195 - actorDid: actorDid, 196 - galleryUri: widget.galleryUri, 197 - onSelect: (photos) { 198 - setState(() { 199 - _photos.addAll(photos); 200 - }); 201 - }, 202 - ); 203 - }, 210 + onPressed: (_loading || _deletingPhotoIndex != null) 211 + ? null 212 + : () async { 213 + final actorDid = apiService.currentUser?.did; 214 + if (actorDid == null) return; 215 + await showLibraryPhotosSelectSheet( 216 + context, 217 + actorDid: actorDid, 218 + galleryUri: widget.galleryUri, 219 + onSelect: (photos) { 220 + setState(() { 221 + _photos.addAll(photos); 222 + }); 223 + }, 224 + ); 225 + }, 204 226 ), 205 227 ), 206 228 ],