import 'package:flutter/material.dart'; import 'package:venera/components/components.dart'; import 'package:venera/foundation/app.dart'; import 'package:venera/foundation/image_provider/cached_image.dart'; import 'package:venera/foundation/local.dart'; import 'package:venera/network/download.dart'; import 'package:venera/utils/io.dart'; import 'package:venera/utils/translations.dart'; class DownloadingPage extends StatefulWidget { const DownloadingPage({super.key}); @override State createState() => _DownloadingPageState(); } class _DownloadingPageState extends State { @override void initState() { LocalManager().addListener(update); super.initState(); } @override void dispose() { LocalManager().removeListener(update); super.dispose(); } void update() { if(mounted) { setState(() {}); } } @override Widget build(BuildContext context) { return PopUpWidgetScaffold( title: "", body: ListView.builder( itemCount: LocalManager().downloadingTasks.length + 1, itemBuilder: (BuildContext context, int i) { if (i == 0) { return buildTop(); } i--; return _DownloadTaskTile( task: LocalManager().downloadingTasks[i], ); }, ), ); } Widget buildTop() { int speed = 0; if (LocalManager().downloadingTasks.isNotEmpty) { speed = LocalManager().downloadingTasks.first.speed; } var first = LocalManager().downloadingTasks.firstOrNull; return Container( height: 48, decoration: BoxDecoration( border: Border( bottom: BorderSide( color: context.colorScheme.outlineVariant, width: 0.6, ), ), ), child: Row( children: [ if (first?.isPaused == true) Text( "Paused".tl, style: ts.s18.bold, ) else if (first?.isError == true) Text( "Error".tl, style: ts.s18.bold, ) else Text( "${bytesToReadableString(speed)}/s", style: ts.s18.bold, ), const Spacer(), if (first?.isPaused == true || first?.isError == true) OutlinedButton( child: Row( children: [ const Icon(Icons.play_arrow, size: 18), const SizedBox(width: 4), Text("Start".tl), ], ), onPressed: () { first!.resume(); }, ) else if (first != null) OutlinedButton( child: Row( children: [ const Icon(Icons.pause, size: 18), const SizedBox(width: 4), Text("Pause".tl), ], ), onPressed: () { first.pause(); }, ), ], ).paddingHorizontal(16), ); } } class _DownloadTaskTile extends StatefulWidget { const _DownloadTaskTile({required this.task}); final DownloadTask task; @override State<_DownloadTaskTile> createState() => _DownloadTaskTileState(); } class _DownloadTaskTileState extends State<_DownloadTaskTile> { @override void initState() { widget.task.addListener(update); super.initState(); } @override void dispose() { widget.task.removeListener(update); super.dispose(); } void update() { context.findAncestorStateOfType<_DownloadingPageState>()?.update(); } @override Widget build(BuildContext context) { return Container( height: 136, padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 12), child: Row( children: [ Container( width: 82, height: double.infinity, decoration: BoxDecoration( borderRadius: BorderRadius.circular(8), color: context.colorScheme.primaryContainer, ), clipBehavior: Clip.antiAlias, child: widget.task.cover == null ? null : Image( image: CachedImageProvider(widget.task.cover!), filterQuality: FilterQuality.medium, fit: BoxFit.cover, ), ), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Expanded( child: Text( widget.task.title, style: Theme.of(context).textTheme.bodyMedium, maxLines: 2, ), ), MenuButton( entries: [ MenuEntry( icon: Icons.close, text: "Cancel".tl, onClick: () { widget.task.cancel(); }, ), MenuEntry( icon: Icons.vertical_align_top, text: "Move To First".tl, onClick: () { LocalManager().moveToFirst(widget.task); }, ), ], ), ], ), const Spacer(), if (!widget.task.isPaused || widget.task.isError) Text( widget.task.message, style: ts.s12, maxLines: 3, ), const SizedBox(height: 4), LinearProgressIndicator( value: widget.task.progress, ), const SizedBox(height: 8), ], ), ), ], ), ); } }