Files
reelbox/lib/media/download_button.dart

98 lines
2.9 KiB
Dart

import 'package:flutter/material.dart';
import '../data/models.dart';
import '../state/app_state.dart';
import 'download_service.dart';
import 'downloads_page.dart';
typedef EnqueueDownload = Future<void> Function({
required TitleRecord title,
required MediaSource source,
EpisodeRecord? episode,
});
/// The primary action always queues inside Reelbox, never an external app.
class DownloadButton extends StatefulWidget {
const DownloadButton({
super.key,
required this.title,
required this.source,
this.episode,
this.enqueue,
this.openDownloads,
});
final TitleRecord title;
final MediaSource source;
final EpisodeRecord? episode;
final EnqueueDownload? enqueue;
final void Function(BuildContext context)? openDownloads;
@override
State<DownloadButton> createState() => _DownloadButtonState();
}
class _DownloadButtonState extends State<DownloadButton> {
bool _starting = false;
Future<void> _download() async {
if (_starting) return;
setState(() => _starting = true);
try {
final host = Uri.tryParse(widget.source.url)?.host.toLowerCase() ?? '';
if (RegExp(
'youtube|embed',
caseSensitive: false,
).hasMatch(widget.source.type) ||
host == 'youtu.be' ||
host == 'youtube.com' ||
host.endsWith('.youtube.com')) {
throw UnsupportedError(
tr(
context,
'Embedded sources cannot be downloaded. Choose a direct media source.',
'منابع جاسازی‌شده قابل دانلود نیستند. یک منبع رسانه مستقیم انتخاب کنید.',
),
);
}
await (widget.enqueue ?? DownloadService.instance.enqueue)(
title: widget.title,
source: widget.source,
episode: widget.episode,
);
if (!mounted) return;
if (widget.openDownloads case final open?) {
open(context);
} else {
Navigator.of(
context,
).push(MaterialPageRoute<void>(builder: (_) => const DownloadsPage()));
}
} catch (error) {
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
'${tr(context, 'Could not start download', 'شروع دانلود ممکن نشد')}: ${downloadErrorMessage(error)}',
),
),
);
}
} finally {
if (mounted) setState(() => _starting = false);
}
}
@override
Widget build(BuildContext context) => FilledButton.icon(
onPressed: widget.source.url.isEmpty || _starting ? null : _download,
icon: _starting
? const SizedBox.square(
dimension: 18,
child: CircularProgressIndicator(strokeWidth: 2),
)
: const Icon(Icons.download_outlined),
label: Text(tr(context, 'Download in Reelbox', 'دانلود در ریلباکس')),
);
}