import 'package:flutter/material.dart'; import 'package:flutter_downloader/flutter_downloader.dart'; import 'package:get_it/get_it.dart'; import 'package:hive/hive.dart'; import '../../models/finamp_models.dart'; import '../../services/downloads_helper.dart'; import '../../services/download_update_stream.dart'; import '../../models/jellyfin_models.dart'; import '../error_snackbar.dart'; class DownloadedIndicator extends StatefulWidget { const DownloadedIndicator({ Key? key, required this.item, this.size, }) : super(key: key); final BaseItemDto item; final double? size; @override State createState() => _DownloadedIndicatorState(); } class _DownloadedIndicatorState extends State { final _downloadsHelper = GetIt.instance(); final _downloadUpdateStream = GetIt.instance(); late Future?> _downloadedIndicatorFuture; String? _downloadTaskId; DownloadTaskStatus? _currentStatus; @override void initState() { super.initState(); _downloadedIndicatorFuture = _downloadsHelper.getDownloadStatus([widget.item.id]); // We do this instead of using a StreamBuilder because the StreamBuilder // kept dropping events. With this, we can also make it so that the widget // only rebuilds when it actually has to. _downloadUpdateStream.stream.listen((event) { if (event.id == _downloadTaskId && event.status != _currentStatus) { setState(() { _currentStatus = event.status; }); } }); } @override Widget build(BuildContext context) { return FutureBuilder?>( future: _downloadedIndicatorFuture, builder: (context, snapshot) { if (snapshot.hasData) { if (snapshot.data != null && snapshot.data!.isNotEmpty) { _downloadTaskId = snapshot.data?[0].taskId; _currentStatus = snapshot.data?[0].status; } // This ValueListenable is used to get the download task ID of new // downloads. It also clears the task ID and status when the download // is deleted. This only rebuilds when the item with key // widget.item.id is changed, so this should only rebuild when the // item is first downloaded and when it is deleted. return ValueListenableBuilder>( valueListenable: _downloadsHelper .getDownloadedItemsListenable(keys: [widget.item.id]), builder: (context, box, _) { if (_downloadTaskId == null && box.get(widget.item.id) != null) { _downloadTaskId = box.get(widget.item.id)!.downloadId; } else if (box.get(widget.item.id) == null) { _downloadTaskId = null; _currentStatus = null; } // return StreamBuilder( // stream: _downloadUpdateStream.stream, // builder: (context, snapshot) { // print("Streambuilder rebuild ${snapshot.data}"); // if (snapshot.hasData && // snapshot.data!.id == _downloadTask?.taskId) { // print("Change $_currentStatus to ${snapshot.data?.status}"); // if (snapshot.data?.status == DownloadTaskStatus.complete) { // print( // "COMPLETE IN STREAMBUILDER ${widget.item.name}!!!!"); // } // _currentStatus = snapshot.data?.status; // } if (_currentStatus == null) { return const SizedBox.shrink(); } else if (_currentStatus == DownloadTaskStatus.complete) { return Icon( Icons.download, color: Theme.of(context).colorScheme.secondary, size: widget.size, ); } else if (_currentStatus == DownloadTaskStatus.failed || _currentStatus == DownloadTaskStatus.undefined) { return Icon( Icons.error, color: Colors.red, size: widget.size, ); } else if (_currentStatus == DownloadTaskStatus.paused) { return Icon( Icons.pause, color: Colors.yellow, size: widget.size, ); } else if (_currentStatus == DownloadTaskStatus.enqueued || _currentStatus == DownloadTaskStatus.running) { return Icon( Icons.download_outlined, color: Colors.white.withOpacity(0.5), size: widget.size, ); } else { return const SizedBox.shrink(); } // }, // ); }, ); } else if (snapshot.hasError) { errorSnackbar(snapshot.error, context); return const SizedBox.shrink(); } else { return const SizedBox.shrink(); } }, ); } }