mirror of
https://github.com/kodjodevf/mangayomi.git
synced 2026-03-11 17:25:32 +00:00
add option to download online subtitles
- button appears for downloaded and local entries - added app logging class
This commit is contained in:
parent
f6c2a24af2
commit
e2ddcf1ffe
18 changed files with 131 additions and 2 deletions
|
|
@ -145,6 +145,7 @@
|
|||
"check_for_update": "Check for update",
|
||||
"share_app_logs": "Share app logs",
|
||||
"no_app_logs": "No log.txt available!",
|
||||
"failed": "Failed!",
|
||||
"n_days_ago": "{days} days ago",
|
||||
"today": "Today",
|
||||
"yesterday": "Yesterday",
|
||||
|
|
|
|||
|
|
@ -945,6 +945,12 @@ abstract class AppLocalizations {
|
|||
/// **'No log.txt available!'**
|
||||
String get no_app_logs;
|
||||
|
||||
/// No description provided for @failed.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Failed!'**
|
||||
String get failed;
|
||||
|
||||
/// No description provided for @n_days_ago.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
|
|
|
|||
|
|
@ -440,6 +440,9 @@ class AppLocalizationsAr extends AppLocalizations {
|
|||
@override
|
||||
String get no_app_logs => 'No log.txt available!';
|
||||
|
||||
@override
|
||||
String get failed => 'Failed!';
|
||||
|
||||
@override
|
||||
String n_days_ago(Object days) {
|
||||
return 'منذ $days أيام';
|
||||
|
|
|
|||
|
|
@ -442,6 +442,9 @@ class AppLocalizationsAs extends AppLocalizations {
|
|||
@override
|
||||
String get no_app_logs => 'No log.txt available!';
|
||||
|
||||
@override
|
||||
String get failed => 'Failed!';
|
||||
|
||||
@override
|
||||
String n_days_ago(Object days) {
|
||||
return '$days দিনৰ আগতে';
|
||||
|
|
|
|||
|
|
@ -444,6 +444,9 @@ class AppLocalizationsDe extends AppLocalizations {
|
|||
@override
|
||||
String get no_app_logs => 'No log.txt available!';
|
||||
|
||||
@override
|
||||
String get failed => 'Failed!';
|
||||
|
||||
@override
|
||||
String n_days_ago(Object days) {
|
||||
return 'Vor $days Tagen';
|
||||
|
|
|
|||
|
|
@ -442,6 +442,9 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||
@override
|
||||
String get no_app_logs => 'No log.txt available!';
|
||||
|
||||
@override
|
||||
String get failed => 'Failed!';
|
||||
|
||||
@override
|
||||
String n_days_ago(Object days) {
|
||||
return '$days days ago';
|
||||
|
|
|
|||
|
|
@ -446,6 +446,9 @@ class AppLocalizationsEs extends AppLocalizations {
|
|||
@override
|
||||
String get no_app_logs => 'No log.txt available!';
|
||||
|
||||
@override
|
||||
String get failed => 'Failed!';
|
||||
|
||||
@override
|
||||
String n_days_ago(Object days) {
|
||||
return 'hace $days días';
|
||||
|
|
|
|||
|
|
@ -448,6 +448,9 @@ class AppLocalizationsFr extends AppLocalizations {
|
|||
@override
|
||||
String get no_app_logs => 'No log.txt available!';
|
||||
|
||||
@override
|
||||
String get failed => 'Failed!';
|
||||
|
||||
@override
|
||||
String n_days_ago(Object days) {
|
||||
return 'Il y a $days jours';
|
||||
|
|
|
|||
|
|
@ -442,6 +442,9 @@ class AppLocalizationsHi extends AppLocalizations {
|
|||
@override
|
||||
String get no_app_logs => 'No log.txt available!';
|
||||
|
||||
@override
|
||||
String get failed => 'Failed!';
|
||||
|
||||
@override
|
||||
String n_days_ago(Object days) {
|
||||
return '$days दिन पहले';
|
||||
|
|
|
|||
|
|
@ -446,6 +446,9 @@ class AppLocalizationsId extends AppLocalizations {
|
|||
@override
|
||||
String get no_app_logs => 'No log.txt available!';
|
||||
|
||||
@override
|
||||
String get failed => 'Failed!';
|
||||
|
||||
@override
|
||||
String n_days_ago(Object days) {
|
||||
return '$days Hari yang Lalu';
|
||||
|
|
|
|||
|
|
@ -446,6 +446,9 @@ class AppLocalizationsIt extends AppLocalizations {
|
|||
@override
|
||||
String get no_app_logs => 'No log.txt available!';
|
||||
|
||||
@override
|
||||
String get failed => 'Failed!';
|
||||
|
||||
@override
|
||||
String n_days_ago(Object days) {
|
||||
return '$days giorni fa';
|
||||
|
|
|
|||
|
|
@ -446,6 +446,9 @@ class AppLocalizationsPt extends AppLocalizations {
|
|||
@override
|
||||
String get no_app_logs => 'No log.txt available!';
|
||||
|
||||
@override
|
||||
String get failed => 'Failed!';
|
||||
|
||||
@override
|
||||
String n_days_ago(Object days) {
|
||||
return '$days dias atrás';
|
||||
|
|
|
|||
|
|
@ -447,6 +447,9 @@ class AppLocalizationsRu extends AppLocalizations {
|
|||
@override
|
||||
String get no_app_logs => 'No log.txt available!';
|
||||
|
||||
@override
|
||||
String get failed => 'Failed!';
|
||||
|
||||
@override
|
||||
String n_days_ago(Object days) {
|
||||
return '$days дней назад';
|
||||
|
|
|
|||
|
|
@ -442,6 +442,9 @@ class AppLocalizationsTh extends AppLocalizations {
|
|||
@override
|
||||
String get no_app_logs => 'No log.txt available!';
|
||||
|
||||
@override
|
||||
String get failed => 'Failed!';
|
||||
|
||||
@override
|
||||
String n_days_ago(Object days) {
|
||||
return '$days วันที่แล้ว';
|
||||
|
|
|
|||
|
|
@ -442,6 +442,9 @@ class AppLocalizationsTr extends AppLocalizations {
|
|||
@override
|
||||
String get no_app_logs => 'No log.txt available!';
|
||||
|
||||
@override
|
||||
String get failed => 'Failed!';
|
||||
|
||||
@override
|
||||
String n_days_ago(Object days) {
|
||||
return '$days gün önce';
|
||||
|
|
|
|||
|
|
@ -434,6 +434,9 @@ class AppLocalizationsZh extends AppLocalizations {
|
|||
@override
|
||||
String get no_app_logs => 'No log.txt available!';
|
||||
|
||||
@override
|
||||
String get failed => 'Failed!';
|
||||
|
||||
@override
|
||||
String n_days_ago(Object days) {
|
||||
return '$days天前';
|
||||
|
|
|
|||
|
|
@ -1355,6 +1355,7 @@ mp.register_script_message('call_button_${button.id}_long', button${button.id}lo
|
|||
await subtitlesSearchraggableMenu(
|
||||
context,
|
||||
chapter: widget.episode,
|
||||
isLocal: widget.isLocal,
|
||||
)
|
||||
as ImdbSubtitle?;
|
||||
if (subtitle != null && context.mounted) {
|
||||
|
|
|
|||
|
|
@ -2,17 +2,30 @@ import 'dart:io';
|
|||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:mangayomi/eval/model/m_bridge.dart';
|
||||
import 'package:mangayomi/models/chapter.dart';
|
||||
import 'package:mangayomi/modules/widgets/custom_extended_image_provider.dart';
|
||||
import 'package:mangayomi/modules/widgets/error_text.dart';
|
||||
import 'package:mangayomi/modules/widgets/progress_center.dart';
|
||||
import 'package:mangayomi/providers/l10n_providers.dart';
|
||||
import 'package:mangayomi/providers/storage_provider.dart';
|
||||
import 'package:mangayomi/services/fetch_subtitles.dart';
|
||||
import 'package:mangayomi/services/http/m_client.dart';
|
||||
import 'package:mangayomi/services/http/rhttp/src/model/settings.dart';
|
||||
import 'package:mangayomi/utils/extensions/build_context_extensions.dart';
|
||||
import 'package:mangayomi/utils/extensions/string_extensions.dart';
|
||||
import 'package:mangayomi/utils/log/logger.dart';
|
||||
import 'package:path/path.dart' as path;
|
||||
import 'package:super_sliver_list/super_sliver_list.dart';
|
||||
|
||||
class SubtitlesWidgetSearch extends ConsumerStatefulWidget {
|
||||
final Chapter chapter;
|
||||
const SubtitlesWidgetSearch({required this.chapter, super.key});
|
||||
final bool isLocal;
|
||||
const SubtitlesWidgetSearch({
|
||||
required this.chapter,
|
||||
required this.isLocal,
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
ConsumerState<SubtitlesWidgetSearch> createState() =>
|
||||
|
|
@ -296,6 +309,12 @@ class _SubtitlesWidgetSearchState extends ConsumerState<SubtitlesWidgetSearch> {
|
|||
),
|
||||
],
|
||||
),
|
||||
if (isSubtitles && widget.isLocal)
|
||||
OutlinedButton.icon(
|
||||
onPressed: () async => _downloadSubtitle(index),
|
||||
label: Text(context.l10n.download),
|
||||
icon: Icon(Icons.download_outlined),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
|
|
@ -308,11 +327,71 @@ class _SubtitlesWidgetSearchState extends ConsumerState<SubtitlesWidgetSearch> {
|
|||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _downloadSubtitle(int index) async {
|
||||
botToast(context.l10n.started);
|
||||
try {
|
||||
final subtitle = subtitles![index];
|
||||
final storageProvider = StorageProvider();
|
||||
final chapterDirectory = (await storageProvider.getMangaChapterDirectory(
|
||||
widget.chapter,
|
||||
))!;
|
||||
final subtitleFile = File(
|
||||
path.join(
|
||||
'${chapterDirectory.path}_subtitles',
|
||||
'${subtitle.language}.srt',
|
||||
),
|
||||
);
|
||||
final client = MClient.httpClient(
|
||||
settings: const ClientSettings(
|
||||
throwOnStatusCode: false,
|
||||
tlsSettings: TlsSettings(verifyCertificates: false),
|
||||
),
|
||||
);
|
||||
await subtitleFile.create(recursive: true);
|
||||
final response = await _withRetry(
|
||||
() => client.get(Uri.parse(subtitle.url ?? '')),
|
||||
);
|
||||
if (response.statusCode != 200) {
|
||||
AppLogger.log(
|
||||
'Warning: Failed to download subtitle file: ${subtitle.language}',
|
||||
);
|
||||
return;
|
||||
}
|
||||
AppLogger.log('Subtitle file downloaded: ${subtitle.language}');
|
||||
await subtitleFile.writeAsBytes(response.bodyBytes);
|
||||
if (context.mounted) {
|
||||
botToast(context.l10n.finished(""));
|
||||
}
|
||||
} catch (e) {
|
||||
AppLogger.log("Failed to download subtitle:", logLevel: LogLevel.error);
|
||||
AppLogger.log(e.toString(), logLevel: LogLevel.error);
|
||||
if (context.mounted) {
|
||||
botToast(context.l10n.failed);
|
||||
}
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
Future<T> _withRetry<T>(Future<T> Function() operation) async {
|
||||
int attempts = 0;
|
||||
while (true) {
|
||||
try {
|
||||
attempts++;
|
||||
return await operation();
|
||||
} catch (e) {
|
||||
if (attempts >= 3) {
|
||||
AppLogger.log("Request retries failed", logLevel: LogLevel.error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
subtitlesSearchraggableMenu(
|
||||
BuildContext context, {
|
||||
required Chapter chapter,
|
||||
required bool isLocal,
|
||||
}) async {
|
||||
var padding = MediaQuery.of(context).padding;
|
||||
return await showDialog(
|
||||
|
|
@ -352,7 +431,7 @@ subtitlesSearchraggableMenu(
|
|||
],
|
||||
),
|
||||
),
|
||||
SubtitlesWidgetSearch(chapter: chapter),
|
||||
SubtitlesWidgetSearch(chapter: chapter, isLocal: isLocal),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
|
|||
Loading…
Reference in a new issue