98 lines
2.9 KiB
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', 'دانلود در ریلباکس')),
|
|
);
|
|
}
|