mirror of
https://github.com/kodjodevf/mangayomi.git
synced 2026-03-11 17:25:32 +00:00
Merge branch 'main' into refactor/refactor-extensions-service
This commit is contained in:
commit
9d712654a9
22 changed files with 2430 additions and 957 deletions
|
|
@ -17,6 +17,7 @@ import 'package:mangayomi/eval/model/m_provider.dart';
|
|||
import 'package:mangayomi/eval/javascript/http.dart';
|
||||
import 'package:mangayomi/models/video.dart';
|
||||
import 'package:mangayomi/modules/browse/extension/providers/extension_preferences_providers.dart';
|
||||
import 'package:mangayomi/utils/extensions/string_extensions.dart';
|
||||
import 'package:mangayomi/utils/log/log.dart';
|
||||
|
||||
class $MProvider extends MProvider with $Bridge<MProvider> {
|
||||
|
|
@ -478,15 +479,7 @@ class $MProvider extends MProvider with $Bridge<MProvider> {
|
|||
return $Future.wrap(runtime.evaluateAsync(args[0]!.$reified).then((value) => $String(value.stringResult)));
|
||||
}),
|
||||
'getUrlWithoutDomain' => $Function((_, __, List<$Value?> args) {
|
||||
final uri = Uri.parse(args[0]!.$value.replaceAll(' ', '%20'));
|
||||
String out = uri.path;
|
||||
if (uri.query.isNotEmpty) {
|
||||
out += '?${uri.query}';
|
||||
}
|
||||
if (uri.fragment.isNotEmpty) {
|
||||
out += '#${uri.fragment}';
|
||||
}
|
||||
return $String(out);
|
||||
return $String((args[0]!.$value as String).getUrlWithoutDomain);
|
||||
}),
|
||||
'parseHtml' => $Function((_, __, List<$Value?> args) {
|
||||
final res = MBridge.parsHtml(args[0]!.$reified);
|
||||
|
|
|
|||
|
|
@ -333,5 +333,18 @@
|
|||
"or": "أو",
|
||||
"advanced": "متقدم",
|
||||
"use_native_http_client": "استخدام عميل HTTP الأصلي",
|
||||
"use_native_http_client_info": "يدعم تلقائيًا ميزات المنصة مثل الشبكات الافتراضية الخاصة (VPNs)، ويدعم ميزات HTTP أكثر مثل HTTP/3 ومعالجة إعادة التوجيه المخصصة"
|
||||
"use_native_http_client_info": "يدعم تلقائيًا ميزات المنصة مثل الشبكات الافتراضية الخاصة (VPNs)، ويدعم ميزات HTTP أكثر مثل HTTP/3 ومعالجة إعادة التوجيه المخصصة",
|
||||
"unwatched": "لم يشاهد",
|
||||
"last_watched": "آخر مشاهدة",
|
||||
"unwatched_count": "عدد غير المشاهد",
|
||||
"latest_episode": "الحلقة الأخيرة",
|
||||
"downloaded_episodes": "الحلقات المحملة",
|
||||
"show_continue_watching_buttons": "إظهار أزرار المتابعة",
|
||||
"by_episode_number": "حسب رقم الحلقة",
|
||||
"episode_number": "رقم الحلقة",
|
||||
"total_episodes": "إجمالي الحلقات",
|
||||
"next_episode": "الحلقة التالية",
|
||||
"next_5_episodes": "الحلقات الخمس التالية",
|
||||
"next_10_episodes": "العشر حلقات التالية",
|
||||
"next_25_episodes": "الخمسة وعشرون حلقة التالية"
|
||||
}
|
||||
|
|
@ -10,14 +10,18 @@
|
|||
"filter": "Filter",
|
||||
"downloaded": "Heruntergeladen",
|
||||
"unread": "Ungelesen",
|
||||
"unwatched": "Nicht angeschaut",
|
||||
"started": "Begonnen",
|
||||
"bookmarked": "Markiert",
|
||||
"sort": "Sortieren",
|
||||
"alphabetically": "Alphabetisch",
|
||||
"last_read": "Zuletzt gelesen",
|
||||
"last_watched": "Zuletzt angeschaut",
|
||||
"last_update_check": "Letzte Aktualisierungsprüfung",
|
||||
"unread_count": "Anzahl Ungelesenes",
|
||||
"unread_count": "Ungelesene Anzahl",
|
||||
"unwatched_count": "Ungesehene Anzahl",
|
||||
"latest_chapter": "Letztes Kapitel",
|
||||
"latest_episode": "Letzte Episode",
|
||||
"date_added": "Hinzugefügt am",
|
||||
"display": "Anzeige",
|
||||
"display_mode": "Anzeigemodus",
|
||||
|
|
@ -27,13 +31,15 @@
|
|||
"list": "Liste",
|
||||
"badges": "Abzeichen",
|
||||
"downloaded_chapters": "Heruntergeladene Kapitel",
|
||||
"downloaded_episodes": "Heruntergeladene Episoden",
|
||||
"language": "Sprache",
|
||||
"local_source": "Lokale Quelle",
|
||||
"tabs": "Tabs",
|
||||
"show_category_tabs": "Kategorietabs anzeigen",
|
||||
"show_numbers_of_items": "Artikelanzahl anzeigen",
|
||||
"other": "Andere",
|
||||
"show_continue_reading_buttons": "Weiterlesen-Schaltflächen anzeigen",
|
||||
"show_continue_reading_buttons": "Weiterlesen-Buttons anzeigen",
|
||||
"show_continue_watching_buttons": "Weiterschauen-Buttons anzeigen",
|
||||
"empty_library": "Leere Bibliothek",
|
||||
"search": "Suche...",
|
||||
"no_recent_updates": "Keine kürzlichen Aktualisierungen",
|
||||
|
|
@ -132,9 +138,11 @@
|
|||
"reset": "Zurücksetzen",
|
||||
"by_source": "Nach Quelle",
|
||||
"by_chapter_number": "Nach Kapitelnummer",
|
||||
"by_episode_number": "Nach Episodennummer",
|
||||
"by_upload_date": "Nach Upload-Datum",
|
||||
"source_title": "Quellentitel",
|
||||
"chapter_number": "Kapitelnummer",
|
||||
"episode_number": "Episodennummer",
|
||||
"share": "Teilen",
|
||||
"n_chapters": "{number} Kapitel",
|
||||
"no_description": "Keine Beschreibung",
|
||||
|
|
@ -164,6 +172,7 @@
|
|||
"delete_chapters": "Kapitel löschen?",
|
||||
"default0": "Standard",
|
||||
"total_chapters": "Gesamtkapitel",
|
||||
"total_episodes": "Gesamtepisoden",
|
||||
"import_local_file": "Lokale Datei importieren",
|
||||
"import_files": "Dateien",
|
||||
"nothing_read_recently": "Kürzlich nichts gelesen",
|
||||
|
|
@ -319,6 +328,10 @@
|
|||
"next_5_chapters": "Nächsten 5 Kapitel",
|
||||
"next_10_chapters": "Nächsten 10 Kapitel",
|
||||
"next_25_chapters": "Nächsten 25 Kapitel",
|
||||
"next_episode": "Nächste Episode",
|
||||
"next_5_episodes": "Nächsten 5 Episoden",
|
||||
"next_10_episodes": "Nächsten 10 Episoden",
|
||||
"next_25_episodes": "Nächsten 25 Episoden",
|
||||
"cover_saved": "Titelbild gespeichert",
|
||||
"set_as_cover": "Als Titelbild festlegen",
|
||||
"use_this_as_cover_art": "Dies als Titelbild verwenden?",
|
||||
|
|
|
|||
|
|
@ -10,14 +10,18 @@
|
|||
"filter": "Filter",
|
||||
"downloaded": "Downloaded",
|
||||
"unread": "Unread",
|
||||
"unwatched": "Unwatched",
|
||||
"started": "Started",
|
||||
"bookmarked": "Bookmarked",
|
||||
"sort": "Sort",
|
||||
"alphabetically": "Alphabetically",
|
||||
"last_read": "Last read",
|
||||
"last_watched": "Last watched",
|
||||
"last_update_check": "Last update check",
|
||||
"unread_count": "Unread count",
|
||||
"unwatched_count": "Unwatched count",
|
||||
"latest_chapter": "Latest chapter",
|
||||
"latest_episode": "Latest episode",
|
||||
"date_added": "Date added",
|
||||
"display": "Display",
|
||||
"display_mode": "Display mode",
|
||||
|
|
@ -27,6 +31,7 @@
|
|||
"list": "List",
|
||||
"badges": "Badges",
|
||||
"downloaded_chapters": "Downloaded chapters",
|
||||
"downloaded_episodes": "Downloaded episodes",
|
||||
"language": "Language",
|
||||
"local_source": "Local source",
|
||||
"tabs": "Tabs",
|
||||
|
|
@ -34,6 +39,7 @@
|
|||
"show_numbers_of_items": "Show numbers of items",
|
||||
"other": "Other",
|
||||
"show_continue_reading_buttons": "Show continue reading buttons",
|
||||
"show_continue_watching_buttons": "Show continue watching buttons",
|
||||
"empty_library": "Empty library",
|
||||
"search": "Search...",
|
||||
"no_recent_updates": "No recent updates",
|
||||
|
|
@ -132,9 +138,11 @@
|
|||
"reset": "Reset",
|
||||
"by_source": "By source",
|
||||
"by_chapter_number": "By chapter number",
|
||||
"by_episode_number": "By episode number",
|
||||
"by_upload_date": "By upload date",
|
||||
"source_title": "Source title",
|
||||
"chapter_number": "Chapter number",
|
||||
"episode_number": "Episode number",
|
||||
"share": "Share",
|
||||
"n_chapters": "{number} chapters",
|
||||
"no_description": "No description",
|
||||
|
|
@ -164,6 +172,7 @@
|
|||
"delete_chapters": "Delete Chapter?",
|
||||
"default0": "Default",
|
||||
"total_chapters": "Total Chapters",
|
||||
"total_episodes": "Total episodes",
|
||||
"import_local_file": "Import Local file",
|
||||
"import_files": "Files",
|
||||
"nothing_read_recently": "Nothing read recently",
|
||||
|
|
@ -319,6 +328,10 @@
|
|||
"next_5_chapters": "Next 5 chapters",
|
||||
"next_10_chapters": "Next 10 chapters",
|
||||
"next_25_chapters": "Next 25 chapters",
|
||||
"next_episode": "Next episode",
|
||||
"next_5_episodes": "Next 5 episodes",
|
||||
"next_10_episodes": "Next 10 episodes",
|
||||
"next_25_episodes": "Next 25 episodes",
|
||||
"cover_saved": "Cover saved",
|
||||
"set_as_cover": "Set as cover",
|
||||
"use_this_as_cover_art": "Use this as cover art?",
|
||||
|
|
|
|||
|
|
@ -333,5 +333,18 @@
|
|||
"or": "O",
|
||||
"advanced": "Avanzado",
|
||||
"use_native_http_client": "Utilizar cliente HTTP nativo",
|
||||
"use_native_http_client_info": "admite automáticamente las características de la plataforma como VPNs, admite más características HTTP como HTTP/3 y manejo de redirección personalizada"
|
||||
"use_native_http_client_info": "admite automáticamente las características de la plataforma como VPNs, admite más características HTTP como HTTP/3 y manejo de redirección personalizada",
|
||||
"unwatched": "No visto",
|
||||
"last_watched": "Visto por última vez",
|
||||
"unwatched_count": "Número no visto",
|
||||
"latest_episode": "Último episodio",
|
||||
"downloaded_episodes": "Episodios descargados",
|
||||
"show_continue_watching_buttons": "Mostrar botones de continuar viendo",
|
||||
"by_episode_number": "Por número de episodio",
|
||||
"episode_number": "Número de episodio",
|
||||
"total_episodes": "Total de episodios",
|
||||
"next_episode": "Siguiente episodio",
|
||||
"next_5_episodes": "Siguientes 5 episodios",
|
||||
"next_10_episodes": "Siguientes 10 episodios",
|
||||
"next_25_episodes": "Siguientes 25 episodios"
|
||||
}
|
||||
|
|
@ -333,5 +333,18 @@
|
|||
"or": "O",
|
||||
"advanced": "Avanzado",
|
||||
"use_native_http_client": "Usar cliente HTTP nativo",
|
||||
"use_native_http_client_info": "soporta automáticamente características de la plataforma como VPNs, soporta más características HTTP como HTTP/3 y manejo de redirección personalizado"
|
||||
"use_native_http_client_info": "soporta automáticamente características de la plataforma como VPNs, soporta más características HTTP como HTTP/3 y manejo de redirección personalizado",
|
||||
"unwatched": "No visto",
|
||||
"last_watched": "Visto por última vez",
|
||||
"unwatched_count": "Número no visto",
|
||||
"latest_episode": "Último episodio",
|
||||
"downloaded_episodes": "Episodios descargados",
|
||||
"show_continue_watching_buttons": "Mostrar botones de continuar viendo",
|
||||
"by_episode_number": "Por número de episodio",
|
||||
"episode_number": "Número de episodio",
|
||||
"total_episodes": "Total de episodios",
|
||||
"next_episode": "Siguiente episodio",
|
||||
"next_5_episodes": "Siguientes 5 episodios",
|
||||
"next_10_episodes": "Siguientes 10 episodios",
|
||||
"next_25_episodes": "Siguientes 25 episodios"
|
||||
}
|
||||
|
|
@ -334,5 +334,18 @@
|
|||
"or": "OU",
|
||||
"advanced": "Avancé",
|
||||
"use_native_http_client": "Utiliser le client HTTP natif",
|
||||
"use_native_http_client_info": "Il supporte automatiquement les fonctionnalités de la plateforme telles que les VPN, et prend en charge plus de fonctionnalités HTTP telles que HTTP/3 et la gestion personnalisée des redirections."
|
||||
"use_native_http_client_info": "Il supporte automatiquement les fonctionnalités de la plateforme telles que les VPN, et prend en charge plus de fonctionnalités HTTP telles que HTTP/3 et la gestion personnalisée des redirections.",
|
||||
"unwatched": "Non regardé",
|
||||
"last_watched": "Dernièrement regardé",
|
||||
"unwatched_count": "Nombre non vu",
|
||||
"latest_episode": "Dernier épisode",
|
||||
"downloaded_episodes": "Épisodes téléchargés",
|
||||
"show_continue_watching_buttons": "Afficher les boutons de reprise",
|
||||
"by_episode_number": "Par numéro d'épisode",
|
||||
"episode_number": "Numéro d'épisode",
|
||||
"total_episodes": "Total des épisodes",
|
||||
"next_episode": "Épisode suivant",
|
||||
"next_5_episodes": "5 épisodes suivants",
|
||||
"next_10_episodes": "10 épisodes suivants",
|
||||
"next_25_episodes": "25 épisodes suivants"
|
||||
}
|
||||
|
|
@ -333,5 +333,18 @@
|
|||
"or": "ATAU",
|
||||
"advanced": "Lanjutan",
|
||||
"use_native_http_client": "Gunakan klien http asli",
|
||||
"use_native_http_client_info": "secara otomatis mendukung fitur platform seperti VPN, mendukung lebih banyak fitur HTTP seperti HTTP/3 dan penanganan pengalihan khusus"
|
||||
"use_native_http_client_info": "secara otomatis mendukung fitur platform seperti VPN, mendukung lebih banyak fitur HTTP seperti HTTP/3 dan penanganan pengalihan khusus",
|
||||
"unwatched": "Belum ditonton",
|
||||
"last_watched": "Terakhir ditonton",
|
||||
"unwatched_count": "Jumlah belum ditonton",
|
||||
"latest_episode": "Episode terbaru",
|
||||
"downloaded_episodes": "Episode yang diunduh",
|
||||
"show_continue_watching_buttons": "Tampilkan tombol lanjut menonton",
|
||||
"by_episode_number": "Menurut nomor episode",
|
||||
"episode_number": "Nomor episode",
|
||||
"total_episodes": "Total episode",
|
||||
"next_episode": "Episode berikutnya",
|
||||
"next_5_episodes": "5 episode berikutnya",
|
||||
"next_10_episodes": "10 episode berikutnya",
|
||||
"next_25_episodes": "25 episode berikutnya"
|
||||
}
|
||||
|
|
@ -333,5 +333,18 @@
|
|||
"or": "O",
|
||||
"advanced": "Avanzate",
|
||||
"use_native_http_client": "Usa il client HTTP nativo",
|
||||
"use_native_http_client_info": "Supporta automaticamente le funzionalità della piattaforma come le VPN, supporta più funzionalità HTTP come HTTP/3 e la gestione dei reindirizzamenti personalizzati."
|
||||
"use_native_http_client_info": "Supporta automaticamente le funzionalità della piattaforma come le VPN, supporta più funzionalità HTTP come HTTP/3 e la gestione dei reindirizzamenti personalizzati.",
|
||||
"unwatched": "Non guardato",
|
||||
"last_watched": "Ultima visione",
|
||||
"unwatched_count": "Conteggio non guardati",
|
||||
"latest_episode": "Ultimo episodio",
|
||||
"downloaded_episodes": "Episodi scaricati",
|
||||
"show_continue_watching_buttons": "Mostra pulsanti continua a guardare",
|
||||
"by_episode_number": "Per numero di episodio",
|
||||
"episode_number": "Numero dell'episodio",
|
||||
"total_episodes": "Episodi totali",
|
||||
"next_episode": "Prossimo episodio",
|
||||
"next_5_episodes": "Prossimi 5 episodi",
|
||||
"next_10_episodes": "Prossimi 10 episodi",
|
||||
"next_25_episodes": "Prossimi 25 episodi"
|
||||
}
|
||||
|
|
@ -333,5 +333,18 @@
|
|||
"or": "OU",
|
||||
"advanced": "Avançado",
|
||||
"use_native_http_client": "Usar cliente HTTP nativo",
|
||||
"use_native_http_client_info": "ele suporta automaticamente recursos da plataforma, como VPNs, suporta mais recursos HTTP, como HTTP/3 e manuseio de redirecionamentos personalizados"
|
||||
"use_native_http_client_info": "ele suporta automaticamente recursos da plataforma, como VPNs, suporta mais recursos HTTP, como HTTP/3 e manuseio de redirecionamentos personalizados",
|
||||
"unwatched": "Não assistido",
|
||||
"last_watched": "Último assistido",
|
||||
"unwatched_count": "Contagem não assistidos",
|
||||
"latest_episode": "Último episódio",
|
||||
"downloaded_episodes": "Episódios baixados",
|
||||
"show_continue_watching_buttons": "Mostrar botões para continuar assistindo",
|
||||
"by_episode_number": "Por número do episódio",
|
||||
"episode_number": "Número do episódio",
|
||||
"total_episodes": "Total de episódios",
|
||||
"next_episode": "Próximo episódio",
|
||||
"next_5_episodes": "Próximos 5 episódios",
|
||||
"next_10_episodes": "Próximos 10 episódios",
|
||||
"next_25_episodes": "Próximos 25 episódios"
|
||||
}
|
||||
|
|
@ -333,5 +333,18 @@
|
|||
"or": "OU",
|
||||
"advanced": "Avançado",
|
||||
"use_native_http_client": "Usar cliente HTTP nativo",
|
||||
"use_native_http_client_info": "ele suporta automaticamente recursos da plataforma como VPNs, suporta mais recursos HTTP, como HTTP/3 e manuseio personalizado de redirecionamento"
|
||||
"use_native_http_client_info": "ele suporta automaticamente recursos da plataforma como VPNs, suporta mais recursos HTTP, como HTTP/3 e manuseio personalizado de redirecionamento",
|
||||
"unwatched": "Não assistido",
|
||||
"last_watched": "Último assistido",
|
||||
"unwatched_count": "Contagem não assistidos",
|
||||
"latest_episode": "Último episódio",
|
||||
"downloaded_episodes": "Episódios baixados",
|
||||
"show_continue_watching_buttons": "Mostrar botões para continuar assistindo",
|
||||
"by_episode_number": "Por número do episódio",
|
||||
"episode_number": "Número do episódio",
|
||||
"total_episodes": "Total de episódios",
|
||||
"next_episode": "Próximo episódio",
|
||||
"next_5_episodes": "Próximos 5 episódios",
|
||||
"next_10_episodes": "Próximos 10 episódios",
|
||||
"next_25_episodes": "Próximos 25 episódios"
|
||||
}
|
||||
|
|
@ -333,5 +333,18 @@
|
|||
"or": "ИЛИ",
|
||||
"advanced": "Продвинутые",
|
||||
"use_native_http_client": "Использовать нативный HTTP-клиент",
|
||||
"use_native_http_client_info": "он автоматически поддерживает функции платформы, такие как VPN, поддерживает больше функций HTTP, таких как HTTP/3 и пользовательская обработка перенаправлений"
|
||||
"use_native_http_client_info": "он автоматически поддерживает функции платформы, такие как VPN, поддерживает больше функций HTTP, таких как HTTP/3 и пользовательская обработка перенаправлений",
|
||||
"unwatched": "Непросмотренный",
|
||||
"last_watched": "Последний просмотр",
|
||||
"unwatched_count": "Количество непросмотренных",
|
||||
"latest_episode": "Последний эпизод",
|
||||
"downloaded_episodes": "Загруженные эпизоды",
|
||||
"show_continue_watching_buttons": "Показать кнопки продолжения просмотра",
|
||||
"by_episode_number": "По номеру эпизода",
|
||||
"episode_number": "Номер эпизода",
|
||||
"total_episodes": "Общее количество эпизодов",
|
||||
"next_episode": "Следующий эпизод",
|
||||
"next_5_episodes": "Следующие 5 эпизодов",
|
||||
"next_10_episodes": "Следующие 10 эпизодов",
|
||||
"next_25_episodes": "Следующие 25 эпизодов"
|
||||
}
|
||||
|
|
@ -335,5 +335,18 @@
|
|||
"or": "หรือ",
|
||||
"advanced": "ขั้นสูง",
|
||||
"use_native_http_client": "ใช้ไคลเอนต์ HTTP พื้นเมือง",
|
||||
"use_native_http_client_info": "รองรับฟีเจอร์ของแพลตฟอร์มโดยอัตโนมัติ เช่น VPNs รองรับฟีเจอร์ HTTP มากขึ้น เช่น HTTP/3 และการจัดการการเปลี่ยนเส้นทางที่กำหนดเอง"
|
||||
"use_native_http_client_info": "รองรับฟีเจอร์ของแพลตฟอร์มโดยอัตโนมัติ เช่น VPNs รองรับฟีเจอร์ HTTP มากขึ้น เช่น HTTP/3 และการจัดการการเปลี่ยนเส้นทางที่กำหนดเอง",
|
||||
"unwatched": "ยังไม่ได้ดู",
|
||||
"last_watched": "ดูครั้งสุดท้าย",
|
||||
"unwatched_count": "จำนวนที่ยังไม่ได้ดู",
|
||||
"latest_episode": "ตอนล่าสุด",
|
||||
"downloaded_episodes": "ตอนที่ดาวน์โหลด",
|
||||
"show_continue_watching_buttons": "แสดงปุ่มดูต่อไป",
|
||||
"by_episode_number": "ตามหมายเลขตอน",
|
||||
"episode_number": "หมายเลขตอน",
|
||||
"total_episodes": "รวมตอน",
|
||||
"next_episode": "ตอนถัดไป",
|
||||
"next_5_episodes": "5 ตอนถัดไป",
|
||||
"next_10_episodes": "10 ตอนถัดไป",
|
||||
"next_25_episodes": "25 ตอนถัดไป"
|
||||
}
|
||||
|
|
@ -333,5 +333,18 @@
|
|||
"or": "VEYA",
|
||||
"advanced": "Gelişmiş",
|
||||
"use_native_http_client": "Yerel http istemcisini kullan",
|
||||
"use_native_http_client_info": "otomatik olarak VPN'ler gibi platform özelliklerini destekler, HTTP/3 gibi daha fazla HTTP özelliğini ve özel yönlendirme işlemlerini destekler"
|
||||
"use_native_http_client_info": "otomatik olarak VPN'ler gibi platform özelliklerini destekler, HTTP/3 gibi daha fazla HTTP özelliğini ve özel yönlendirme işlemlerini destekler",
|
||||
"unwatched": "İzlenmemiş",
|
||||
"last_watched": "Son İzlenen",
|
||||
"unwatched_count": "İzlenmemiş Sayısı",
|
||||
"latest_episode": "Son Bölüm",
|
||||
"downloaded_episodes": "İndirilen Bölümler",
|
||||
"show_continue_watching_buttons": "İzlemeye Devam Et Düğmelerini Göster",
|
||||
"by_episode_number": "Bölüm Sayısına Göre",
|
||||
"episode_number": "Bölüm Sayısı",
|
||||
"total_episodes": "Toplam Bölümler",
|
||||
"next_episode": "Sonraki Bölüm",
|
||||
"next_5_episodes": "Sonraki 5 Bölüm",
|
||||
"next_10_episodes": "Sonraki 10 Bölüm",
|
||||
"next_25_episodes": "Sonraki 25 Bölüm"
|
||||
}
|
||||
|
|
@ -335,5 +335,18 @@
|
|||
"or": "或",
|
||||
"advanced": "高级",
|
||||
"use_native_http_client": "使用本地 HTTP 客户端",
|
||||
"use_native_http_client_info": "它自动支持平台特性,如 VPN,支持更多 HTTP 特性,如 HTTP/3 和自定义重定向处理"
|
||||
"use_native_http_client_info": "它自动支持平台特性,如 VPN,支持更多 HTTP 特性,如 HTTP/3 和自定义重定向处理",
|
||||
"unwatched": "未观看",
|
||||
"last_watched": "上次观看",
|
||||
"unwatched_count": "未观看计数",
|
||||
"latest_episode": "最新一集",
|
||||
"downloaded_episodes": "下载的剧集",
|
||||
"show_continue_watching_buttons": "显示继续观看按钮",
|
||||
"by_episode_number": "按集数",
|
||||
"episode_number": "集数",
|
||||
"total_episodes": "总集数",
|
||||
"next_episode": "下一集",
|
||||
"next_5_episodes": "接下来的 5 集",
|
||||
"next_10_episodes": "接下来的 10 集",
|
||||
"next_25_episodes": "接下来的 25 集"
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -227,6 +227,7 @@ class _MangaDetailsViewState extends ConsumerState<MangaDetailsView> {
|
|||
},
|
||||
sourceExist: widget.sourceExist,
|
||||
checkForUpdate: widget.checkForUpdate,
|
||||
isManga: widget.manga.isManga!,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -2,7 +2,7 @@ import 'dart:io';
|
|||
import 'package:file_picker/file_picker.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:mangayomi/eval/model/m_bridge.dart';
|
||||
import 'package:mangayomi/eval/dart/model/m_bridge.dart';
|
||||
import 'package:mangayomi/modules/manga/detail/widgets/chapter_filter_list_tile_widget.dart';
|
||||
import 'package:mangayomi/modules/more/backup_and_restore/providers/auto_backup.dart';
|
||||
import 'package:mangayomi/modules/more/backup_and_restore/providers/backup.dart';
|
||||
|
|
@ -17,7 +17,8 @@ class BackupAndRestore extends ConsumerWidget {
|
|||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final backupFrequency = ref.watch(backupFrequencyStateProvider);
|
||||
final backupFrequencyOptions = ref.watch(backupFrequencyOptionsStateProvider);
|
||||
final backupFrequencyOptions =
|
||||
ref.watch(backupFrequencyOptionsStateProvider);
|
||||
final autoBackupLocation = ref.watch(autoBackupLocationStateProvider);
|
||||
ref.read(autoBackupLocationStateProvider.notifier).refresh();
|
||||
|
||||
|
|
@ -73,24 +74,32 @@ class BackupAndRestore extends ConsumerWidget {
|
|||
},
|
||||
child: Text(
|
||||
l10n.cancel,
|
||||
style: TextStyle(color: context.primaryColor),
|
||||
style: TextStyle(
|
||||
color: context.primaryColor),
|
||||
)),
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
String? result;
|
||||
if (Platform.isIOS) {
|
||||
result = (await StorageProvider().getIosBackupDirectory())!.path;
|
||||
result = (await StorageProvider()
|
||||
.getIosBackupDirectory())!
|
||||
.path;
|
||||
} else {
|
||||
result = await FilePicker.platform.getDirectoryPath();
|
||||
result = await FilePicker.platform
|
||||
.getDirectoryPath();
|
||||
}
|
||||
|
||||
if (result != null && context.mounted) {
|
||||
ref.watch(doBackUpProvider(list: indexList, path: result, context: context));
|
||||
ref.watch(doBackUpProvider(
|
||||
list: indexList,
|
||||
path: result,
|
||||
context: context));
|
||||
}
|
||||
},
|
||||
child: Text(
|
||||
l10n.ok,
|
||||
style: TextStyle(color: context.primaryColor),
|
||||
style: TextStyle(
|
||||
color: context.primaryColor),
|
||||
)),
|
||||
],
|
||||
)
|
||||
|
|
@ -120,12 +129,15 @@ class BackupAndRestore extends ConsumerWidget {
|
|||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Icon(Icons.info_outline_rounded, color: context.secondaryColor),
|
||||
Icon(Icons.info_outline_rounded,
|
||||
color: context.secondaryColor),
|
||||
],
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 5),
|
||||
child: Text(l10n.restore_backup_warning_title),
|
||||
padding:
|
||||
const EdgeInsets.symmetric(vertical: 5),
|
||||
child:
|
||||
Text(l10n.restore_backup_warning_title),
|
||||
),
|
||||
],
|
||||
)),
|
||||
|
|
@ -139,16 +151,22 @@ class BackupAndRestore extends ConsumerWidget {
|
|||
},
|
||||
child: Text(
|
||||
l10n.cancel,
|
||||
style: TextStyle(color: context.primaryColor),
|
||||
style:
|
||||
TextStyle(color: context.primaryColor),
|
||||
)),
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
try {
|
||||
FilePickerResult? result =
|
||||
await FilePicker.platform.pickFiles(allowMultiple: false);
|
||||
await FilePicker.platform
|
||||
.pickFiles(allowMultiple: false,
|
||||
type: FileType.custom,
|
||||
allowedExtensions: ["backup"]);
|
||||
|
||||
if (result != null && context.mounted) {
|
||||
ref.watch(doRestoreProvider(path: result.files.first.path!, context: context));
|
||||
ref.watch(doRestoreProvider(
|
||||
path: result.files.first.path!,
|
||||
context: context));
|
||||
}
|
||||
if (!context.mounted) return;
|
||||
Navigator.pop(context);
|
||||
|
|
@ -159,7 +177,8 @@ class BackupAndRestore extends ConsumerWidget {
|
|||
},
|
||||
child: Text(
|
||||
l10n.ok,
|
||||
style: TextStyle(color: context.primaryColor),
|
||||
style:
|
||||
TextStyle(color: context.primaryColor),
|
||||
)),
|
||||
],
|
||||
)
|
||||
|
|
@ -177,7 +196,9 @@ class BackupAndRestore extends ConsumerWidget {
|
|||
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 20),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(l10n.automatic_backups, style: TextStyle(fontSize: 13, color: context.primaryColor)),
|
||||
Text(l10n.automatic_backups,
|
||||
style:
|
||||
TextStyle(fontSize: 13, color: context.primaryColor)),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
@ -201,7 +222,10 @@ class BackupAndRestore extends ConsumerWidget {
|
|||
value: index,
|
||||
groupValue: backupFrequency,
|
||||
onChanged: (value) {
|
||||
ref.read(backupFrequencyStateProvider.notifier).set(value!);
|
||||
ref
|
||||
.read(backupFrequencyStateProvider
|
||||
.notifier)
|
||||
.set(value!);
|
||||
Navigator.pop(context);
|
||||
},
|
||||
title: Row(
|
||||
|
|
@ -220,7 +244,8 @@ class BackupAndRestore extends ConsumerWidget {
|
|||
},
|
||||
child: Text(
|
||||
l10n.cancel,
|
||||
style: TextStyle(color: context.primaryColor),
|
||||
style:
|
||||
TextStyle(color: context.primaryColor),
|
||||
)),
|
||||
],
|
||||
)
|
||||
|
|
@ -240,12 +265,16 @@ class BackupAndRestore extends ConsumerWidget {
|
|||
String? result = await FilePicker.platform.getDirectoryPath();
|
||||
|
||||
if (result != null) {
|
||||
ref.read(autoBackupLocationStateProvider.notifier).set(result);
|
||||
ref
|
||||
.read(autoBackupLocationStateProvider.notifier)
|
||||
.set(result);
|
||||
}
|
||||
},
|
||||
title: Text(l10n.backup_location),
|
||||
subtitle: Text(
|
||||
autoBackupLocation.$2.isEmpty ? autoBackupLocation.$1 : autoBackupLocation.$2,
|
||||
autoBackupLocation.$2.isEmpty
|
||||
? autoBackupLocation.$1
|
||||
: autoBackupLocation.$2,
|
||||
style: TextStyle(fontSize: 11, color: context.secondaryColor),
|
||||
),
|
||||
),
|
||||
|
|
@ -295,16 +324,22 @@ class BackupAndRestore extends ConsumerWidget {
|
|||
},
|
||||
child: Text(
|
||||
l10n.cancel,
|
||||
style: TextStyle(color: context.primaryColor),
|
||||
style: TextStyle(
|
||||
color: context.primaryColor),
|
||||
)),
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
ref.read(backupFrequencyOptionsStateProvider.notifier).set(indexList);
|
||||
ref
|
||||
.read(
|
||||
backupFrequencyOptionsStateProvider
|
||||
.notifier)
|
||||
.set(indexList);
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: Text(
|
||||
l10n.ok,
|
||||
style: TextStyle(color: context.primaryColor),
|
||||
style: TextStyle(
|
||||
color: context.primaryColor),
|
||||
)),
|
||||
],
|
||||
)
|
||||
|
|
@ -325,12 +360,14 @@ class BackupAndRestore extends ConsumerWidget {
|
|||
padding: const EdgeInsets.only(bottom: 8),
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(Icons.info_outline_rounded, color: context.secondaryColor),
|
||||
Icon(Icons.info_outline_rounded,
|
||||
color: context.secondaryColor),
|
||||
],
|
||||
),
|
||||
),
|
||||
subtitle: Text(l10n.backup_and_restore_warning_info,
|
||||
style: TextStyle(fontSize: 11, color: context.secondaryColor)),
|
||||
style:
|
||||
TextStyle(fontSize: 11, color: context.secondaryColor)),
|
||||
)
|
||||
],
|
||||
),
|
||||
|
|
@ -354,5 +391,12 @@ List<String> _getList(BuildContext context) {
|
|||
|
||||
List<String> _getBackupFrequencyList(BuildContext context) {
|
||||
final l10n = l10nLocalizations(context)!;
|
||||
return [l10n.off, l10n.every_6_hours, l10n.every_12_hours, l10n.daily, l10n.every_2_days, l10n.weekly];
|
||||
return [
|
||||
l10n.off,
|
||||
l10n.every_6_hours,
|
||||
l10n.every_12_hours,
|
||||
l10n.daily,
|
||||
l10n.every_2_days,
|
||||
l10n.weekly
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
import 'package:desktop_webview_window/desktop_webview_window.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
|
@ -22,15 +23,16 @@ class MangaWebView extends ConsumerStatefulWidget {
|
|||
}
|
||||
|
||||
class _MangaWebViewState extends ConsumerState<MangaWebView> {
|
||||
late final MyInAppBrowser browser;
|
||||
double _progress = 0;
|
||||
bool isNotDesktop = false;
|
||||
bool isNotWebviewWindow = false;
|
||||
@override
|
||||
void initState() {
|
||||
if (Platform.isLinux) {
|
||||
if (Platform.isLinux || Platform.isWindows) {
|
||||
_runWebViewDesktop();
|
||||
} else {
|
||||
setState(() {
|
||||
isNotDesktop = true;
|
||||
isNotWebviewWindow = true;
|
||||
});
|
||||
}
|
||||
super.initState();
|
||||
|
|
@ -38,23 +40,59 @@ class _MangaWebViewState extends ConsumerState<MangaWebView> {
|
|||
|
||||
Webview? _desktopWebview;
|
||||
_runWebViewDesktop() async {
|
||||
_desktopWebview = await WebviewWindow.create();
|
||||
if (Platform.isLinux) {
|
||||
_desktopWebview = await WebviewWindow.create();
|
||||
|
||||
final timer = Timer.periodic(const Duration(seconds: 1), (timer) async {
|
||||
try {
|
||||
final cookieList = await _desktopWebview!.getAllCookies();
|
||||
final ua = await _desktopWebview!.evaluateJavaScript("navigator.userAgent") ?? "";
|
||||
final cookie = cookieList.map((e) => "${e.name}=${e.value}").join(";");
|
||||
await MClient.setCookie(_url, ua, null, cookie: cookie);
|
||||
} catch (_) {}
|
||||
});
|
||||
_desktopWebview!
|
||||
..setBrightness(Brightness.dark)
|
||||
..launch(widget.url)
|
||||
..onClose.whenComplete(() {
|
||||
timer.cancel();
|
||||
Navigator.pop(context);
|
||||
final timer = Timer.periodic(const Duration(seconds: 1), (timer) async {
|
||||
try {
|
||||
final cookieList = await _desktopWebview!.getAllCookies();
|
||||
final ua = await _desktopWebview!
|
||||
.evaluateJavaScript("navigator.userAgent") ??
|
||||
"";
|
||||
final cookie =
|
||||
cookieList.map((e) => "${e.name}=${e.value}").join(";");
|
||||
await MClient.setCookie(_url, ua, null, cookie: cookie);
|
||||
} catch (_) {}
|
||||
});
|
||||
_desktopWebview!
|
||||
..setBrightness(Brightness.dark)
|
||||
..launch(widget.url)
|
||||
..onClose.whenComplete(() {
|
||||
timer.cancel();
|
||||
Navigator.pop(context);
|
||||
});
|
||||
} else {
|
||||
browser = MyInAppBrowser(
|
||||
context: context,
|
||||
controller: (controller) {
|
||||
_webViewController = controller;
|
||||
},
|
||||
onProgress: (progress) async {
|
||||
final canGoback = await _webViewController?.canGoBack();
|
||||
final canGoForward = await _webViewController?.canGoForward();
|
||||
final title = await _webViewController?.getTitle();
|
||||
final url = await _webViewController?.getUrl();
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_progress = progress / 100;
|
||||
_url = url.toString();
|
||||
_title = title!;
|
||||
_canGoback = canGoback ?? false;
|
||||
_canGoForward = canGoForward ?? false;
|
||||
});
|
||||
}
|
||||
},
|
||||
);
|
||||
await browser.openUrlRequest(
|
||||
urlRequest: URLRequest(url: WebUri(widget.url)),
|
||||
settings: InAppBrowserClassSettings(
|
||||
browserSettings: InAppBrowserSettings(
|
||||
presentationStyle: ModalPresentationStyle.POPOVER),
|
||||
webViewSettings: InAppWebViewSettings(
|
||||
isInspectable: kDebugMode, useShouldOverrideUrlLoading: true),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
InAppWebViewController? _webViewController;
|
||||
|
|
@ -65,16 +103,19 @@ class _MangaWebViewState extends ConsumerState<MangaWebView> {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final l10n = l10nLocalizations(context);
|
||||
return !isNotDesktop
|
||||
return (!isNotWebviewWindow && Platform.isLinux)
|
||||
? Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(
|
||||
_title,
|
||||
style: const TextStyle(overflow: TextOverflow.ellipsis, fontWeight: FontWeight.bold),
|
||||
style: const TextStyle(
|
||||
overflow: TextOverflow.ellipsis,
|
||||
fontWeight: FontWeight.bold),
|
||||
),
|
||||
leading: IconButton(
|
||||
onPressed: () {
|
||||
_desktopWebview!.close();
|
||||
|
||||
Navigator.pop(context);
|
||||
},
|
||||
icon: const Icon(Icons.close)),
|
||||
|
|
@ -103,21 +144,32 @@ class _MangaWebViewState extends ConsumerState<MangaWebView> {
|
|||
dense: true,
|
||||
subtitle: Text(
|
||||
_url,
|
||||
style: const TextStyle(fontSize: 10, overflow: TextOverflow.ellipsis),
|
||||
style: const TextStyle(
|
||||
fontSize: 10,
|
||||
overflow: TextOverflow.ellipsis),
|
||||
),
|
||||
title: Text(
|
||||
_title,
|
||||
style: const TextStyle(overflow: TextOverflow.ellipsis, fontWeight: FontWeight.bold),
|
||||
style: const TextStyle(
|
||||
overflow: TextOverflow.ellipsis,
|
||||
fontWeight: FontWeight.bold),
|
||||
),
|
||||
leading: IconButton(
|
||||
onPressed: () {
|
||||
if (Platform.isWindows) {
|
||||
if (browser.isOpened()) {
|
||||
browser.close();
|
||||
browser.dispose();
|
||||
}
|
||||
}
|
||||
Navigator.pop(context);
|
||||
},
|
||||
icon: const Icon(Icons.close)),
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
icon: Icon(Icons.arrow_back, color: _canGoback ? null : Colors.grey),
|
||||
icon: Icon(Icons.arrow_back,
|
||||
color: _canGoback ? null : Colors.grey),
|
||||
onPressed: _canGoback
|
||||
? () {
|
||||
_webViewController?.goBack();
|
||||
|
|
@ -125,7 +177,8 @@ class _MangaWebViewState extends ConsumerState<MangaWebView> {
|
|||
: null,
|
||||
),
|
||||
IconButton(
|
||||
icon: Icon(Icons.arrow_forward, color: _canGoForward ? null : Colors.grey),
|
||||
icon: Icon(Icons.arrow_forward,
|
||||
color: _canGoForward ? null : Colors.grey),
|
||||
onPressed: _canGoForward
|
||||
? () {
|
||||
_webViewController?.goForward();
|
||||
|
|
@ -136,10 +189,15 @@ class _MangaWebViewState extends ConsumerState<MangaWebView> {
|
|||
popUpAnimationStyle: popupAnimationStyle,
|
||||
itemBuilder: (context) {
|
||||
return [
|
||||
PopupMenuItem<int>(value: 0, child: Text(l10n!.refresh)),
|
||||
PopupMenuItem<int>(value: 1, child: Text(l10n.share)),
|
||||
PopupMenuItem<int>(value: 2, child: Text(l10n.open_in_browser)),
|
||||
PopupMenuItem<int>(value: 3, child: Text(l10n.clear_cookie)),
|
||||
PopupMenuItem<int>(
|
||||
value: 0, child: Text(l10n!.refresh)),
|
||||
PopupMenuItem<int>(
|
||||
value: 1, child: Text(l10n.share)),
|
||||
PopupMenuItem<int>(
|
||||
value: 2,
|
||||
child: Text(l10n.open_in_browser)),
|
||||
PopupMenuItem<int>(
|
||||
value: 3, child: Text(l10n.clear_cookie)),
|
||||
];
|
||||
},
|
||||
onSelected: (value) async {
|
||||
|
|
@ -148,7 +206,8 @@ class _MangaWebViewState extends ConsumerState<MangaWebView> {
|
|||
} else if (value == 1) {
|
||||
Share.share(_url);
|
||||
} else if (value == 2) {
|
||||
await InAppBrowser.openWithSystemBrowser(url: WebUri(_url));
|
||||
await InAppBrowser.openWithSystemBrowser(
|
||||
url: WebUri(_url));
|
||||
} else if (value == 3) {
|
||||
CookieManager.instance().deleteAllCookies();
|
||||
MClient.deleteAllCookies(_url);
|
||||
|
|
@ -157,67 +216,78 @@ class _MangaWebViewState extends ConsumerState<MangaWebView> {
|
|||
],
|
||||
),
|
||||
),
|
||||
_progress < 1.0 ? LinearProgressIndicator(value: _progress) : Container(),
|
||||
Expanded(
|
||||
child: InAppWebView(
|
||||
webViewEnvironment: webViewEnvironment,
|
||||
onWebViewCreated: (controller) async {
|
||||
_webViewController = controller;
|
||||
},
|
||||
onLoadStart: (controller, url) async {
|
||||
setState(() {
|
||||
_url = url.toString();
|
||||
});
|
||||
},
|
||||
shouldOverrideUrlLoading: (controller, navigationAction) async {
|
||||
var uri = navigationAction.request.url!;
|
||||
|
||||
if (!["http", "https", "file", "chrome", "data", "javascript", "about"]
|
||||
.contains(uri.scheme)) {
|
||||
if (await canLaunchUrl(uri)) {
|
||||
// Launch the App
|
||||
await launchUrl(
|
||||
uri,
|
||||
);
|
||||
// and cancel the request
|
||||
return NavigationActionPolicy.CANCEL;
|
||||
_progress < 1.0
|
||||
? LinearProgressIndicator(value: _progress)
|
||||
: Container(),
|
||||
if (!Platform.isWindows)
|
||||
Expanded(
|
||||
child: InAppWebView(
|
||||
webViewEnvironment: webViewEnvironment,
|
||||
onWebViewCreated: (controller) async {
|
||||
_webViewController = controller;
|
||||
},
|
||||
onLoadStart: (controller, url) async {
|
||||
setState(() {
|
||||
_url = url.toString();
|
||||
});
|
||||
},
|
||||
shouldOverrideUrlLoading:
|
||||
(controller, navigationAction) async {
|
||||
var uri = navigationAction.request.url!;
|
||||
if (![
|
||||
"http",
|
||||
"https",
|
||||
"file",
|
||||
"chrome",
|
||||
"data",
|
||||
"javascript",
|
||||
"about"
|
||||
].contains(uri.scheme)) {
|
||||
if (await canLaunchUrl(uri)) {
|
||||
await launchUrl(uri);
|
||||
return NavigationActionPolicy.CANCEL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NavigationActionPolicy.ALLOW;
|
||||
},
|
||||
onLoadStop: (controller, url) async {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_url = url.toString();
|
||||
});
|
||||
}
|
||||
},
|
||||
onProgressChanged: (controller, progress) async {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_progress = progress / 100;
|
||||
});
|
||||
}
|
||||
},
|
||||
onUpdateVisitedHistory: (controller, url, isReload) async {
|
||||
final ua = await controller.evaluateJavascript(source: "navigator.userAgent") ?? "";
|
||||
await MClient.setCookie(url.toString(), ua, controller);
|
||||
final canGoback = await controller.canGoBack();
|
||||
final canGoForward = await controller.canGoForward();
|
||||
final title = await controller.getTitle();
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_url = url.toString();
|
||||
_title = title!;
|
||||
_canGoback = canGoback;
|
||||
_canGoForward = canGoForward;
|
||||
});
|
||||
}
|
||||
},
|
||||
initialUrlRequest: URLRequest(url: WebUri(widget.url)),
|
||||
return NavigationActionPolicy.ALLOW;
|
||||
},
|
||||
onLoadStop: (controller, url) async {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_url = url.toString();
|
||||
});
|
||||
}
|
||||
},
|
||||
onProgressChanged: (controller, progress) async {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_progress = progress / 100;
|
||||
});
|
||||
}
|
||||
},
|
||||
onUpdateVisitedHistory:
|
||||
(controller, url, isReload) async {
|
||||
final ua = await controller.evaluateJavascript(
|
||||
source: "navigator.userAgent") ??
|
||||
"";
|
||||
await MClient.setCookie(
|
||||
url.toString(), ua, controller);
|
||||
final canGoback = await controller.canGoBack();
|
||||
final canGoForward =
|
||||
await controller.canGoForward();
|
||||
final title = await controller.getTitle();
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_url = url.toString();
|
||||
_title = title!;
|
||||
_canGoback = canGoback;
|
||||
_canGoForward = canGoForward;
|
||||
});
|
||||
}
|
||||
},
|
||||
initialUrlRequest:
|
||||
URLRequest(url: WebUri(widget.url)),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
@ -225,3 +295,53 @@ class _MangaWebViewState extends ConsumerState<MangaWebView> {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
class MyInAppBrowser extends InAppBrowser {
|
||||
BuildContext context;
|
||||
void Function(InAppWebViewController) controller;
|
||||
void Function(int) onProgress;
|
||||
MyInAppBrowser(
|
||||
{required this.context,
|
||||
required this.controller,
|
||||
required this.onProgress})
|
||||
: super(webViewEnvironment: webViewEnvironment);
|
||||
|
||||
@override
|
||||
Future onBrowserCreated() async {
|
||||
controller.call(webViewController!);
|
||||
}
|
||||
|
||||
@override
|
||||
void onProgressChanged(progress) {
|
||||
onProgress.call(progress);
|
||||
}
|
||||
|
||||
@override
|
||||
void onExit() {
|
||||
Navigator.pop(context);
|
||||
}
|
||||
|
||||
@override
|
||||
void onLoadStop(url) async {
|
||||
if (webViewController != null) {
|
||||
final ua = await webViewController!
|
||||
.evaluateJavascript(source: "navigator.userAgent") ??
|
||||
"";
|
||||
await MClient.setCookie(url.toString(), ua, webViewController);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<NavigationActionPolicy> shouldOverrideUrlLoading(
|
||||
navigationAction) async {
|
||||
var uri = navigationAction.request.url!;
|
||||
if (!["http", "https", "file", "chrome", "data", "javascript", "about"]
|
||||
.contains(uri.scheme)) {
|
||||
if (await canLaunchUrl(uri)) {
|
||||
await launchUrl(uri);
|
||||
return NavigationActionPolicy.CANCEL;
|
||||
}
|
||||
}
|
||||
return NavigationActionPolicy.ALLOW;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,6 +40,18 @@ extension StringExtensions on String {
|
|||
return replaceAll(RegExp(r'[\\/:*?"<>|\0]|(^CON$|^PRN$|^AUX$|^NUL$|^COM[1-9]$|^LPT[1-9]$)'), source);
|
||||
}
|
||||
|
||||
String get getUrlWithoutDomain {
|
||||
final uri = Uri.parse(replaceAll(' ', '%20'));
|
||||
String out = uri.path;
|
||||
if (uri.query.isNotEmpty) {
|
||||
out += '?${uri.query}';
|
||||
}
|
||||
if (uri.fragment.isNotEmpty) {
|
||||
out += '#${uri.fragment}';
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
bool isMediaVideo() {
|
||||
return ["3gp", "avi", "mpg", "mpeg", "webm", "ogg", "flv", "m4v", "mvp", "mp4", "wmv", "mkv", "mov"]
|
||||
.any((extension) => toLowerCase().endsWith(extension));
|
||||
|
|
|
|||
Loading…
Reference in a new issue