import 'package:clipboard/clipboard.dart'; import 'package:expandable/expandable.dart'; import 'package:flutter/material.dart'; import 'package:flutter_translate/flutter_translate.dart'; import 'package:provider/provider.dart'; import 'package:share_plus/share_plus.dart'; import '../../core/enums/viewstate.dart'; import '../../core/models/session.dart'; import '../../core/util/formatter_util.dart'; import '../../core/util/paste_util.dart'; import '../../core/viewmodels/history_model.dart'; import '../../ui/widgets/centered_error_row.dart'; import '../shared/app_colors.dart'; import '../widgets/my_appbar.dart'; import 'base_view.dart'; class HistoryView extends StatelessWidget { static const routeName = '/history'; const HistoryView({super.key}); @override Widget build(BuildContext context) { return BaseView( onModelReady: (model) { model.init(); return model.getHistory(); }, builder: (context, model, child) => Scaffold( appBar: MyAppBar(title: Text(translate('titles.history'))), body: _render(model, context)), ); } Widget _render(HistoryModel model, BuildContext context) { var url = Provider.of(context).url; return model.state == ViewState.busy ? const Center(child: CircularProgressIndicator()) : (model.errorMessage == null ? Container( padding: const EdgeInsets.all(0), child: RefreshIndicator( onRefresh: () async => await model.getHistory(), child: _renderItems(model, url, context))) : Container( padding: const EdgeInsets.all(25), child: CenteredErrorRow( model.errorMessage, retryCallback: () => model.getHistory(), ))); } Widget _renderItems(HistoryModel model, String url, BuildContext context) { List cards = []; if (model.pastes.isNotEmpty) { for (var paste in model.pastes.reversed) { List widgets = []; var fullPasteUrl = PasteUtil.generateLink(url, paste.id); var openInBrowserButton = _renderOpenInBrowser(model, fullPasteUrl); var dateWidget = ListTile( title: Text( FormatterUtil.formatEpoch(paste.date!.millisecondsSinceEpoch)), subtitle: Text(translate('history.date')), ); var linkWidget = ListTile( title: Text(translate('history.open_link')), trailing: openInBrowserButton, ); var copyWidget = ListTile( title: Text(translate('history.copy_link.description')), trailing: IconButton( icon: const Icon(Icons.copy, color: blueColor, textDirection: TextDirection.ltr), onPressed: () { FlutterClipboard.copy(fullPasteUrl).then((value) { final snackBar = SnackBar( action: SnackBarAction( label: translate('history.copy_link.dismiss'), textColor: blueColor, onPressed: () { ScaffoldMessenger.of(context).hideCurrentSnackBar(); }, ), content: Text(translate('history.copy_link.copied')), duration: const Duration(seconds: 10), ); ScaffoldMessenger.of(context).showSnackBar(snackBar); }); })); var deleteWidget = ListTile( title: Text(translate('history.delete')), trailing: IconButton( icon: const Icon(Icons.delete, color: redColor), onPressed: () { model.deletePaste(paste.id); })); if (!paste.isMulti!) { var titleWidget = ListTile( title: Text(paste.filename ?? paste.id), subtitle: Text(translate('history.filename')), ); var fileSizeWidget = ListTile( title: Text(FormatterUtil.formatBytes(paste.filesize as int, 2)), subtitle: Text(translate('history.filesize')), ); var idWidget = ListTile( title: Text(paste.id), subtitle: Text(translate('history.id')), ); var mimeTypeWidget = ListTile( title: Text(paste.mimetype!), subtitle: Text(translate('history.mimetype')), ); widgets.add(titleWidget); widgets.add(idWidget); widgets.add(fileSizeWidget); widgets.add(mimeTypeWidget); } else { for (var element in paste.items!) { widgets.add(ListTile( title: Text(element!), subtitle: Text(translate('history.multipaste_element')), trailing: _renderOpenInBrowser(model, '$url/$element'), )); } } widgets.add(dateWidget); widgets.add(linkWidget); widgets.add(copyWidget); widgets.add(deleteWidget); var expandable = ExpandableTheme( data: const ExpandableThemeData( iconPlacement: ExpandablePanelIconPlacement.right, headerAlignment: ExpandablePanelHeaderAlignment.center, hasIcon: true, iconColor: blueColor, tapHeaderToExpand: true), child: ExpandablePanel( collapsed: Container(), header: InkWell( child: Text( paste.id, style: const TextStyle(color: blueColor), textAlign: TextAlign.left, )), expanded: Column( mainAxisSize: MainAxisSize.min, children: widgets, ), ), ); cards.add(Card( child: ListTile( title: expandable, trailing: Wrap(children: [ openInBrowserButton, IconButton( icon: const Icon(Icons.share, color: blueColor, textDirection: TextDirection.ltr), onPressed: () async { await Share.share(fullPasteUrl); }) ]), subtitle: Text(!paste.isMulti! ? paste.filename! : '', style: const TextStyle(fontStyle: FontStyle.italic)), ), )); } } else { cards.add(Card( child: ListTile( title: Text(translate('history.no_items')), ), )); } return ListView( padding: const EdgeInsets.all(8), physics: const AlwaysScrollableScrollPhysics(), children: cards, ); } Widget _renderOpenInBrowser(HistoryModel model, String url) { return IconButton( icon: const Icon(Icons.open_in_new, color: blueColor, textDirection: TextDirection.ltr), onPressed: () { return model.openLink(url); }); } }