import 'package:flutter/material.dart'; import 'package:manager_app/Components/resource_picker.dart'; import 'package:manager_app/Screens/Resources/resource_formatting.dart'; import 'package:manager_app/app_context.dart'; import 'package:manager_app/constants.dart'; import 'package:manager_app/l10n/app_localizations.dart'; /// Dialogue d'ajout d'une ressource. /// /// Un seul corps, pas deux onglets : « Local » / « En ligne » imposait une question /// technique — où vivent les octets — avant que l'utilisateur ait rien choisi. Une /// zone de dépôt, et dessous une ligne « ou coller une URL » qui se déplie. /// /// Rend la liste des entrées choisies, ou `null` si le dialogue est annulé. Future?> showNewResource( AppContext appContext, BuildContext context) async { final picked = []; return showDialog>( context: context, builder: (BuildContext context) => _NewResourceDialog(picked: picked), ); } class _NewResourceDialog extends StatefulWidget { final List picked; const _NewResourceDialog({required this.picked}); @override State<_NewResourceDialog> createState() => _NewResourceDialogState(); } class _NewResourceDialogState extends State<_NewResourceDialog> { int get _totalBytes => widget.picked.fold(0, (sum, entry) => sum + entry.sizeBytes); @override Widget build(BuildContext context) { final l = AppLocalizations.of(context)!; return Dialog( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(kRadiusShell), side: const BorderSide(color: kLine), ), clipBehavior: Clip.antiAlias, child: SizedBox( width: 560, child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ _header(l), Flexible( child: SingleChildScrollView( padding: const EdgeInsets.fromLTRB(kSpace6, 0, kSpace6, kSpace4), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, mainAxisSize: MainAxisSize.min, children: [ ResourcePicker( picked: widget.picked, onChanged: () => setState(() {}), ), if (widget.picked.isNotEmpty) _totals(l), ], ), ), ), _footer(l), ], ), ), ); } Widget _header(AppLocalizations l) { return Padding( padding: const EdgeInsets.fromLTRB(kSpace6, kSpace5, kSpace4, kSpace4), child: Row( children: [ Expanded(child: Text(l.mediaAddTitle, style: kTitleCard)), IconButton( icon: const Icon(Icons.close, size: 18, color: kInk3), splashRadius: 16, tooltip: l.close, onPressed: () => Navigator.of(context).pop(), ), ], ), ); } Widget _totals(AppLocalizations l) { return Padding( padding: const EdgeInsets.only(top: kSpace4), child: Text( l.mediaSelectedTotal(widget.picked.length, formatBytes(context, _totalBytes)), style: kTextHint, ), ); } Widget _footer(AppLocalizations l) { // Désactivé plutôt qu'expliqué : l'ancien dialogue acceptait le clic à vide, // puis affichait une notification orange « aucun fichier chargé ». final canAdd = widget.picked.isNotEmpty; return Container( padding: const EdgeInsets.all(kSpace4), decoration: const BoxDecoration( color: kSurface2, border: Border(top: BorderSide(color: kLineSoft)), ), child: Row( mainAxisAlignment: MainAxisAlignment.end, children: [ TextButton( onPressed: () => Navigator.of(context).pop(), child: Text(l.cancel, style: const TextStyle(fontSize: 13, color: kInk2)), ), const SizedBox(width: kSpace2), FilledButton( onPressed: canAdd ? () => Navigator.pop(context, widget.picked) : null, style: FilledButton.styleFrom( backgroundColor: kPrimaryColor, padding: const EdgeInsets.symmetric( horizontal: kSpace5, vertical: kSpace3), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(kRadiusPill)), ), child: Text(l.mediaAddCount(widget.picked.length), style: const TextStyle(fontSize: 13, fontWeight: FontWeight.w600)), ), ], ), ); } }