import 'package:flutter/material.dart' hide Visibility; import 'package:provider/provider.dart'; import '../controls/login_aware_cached_network_image.dart'; import '../models/gallery_data.dart'; import '../models/image_entry.dart'; import '../models/visibility.dart'; import '../serializers/friendica/image_entry_friendica_extensions.dart'; import '../services/gallery_service.dart'; import '../utils/active_profile_selector.dart'; import 'media_viewer_screen.dart'; class ExistingImageSelectorScreen extends StatefulWidget { final Visibility? visibilityFilter; const ExistingImageSelectorScreen({ super.key, this.visibilityFilter, }); @override State createState() => _ExistingImageSelectorScreenState(); } class _ExistingImageSelectorScreenState extends State { GalleryData? selectedGallery; final selectedImages = []; @override Widget build(BuildContext context) { final service = context .watch>() .activeEntry .value; final title = selectedImages.isEmpty ? 'Select Image(s)' : '${selectedImages.length} selected'; final galleries = service.getGalleries(); return SafeArea( child: Scaffold( appBar: AppBar( title: Text(title), actions: [ IconButton( onPressed: selectedImages.isEmpty ? null : () { Navigator.of(context).pop(selectedImages); }, tooltip: 'Attach selected files', icon: const Icon(Icons.attach_file), ), IconButton( onPressed: selectedImages.isEmpty ? null : () { setState(() { selectedImages.clear(); }); }, tooltip: 'Clear Selection', icon: const Icon(Icons.remove_circle_outline), ), ], ), body: Center( child: Column( children: [ DropdownButton( value: selectedGallery, items: galleries .map((g) => DropdownMenuItem(value: g, child: Text(g.name))) .toList(), onChanged: (value) { setState(() { selectedGallery = value; }); }), const VerticalDivider(), selectedGallery == null ? buildInfoBody() : Expanded(child: buildGrid(context, service)), ], )), ), ); } Widget buildInfoBody() { return const Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [Text('Select a gallery')], ), ); } Widget buildGrid( BuildContext context, GalleryService service, ) { const thumbnailDimension = 350.0; final galleryName = selectedGallery!.name; final expectedPhotoCount = service.getGallery(galleryName).fold( onSuccess: (gd) => gd.count, onError: (_) => 0, ); final List images = selectedGallery == null ? [] : service .getGalleryImageList(galleryName) .getValueOrElse(() => []) .where((i) => widget.visibilityFilter == null ? true : i.visibility.type == widget.visibilityFilter!.type) .toList(); return GridView.builder( itemCount: images.length, padding: const EdgeInsets.all(5.0), gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent( maxCrossAxisExtent: thumbnailDimension), itemBuilder: (context, index) { final image = images[index]; if (images.length < expectedPhotoCount && index == images.length - 1) { service.updateGalleryImageList( galleryName: galleryName, withNextPage: true, nextPageOnly: true, ); } final selected = selectedImages.contains(image); final tileWidget = Card( child: Stack( children: [ LoginAwareCachedNetworkImage( imageUrl: image.thumbnailUrl, ), if (selected) const Positioned( child: Icon( Icons.check_circle, color: Colors.green, )), Positioned( bottom: 5.0, right: 5.0, child: Icon(image.visibility.type == VisibilityType.public ? Icons.public : Icons.lock), ), ], ), ); return Padding( padding: const EdgeInsets.all(2.0), child: GestureDetector( onTap: () { setState(() { if (selected) { selectedImages.remove(image); } else { selectedImages.add(image); } }); }, onDoubleTap: () { Navigator.of(context).push( MaterialPageRoute( builder: (context) => MediaViewerScreen( attachments: [image.toMediaAttachment()], ), ), ); }, child: tileWidget, ), ); }); } }