From 69b82617d24fe526b80b723101a77c23311dced3 Mon Sep 17 00:00:00 2001 From: Darkeudo <86541891+Darkeudo@users.noreply.github.com> Date: Sun, 8 Feb 2026 04:54:01 -0500 Subject: [PATCH 01/16] This PR introduces local private notes for anime/manga entries, improves backup and restore reliability, and fixes the Linux desktop icon visibility issue. (#88) * feat: implement Private Review with local storage * Fix: Icon App Dock Gnome * Feauture: add backup notes private and restore desktop * Feauture: add backup notes manga * Fix: Scaffold Note Mobile --- lib/cache/cachemanager.dart | 24 +++++- lib/constant.dart | 41 +++++----- lib/generated/intl/messages_ar_EG.dart | 16 ++++ lib/generated/intl/messages_de_DE.dart | 16 ++++ lib/generated/intl/messages_en_US.dart | 17 ++++ lib/generated/intl/messages_es_ES.dart | 16 ++++ lib/generated/intl/messages_id_ID.dart | 16 ++++ lib/generated/intl/messages_ja.dart | 16 ++++ lib/generated/intl/messages_ko_KR.dart | 14 ++++ lib/generated/intl/messages_pt_BR.dart | 16 ++++ lib/generated/intl/messages_ru_RU.dart | 16 ++++ lib/generated/intl/messages_tr_TR.dart | 16 ++++ lib/generated/l10n.dart | 67 +++++++++++++-- lib/l10n/intl_ar_EG.arb | 8 +- lib/l10n/intl_de_DE.arb | 8 +- lib/l10n/intl_en.arb | 8 +- lib/l10n/intl_es_ES.arb | 8 +- lib/l10n/intl_id_ID.arb | 8 +- lib/l10n/intl_ja.arb | 8 +- lib/l10n/intl_ko_KR.arb | 8 +- lib/l10n/intl_pt_BR.arb | 8 +- lib/l10n/intl_ru_RU.arb | 8 +- lib/l10n/intl_tr_TR.arb | 8 +- lib/pages/settings/anime_manga_settings.dart | 19 +++++ lib/pages/settings/backup_restore.dart | 10 ++- lib/user/anime_manga_pref.dart | 2 + lib/user/anime_manga_pref.g.dart | 2 + lib/util/file_service.dart | 17 ++-- lib/util/linux_desktop_helper.dart | 52 +++++++++++- lib/widgets/user/contenteditwidget.dart | 85 ++++++++++++++++++-- linux/my_application.cc | 8 ++ 31 files changed, 512 insertions(+), 54 deletions(-) diff --git a/lib/cache/cachemanager.dart b/lib/cache/cachemanager.dart index 9a763e0..974f0d8 100644 --- a/lib/cache/cachemanager.dart +++ b/lib/cache/cachemanager.dart @@ -126,18 +126,38 @@ class CacheManager { Future getBackUpData() async { final pref = await _pref; final allData = {}; - final keys = [ + + // Fixed keys that should always be backed up + final fixedKeys = [ 'user', StreamUtils.i.key(StreamType.book_marks), '${UserContentBuilder.serviceName} - anime-@me', '${UserContentBuilder.serviceName} - manga-@me', ]; - for (var key in keys) { + + // Get all keys from SharedPreferences + final allKeys = pref.getKeys(); + + // Combine fixed keys with dynamic private notes + final keysToBackup = {...fixedKeys}; + + // Add all private note keys + for (var key in allKeys) { + // The key format in setValueForService is "$serviceName - $key" + // So for 'private_note', it is "private_note - 123" + if (key.startsWith('private_note - ')) { + keysToBackup.add(key); + } + } + + // Collect data for all keys + for (var key in keysToBackup) { String? data = pref.get(key)?.toString(); if (data != null) { allData[key] = data; } } + return jsonEncode(allData); } diff --git a/lib/constant.dart b/lib/constant.dart index 95c109e..2eb6441 100644 --- a/lib/constant.dart +++ b/lib/constant.dart @@ -1067,25 +1067,28 @@ Future showContentEditSheet( return showCupertinoDialog( context: context, barrierDismissible: true, - builder: (context) => AnimatedPadding( - padding: MediaQuery.of(context).viewInsets, - duration: const Duration(milliseconds: 100), - curve: Curves.decelerate, - child: ContentEditWidget( - category: category, - showAdditional: true, - contentDetailed: content, - isCacheRefreshed: true, - updateCache: updateCache, - onDelete: () { - if (onDelete != null) onDelete(); - }, - onListStatusChange: (status) { - if (onListStatusChange != null) onListStatusChange(status); - }, - onUpdate: (value) { - if (onUpdate != null) onUpdate(value); - }, + builder: (context) => Scaffold( + backgroundColor: Colors.transparent, + resizeToAvoidBottomInset: true, + body: GestureDetector( + onTap: () => Navigator.pop(context), + behavior: HitTestBehavior.opaque, + child: ContentEditWidget( + category: category, + showAdditional: true, + contentDetailed: content, + isCacheRefreshed: true, + updateCache: updateCache, + onDelete: () { + if (onDelete != null) onDelete(); + }, + onListStatusChange: (status) { + if (onListStatusChange != null) onListStatusChange(status); + }, + onUpdate: (value) { + if (onUpdate != null) onUpdate(value); + }, + ), ), )); } diff --git a/lib/generated/intl/messages_ar_EG.dart b/lib/generated/intl/messages_ar_EG.dart index 9380704..639f366 100644 --- a/lib/generated/intl/messages_ar_EG.dart +++ b/lib/generated/intl/messages_ar_EG.dart @@ -1056,6 +1056,16 @@ class MessageLookup extends MessageLookupByLibrary { "Priority_level_qn": MessageLookupByLibrary.simpleMessage( "ما هو مستوى أولويتك لمشاهدة / قراءة هذا؟", ), + "Private_Note": MessageLookupByLibrary.simpleMessage("ملاحظة خاصة"), + "Private_Note_Desc": MessageLookupByLibrary.simpleMessage( + "يتم حفظها محليًا، ولن يتم إرسالها إلى الخوادم أبدًا", + ), + "Private_Note_Hint": MessageLookupByLibrary.simpleMessage( + "اكتب ملاحظتك الخاصة هنا...", + ), + "Private_Note_Local_Only": MessageLookupByLibrary.simpleMessage( + "هذه الملاحظة محلية فقط ولن يتمت مزامنتها.", + ), "Profile": MessageLookupByLibrary.simpleMessage("الملف الشخصي"), "Profile_Page": MessageLookupByLibrary.simpleMessage("الصفحة الشخصية"), "Profile_bg_removed": MessageLookupByLibrary.simpleMessage( @@ -1298,6 +1308,12 @@ class MessageLookup extends MessageLookupByLibrary { "Show_Original": MessageLookupByLibrary.simpleMessage( "إظهار النسخة الأصلية", ), + "Show_Private_Review": MessageLookupByLibrary.simpleMessage( + "إظهار الملاحظة الخاصة", + ), + "Show_Private_Review_Desc": MessageLookupByLibrary.simpleMessage( + "إظهار حقل الملاحظة الخاصة في شاشة التحرير", + ), "Show_Spoiler": MessageLookupByLibrary.simpleMessage("عرض المفسد"), "Show_priority_in_anime_manga_list": MessageLookupByLibrary.simpleMessage( "إظهار الأولوية في قائمة أنيمي / مانغا", diff --git a/lib/generated/intl/messages_de_DE.dart b/lib/generated/intl/messages_de_DE.dart index 6c8eb9e..803c191 100644 --- a/lib/generated/intl/messages_de_DE.dart +++ b/lib/generated/intl/messages_de_DE.dart @@ -1130,6 +1130,16 @@ class MessageLookup extends MessageLookupByLibrary { "Priority_level_qn": MessageLookupByLibrary.simpleMessage( "Was ist Ihr Prioritätsniveau, um dies zu sehen / zu lesen?", ), + "Private_Note": MessageLookupByLibrary.simpleMessage("Private Notiz"), + "Private_Note_Desc": MessageLookupByLibrary.simpleMessage( + "Lokal gespeichert, wird nie an Server gesendet", + ), + "Private_Note_Hint": MessageLookupByLibrary.simpleMessage( + "Schreiben Sie hier Ihre private Notiz...", + ), + "Private_Note_Local_Only": MessageLookupByLibrary.simpleMessage( + "Diese Notiz ist nur lokal und wird nicht synchronisiert.", + ), "Profile": MessageLookupByLibrary.simpleMessage("Profil"), "Profile_Page": MessageLookupByLibrary.simpleMessage("Profilseite"), "Profile_bg_removed": MessageLookupByLibrary.simpleMessage( @@ -1392,6 +1402,12 @@ class MessageLookup extends MessageLookupByLibrary { ), "Show_Menu": MessageLookupByLibrary.simpleMessage("Zeige das Menü"), "Show_Original": MessageLookupByLibrary.simpleMessage("Original zeigen"), + "Show_Private_Review": MessageLookupByLibrary.simpleMessage( + "Private Notiz anzeigen", + ), + "Show_Private_Review_Desc": MessageLookupByLibrary.simpleMessage( + "Privates Notizfeld im Bearbeitungsbildschirm anzeigen", + ), "Show_Spoiler": MessageLookupByLibrary.simpleMessage("Spoiler zeigen"), "Show_priority_in_anime_manga_list": MessageLookupByLibrary.simpleMessage( "Priorität in Anime / Manga-Liste anzeigen", diff --git a/lib/generated/intl/messages_en_US.dart b/lib/generated/intl/messages_en_US.dart index 2fb970e..ee86e7a 100644 --- a/lib/generated/intl/messages_en_US.dart +++ b/lib/generated/intl/messages_en_US.dart @@ -1073,6 +1073,16 @@ class MessageLookup extends MessageLookupByLibrary { "Priority_level_qn": MessageLookupByLibrary.simpleMessage( "What is your priority level to watch/read this?", ), + "Private_Note": MessageLookupByLibrary.simpleMessage("Private Note"), + "Private_Note_Desc": MessageLookupByLibrary.simpleMessage( + "Saved locally, never sent to servers", + ), + "Private_Note_Hint": MessageLookupByLibrary.simpleMessage( + "Write your private note here...", + ), + "Private_Note_Local_Only": MessageLookupByLibrary.simpleMessage( + "This note is local only and won\'t be synced.", + ), "Profile": MessageLookupByLibrary.simpleMessage("Profile"), "Profile_Page": MessageLookupByLibrary.simpleMessage("Profile Page"), "Profile_bg_removed": MessageLookupByLibrary.simpleMessage( @@ -1206,6 +1216,7 @@ class MessageLookup extends MessageLookupByLibrary { "Score_Distribution": MessageLookupByLibrary.simpleMessage( "Score Distribution", ), + "Score_Stats": MessageLookupByLibrary.simpleMessage("Score Stats"), "Screening": MessageLookupByLibrary.simpleMessage("Screening"), "Search": MessageLookupByLibrary.simpleMessage("Search"), "SearchBarHintText": MessageLookupByLibrary.simpleMessage( @@ -1317,6 +1328,12 @@ class MessageLookup extends MessageLookupByLibrary { ), "Show_Menu": MessageLookupByLibrary.simpleMessage("Show Menu"), "Show_Original": MessageLookupByLibrary.simpleMessage("Show Original"), + "Show_Private_Review": MessageLookupByLibrary.simpleMessage( + "Show Private Review", + ), + "Show_Private_Review_Desc": MessageLookupByLibrary.simpleMessage( + "Show private note field in the edit screen", + ), "Show_Spoiler": MessageLookupByLibrary.simpleMessage("Show Spoiler"), "Show_dub_status_AnimeList_Desc": MessageLookupByLibrary.simpleMessage( "Show dub (English) status of an anime in list", diff --git a/lib/generated/intl/messages_es_ES.dart b/lib/generated/intl/messages_es_ES.dart index 74d7b6e..566d4a7 100644 --- a/lib/generated/intl/messages_es_ES.dart +++ b/lib/generated/intl/messages_es_ES.dart @@ -1156,6 +1156,16 @@ class MessageLookup extends MessageLookupByLibrary { "Priority_level_qn": MessageLookupByLibrary.simpleMessage( "¿Cuál es su nivel de prioridad para ver / leer esto?", ), + "Private_Note": MessageLookupByLibrary.simpleMessage("Nota Privada"), + "Private_Note_Desc": MessageLookupByLibrary.simpleMessage( + "Guardado localmente, nunca se envía a los servidores", + ), + "Private_Note_Hint": MessageLookupByLibrary.simpleMessage( + "Escribe tu nota privada aquí...", + ), + "Private_Note_Local_Only": MessageLookupByLibrary.simpleMessage( + "Esta nota es solo local y no se sincronizará.", + ), "Profile": MessageLookupByLibrary.simpleMessage("Perfil"), "Profile_Page": MessageLookupByLibrary.simpleMessage("Página de perfil"), "Profile_bg_removed": MessageLookupByLibrary.simpleMessage( @@ -1418,6 +1428,12 @@ class MessageLookup extends MessageLookupByLibrary { ), "Show_Menu": MessageLookupByLibrary.simpleMessage("Muestrame el menu"), "Show_Original": MessageLookupByLibrary.simpleMessage("Mostrar original"), + "Show_Private_Review": MessageLookupByLibrary.simpleMessage( + "Mostrar Notas Privadas", + ), + "Show_Private_Review_Desc": MessageLookupByLibrary.simpleMessage( + "Mostrar el campo de notas privadas en la pantalla de edición", + ), "Show_Spoiler": MessageLookupByLibrary.simpleMessage("Mostrar spoiler"), "Show_priority_in_anime_manga_list": MessageLookupByLibrary.simpleMessage( "Mostrar prioridad en la lista de anime / manga", diff --git a/lib/generated/intl/messages_id_ID.dart b/lib/generated/intl/messages_id_ID.dart index 71dee31..cb20b3f 100644 --- a/lib/generated/intl/messages_id_ID.dart +++ b/lib/generated/intl/messages_id_ID.dart @@ -1112,6 +1112,16 @@ class MessageLookup extends MessageLookupByLibrary { "Priority_level_qn": MessageLookupByLibrary.simpleMessage( "Apa tingkat prioritas Anda untuk menonton / membaca ini?", ), + "Private_Note": MessageLookupByLibrary.simpleMessage("Catatan Pribadi"), + "Private_Note_Desc": MessageLookupByLibrary.simpleMessage( + "Disimpan secara lokal, tidak pernah dikirim ke server", + ), + "Private_Note_Hint": MessageLookupByLibrary.simpleMessage( + "Tulis catatan pribadi Anda di sini...", + ), + "Private_Note_Local_Only": MessageLookupByLibrary.simpleMessage( + "Catatan ini hanya bersifat lokal dan tidak akan disinkronkan.", + ), "Profile": MessageLookupByLibrary.simpleMessage("Profil"), "Profile_Page": MessageLookupByLibrary.simpleMessage("Halaman profil"), "Profile_bg_removed": MessageLookupByLibrary.simpleMessage( @@ -1362,6 +1372,12 @@ class MessageLookup extends MessageLookupByLibrary { "Show_Original": MessageLookupByLibrary.simpleMessage( "Menunjukkan yang asli", ), + "Show_Private_Review": MessageLookupByLibrary.simpleMessage( + "Tampilkan Catatan Pribadi", + ), + "Show_Private_Review_Desc": MessageLookupByLibrary.simpleMessage( + "Tampilkan kolom catatan pribadi di layar edit", + ), "Show_Spoiler": MessageLookupByLibrary.simpleMessage("Tampilkan Spoiler."), "Show_priority_in_anime_manga_list": MessageLookupByLibrary.simpleMessage( "Tampilkan prioritas dalam daftar anime / manga", diff --git a/lib/generated/intl/messages_ja.dart b/lib/generated/intl/messages_ja.dart index 281b62f..645e908 100644 --- a/lib/generated/intl/messages_ja.dart +++ b/lib/generated/intl/messages_ja.dart @@ -940,6 +940,16 @@ class MessageLookup extends MessageLookupByLibrary { "Priority_level_qn": MessageLookupByLibrary.simpleMessage( "これを見る/読むためのあなたの優先レベルは何ですか?", ), + "Private_Note": MessageLookupByLibrary.simpleMessage("プライベートノート"), + "Private_Note_Desc": MessageLookupByLibrary.simpleMessage( + "ローカルに保存され、サーバーには送信されません", + ), + "Private_Note_Hint": MessageLookupByLibrary.simpleMessage( + "ここにプライベートノートを書いてください...", + ), + "Private_Note_Local_Only": MessageLookupByLibrary.simpleMessage( + "このノートはローカルのみであり、同期されません。", + ), "Profile": MessageLookupByLibrary.simpleMessage("プロフィール"), "Profile_Page": MessageLookupByLibrary.simpleMessage("自己紹介ページ"), "Profile_bg_removed": MessageLookupByLibrary.simpleMessage( @@ -1150,6 +1160,12 @@ class MessageLookup extends MessageLookupByLibrary { ), "Show_Menu": MessageLookupByLibrary.simpleMessage("メニューを表示"), "Show_Original": MessageLookupByLibrary.simpleMessage("オリジナルを見せる"), + "Show_Private_Review": MessageLookupByLibrary.simpleMessage( + "プライベートレビューを表示", + ), + "Show_Private_Review_Desc": MessageLookupByLibrary.simpleMessage( + "編集画面にプライベートノートフィールドを表示する", + ), "Show_Spoiler": MessageLookupByLibrary.simpleMessage("スポイラーを見せる"), "Show_priority_in_anime_manga_list": MessageLookupByLibrary.simpleMessage( "アニメ/マンガリストの優先順位を表示します", diff --git a/lib/generated/intl/messages_ko_KR.dart b/lib/generated/intl/messages_ko_KR.dart index 65579e1..699a698 100644 --- a/lib/generated/intl/messages_ko_KR.dart +++ b/lib/generated/intl/messages_ko_KR.dart @@ -920,6 +920,16 @@ class MessageLookup extends MessageLookupByLibrary { "Priority_level_qn": MessageLookupByLibrary.simpleMessage( "이것을 보거나 읽을 우선 순위 수준은 무엇입니까?", ), + "Private_Note": MessageLookupByLibrary.simpleMessage("개인 메모"), + "Private_Note_Desc": MessageLookupByLibrary.simpleMessage( + "로컬에 저장되며 서버로 전송되지 않습니다.", + ), + "Private_Note_Hint": MessageLookupByLibrary.simpleMessage( + "여기에 개인 메모를 작성하세요...", + ), + "Private_Note_Local_Only": MessageLookupByLibrary.simpleMessage( + "이 메모는 로컬 전용이며 동기화되지 않습니다.", + ), "Profile": MessageLookupByLibrary.simpleMessage("프로필"), "Profile_Page": MessageLookupByLibrary.simpleMessage("프로필 페이지"), "Profile_bg_removed": MessageLookupByLibrary.simpleMessage( @@ -1122,6 +1132,10 @@ class MessageLookup extends MessageLookupByLibrary { ), "Show_Menu": MessageLookupByLibrary.simpleMessage("메뉴 보기"), "Show_Original": MessageLookupByLibrary.simpleMessage("원본보기"), + "Show_Private_Review": MessageLookupByLibrary.simpleMessage("개인 메모 표시"), + "Show_Private_Review_Desc": MessageLookupByLibrary.simpleMessage( + "편집 화면에서 개인 메모 필드를 표시합니다.", + ), "Show_Spoiler": MessageLookupByLibrary.simpleMessage("쇼 스포일러"), "Show_priority_in_anime_manga_list": MessageLookupByLibrary.simpleMessage( "Anime / Manga 목록에서 우선 순위를 표시합니다", diff --git a/lib/generated/intl/messages_pt_BR.dart b/lib/generated/intl/messages_pt_BR.dart index f66850c..066e2bd 100644 --- a/lib/generated/intl/messages_pt_BR.dart +++ b/lib/generated/intl/messages_pt_BR.dart @@ -1162,6 +1162,16 @@ class MessageLookup extends MessageLookupByLibrary { "Priority_level_qn": MessageLookupByLibrary.simpleMessage( "Qual é o seu nível de prioridade para assistir / ler isso?", ), + "Private_Note": MessageLookupByLibrary.simpleMessage("Nota Privada"), + "Private_Note_Desc": MessageLookupByLibrary.simpleMessage( + "Salvo localmente, nunca enviado para servidores", + ), + "Private_Note_Hint": MessageLookupByLibrary.simpleMessage( + "Escreva sua nota privada aqui...", + ), + "Private_Note_Local_Only": MessageLookupByLibrary.simpleMessage( + "Esta nota é apenas local e não será sincronizada.", + ), "Profile": MessageLookupByLibrary.simpleMessage("Perfil"), "Profile_Page": MessageLookupByLibrary.simpleMessage("Página de perfil"), "Profile_bg_removed": MessageLookupByLibrary.simpleMessage( @@ -1420,6 +1430,12 @@ class MessageLookup extends MessageLookupByLibrary { ), "Show_Menu": MessageLookupByLibrary.simpleMessage("Mostrar Menu"), "Show_Original": MessageLookupByLibrary.simpleMessage("Mostrar original"), + "Show_Private_Review": MessageLookupByLibrary.simpleMessage( + "Mostrar Nota Privada", + ), + "Show_Private_Review_Desc": MessageLookupByLibrary.simpleMessage( + "Mostrar campo de nota privada na tela de edição", + ), "Show_Spoiler": MessageLookupByLibrary.simpleMessage("Mostrar spoiler"), "Show_priority_in_anime_manga_list": MessageLookupByLibrary.simpleMessage( "Mostrar prioridade na lista de anime / mangá", diff --git a/lib/generated/intl/messages_ru_RU.dart b/lib/generated/intl/messages_ru_RU.dart index 216a048..594504a 100644 --- a/lib/generated/intl/messages_ru_RU.dart +++ b/lib/generated/intl/messages_ru_RU.dart @@ -1132,6 +1132,16 @@ class MessageLookup extends MessageLookupByLibrary { "Priority_level_qn": MessageLookupByLibrary.simpleMessage( "Какой у вас приоритет при просмотре/чтении этого?", ), + "Private_Note": MessageLookupByLibrary.simpleMessage("Личная заметка"), + "Private_Note_Desc": MessageLookupByLibrary.simpleMessage( + "Сохранено локально, никогда не отправляется на серверы", + ), + "Private_Note_Hint": MessageLookupByLibrary.simpleMessage( + "Напишите здесь свою личную заметку...", + ), + "Private_Note_Local_Only": MessageLookupByLibrary.simpleMessage( + "Эта заметка только локальная и не будет синхронизирована.", + ), "Profile": MessageLookupByLibrary.simpleMessage("Профиль"), "Profile_Page": MessageLookupByLibrary.simpleMessage("Страница профиля"), "Profile_bg_removed": MessageLookupByLibrary.simpleMessage( @@ -1386,6 +1396,12 @@ class MessageLookup extends MessageLookupByLibrary { ), "Show_Menu": MessageLookupByLibrary.simpleMessage("Показать меню"), "Show_Original": MessageLookupByLibrary.simpleMessage("Показать оригинал"), + "Show_Private_Review": MessageLookupByLibrary.simpleMessage( + "Показать личную заметку", + ), + "Show_Private_Review_Desc": MessageLookupByLibrary.simpleMessage( + "Показать поле личной заметки на экране редактирования", + ), "Show_Spoiler": MessageLookupByLibrary.simpleMessage("Показать спойлер"), "Show_priority_in_anime_manga_list": MessageLookupByLibrary.simpleMessage( "Показывать приоритет в списке аниме/манги", diff --git a/lib/generated/intl/messages_tr_TR.dart b/lib/generated/intl/messages_tr_TR.dart index aa51656..9ed2e88 100644 --- a/lib/generated/intl/messages_tr_TR.dart +++ b/lib/generated/intl/messages_tr_TR.dart @@ -1100,6 +1100,16 @@ class MessageLookup extends MessageLookupByLibrary { "Priority_level_qn": MessageLookupByLibrary.simpleMessage( "Bunu izlemek/okumak için öncelik düzeyiniz nedir?", ), + "Private_Note": MessageLookupByLibrary.simpleMessage("Özel Not"), + "Private_Note_Desc": MessageLookupByLibrary.simpleMessage( + "Yerel olarak kaydedilir, asla sunuculara gönderilmez", + ), + "Private_Note_Hint": MessageLookupByLibrary.simpleMessage( + "Özel notunuzu buraya yazın...", + ), + "Private_Note_Local_Only": MessageLookupByLibrary.simpleMessage( + "Bu not yalnızca yereldir ve senkronize edilmeyecektir.", + ), "Profile": MessageLookupByLibrary.simpleMessage("Profil"), "Profile_Page": MessageLookupByLibrary.simpleMessage("Profil sayfası"), "Profile_bg_removed": MessageLookupByLibrary.simpleMessage( @@ -1348,6 +1358,12 @@ class MessageLookup extends MessageLookupByLibrary { ), "Show_Menu": MessageLookupByLibrary.simpleMessage("Menüyü göster"), "Show_Original": MessageLookupByLibrary.simpleMessage("Orjinali göster"), + "Show_Private_Review": MessageLookupByLibrary.simpleMessage( + "Özel Notu Göster", + ), + "Show_Private_Review_Desc": MessageLookupByLibrary.simpleMessage( + "Düzenleme ekranında özel not alanını göster", + ), "Show_Spoiler": MessageLookupByLibrary.simpleMessage("Spoiler\'ı Göster"), "Show_priority_in_anime_manga_list": MessageLookupByLibrary.simpleMessage( "Anime/manga listesinde önceliği göster", diff --git a/lib/generated/l10n.dart b/lib/generated/l10n.dart index daf4477..c4ad36a 100644 --- a/lib/generated/l10n.dart +++ b/lib/generated/l10n.dart @@ -321,12 +321,7 @@ class S { /// `Score Stats` String get Score_Stats { - return Intl.message( - 'Score Stats', - name: 'Score_Stats', - desc: '', - args: [], - ); + return Intl.message('Score Stats', name: 'Score_Stats', desc: '', args: []); } /// `Pictures` @@ -7613,6 +7608,66 @@ class S { String get Calendar { return Intl.message('Calendar', name: 'Calendar', desc: '', args: []); } + + /// `Private Note` + String get Private_Note { + return Intl.message( + 'Private Note', + name: 'Private_Note', + desc: '', + args: [], + ); + } + + /// `Show Private Review` + String get Show_Private_Review { + return Intl.message( + 'Show Private Review', + name: 'Show_Private_Review', + desc: '', + args: [], + ); + } + + /// `Show private note field in the edit screen` + String get Show_Private_Review_Desc { + return Intl.message( + 'Show private note field in the edit screen', + name: 'Show_Private_Review_Desc', + desc: '', + args: [], + ); + } + + /// `Saved locally, never sent to servers` + String get Private_Note_Desc { + return Intl.message( + 'Saved locally, never sent to servers', + name: 'Private_Note_Desc', + desc: '', + args: [], + ); + } + + /// `Write your private note here...` + String get Private_Note_Hint { + return Intl.message( + 'Write your private note here...', + name: 'Private_Note_Hint', + desc: '', + args: [], + ); + } + + /// `This note is local only and won't be synced.` + String get Private_Note_Local_Only { + return Intl.message( + 'This note is local only and won\'t be synced.', + name: 'Private_Note_Local_Only', + desc: '', + args: [], + ); + } } class AppLocalizationDelegate extends LocalizationsDelegate { diff --git a/lib/l10n/intl_ar_EG.arb b/lib/l10n/intl_ar_EG.arb index 7531a15..6f6850d 100644 --- a/lib/l10n/intl_ar_EG.arb +++ b/lib/l10n/intl_ar_EG.arb @@ -1016,5 +1016,11 @@ "Add_To_Calendar_Prompt": "\u0625\u0636\u0627\u0641\u0629 \u0625\u0644\u0649 \u0627\u0644\u062a\u0642\u0648\u064a\u0645", "Add_Recurring_Event": "\u0645\u062a\u0643\u0631\u0631 \u0623\u0633\u0628\u0648\u0639\u064a", "Add_Recurring_Event_Desc": "\u0623\u0636\u0641 \u0627\u0644\u062d\u0644\u0642\u0627\u062a \u0627\u0644\u0645\u0633\u062a\u0642\u0628\u0644\u064a\u0629 \u0643\u0623\u062d\u062f\u0627\u062b \u0623\u0633\u0628\u0648\u0639\u064a\u0629", - "Add": "\u064a\u0636\u064a\u0641" + "Add": "\u064a\u0636\u064a\u0641", + "Private_Note": "ملاحظة خاصة", + "Show_Private_Review": "إظهار الملاحظة الخاصة", + "Show_Private_Review_Desc": "إظهار حقل الملاحظة الخاصة في شاشة التحرير", + "Private_Note_Desc": "يتم حفظها محليًا، ولن يتم إرسالها إلى الخوادم أبدًا", + "Private_Note_Hint": "اكتب ملاحظتك الخاصة هنا...", + "Private_Note_Local_Only": "هذه الملاحظة محلية فقط ولن يتمت مزامنتها." } \ No newline at end of file diff --git a/lib/l10n/intl_de_DE.arb b/lib/l10n/intl_de_DE.arb index 2c2483e..84f3008 100644 --- a/lib/l10n/intl_de_DE.arb +++ b/lib/l10n/intl_de_DE.arb @@ -1017,5 +1017,11 @@ "Add_To_Calendar_Prompt": "Zum Kalender hinzuf\u00fcgen", "Add_Recurring_Event": "Wiederkehrendes w\u00f6chentliches", "Add_Recurring_Event_Desc": "F\u00fcgen Sie zuk\u00fcnftige Episoden als w\u00f6chentliche Ereignisse hinzu", - "Add": "Hinzuf\u00fcgen" + "Add": "Hinzuf\u00fcgen", + "Private_Note": "Private Notiz", + "Show_Private_Review": "Private Notiz anzeigen", + "Show_Private_Review_Desc": "Privates Notizfeld im Bearbeitungsbildschirm anzeigen", + "Private_Note_Desc": "Lokal gespeichert, wird nie an Server gesendet", + "Private_Note_Hint": "Schreiben Sie hier Ihre private Notiz...", + "Private_Note_Local_Only": "Diese Notiz ist nur lokal und wird nicht synchronisiert." } diff --git a/lib/l10n/intl_en.arb b/lib/l10n/intl_en.arb index 128fb25..411f3b2 100644 --- a/lib/l10n/intl_en.arb +++ b/lib/l10n/intl_en.arb @@ -1017,5 +1017,11 @@ "Add_Recurring_Event_Desc": "Add future episodes as weekly events", "Add": "Add", "View_Related_Graph_Tooltip": "View related anime/manga graph", - "Calendar": "Calendar" + "Calendar": "Calendar", + "Private_Note": "Private Note", + "Show_Private_Review": "Show Private Review", + "Show_Private_Review_Desc": "Show private note field in the edit screen", + "Private_Note_Desc": "Saved locally, never sent to servers", + "Private_Note_Hint": "Write your private note here...", + "Private_Note_Local_Only": "This note is local only and won't be synced." } \ No newline at end of file diff --git a/lib/l10n/intl_es_ES.arb b/lib/l10n/intl_es_ES.arb index 1273dbd..a8fc0cf 100644 --- a/lib/l10n/intl_es_ES.arb +++ b/lib/l10n/intl_es_ES.arb @@ -1017,5 +1017,11 @@ "Add_To_Calendar_Prompt": "Agregar al calendario", "Add_Recurring_Event": "Semanal recurrente", "Add_Recurring_Event_Desc": "Agregar episodios futuros como eventos semanales", - "Add": "Agregar" + "Add": "Agregar", + "Private_Note": "Nota Privada", + "Show_Private_Review": "Mostrar Notas Privadas", + "Show_Private_Review_Desc": "Mostrar el campo de notas privadas en la pantalla de edición", + "Private_Note_Desc": "Guardado localmente, nunca se envía a los servidores", + "Private_Note_Hint": "Escribe tu nota privada aquí...", + "Private_Note_Local_Only": "Esta nota es solo local y no se sincronizará." } \ No newline at end of file diff --git a/lib/l10n/intl_id_ID.arb b/lib/l10n/intl_id_ID.arb index 88127cb..0306f92 100644 --- a/lib/l10n/intl_id_ID.arb +++ b/lib/l10n/intl_id_ID.arb @@ -1016,5 +1016,11 @@ "Add_To_Calendar_Prompt": "Tambahkan ke Kalender", "Add_Recurring_Event": "Berulang mingguan", "Add_Recurring_Event_Desc": "Tambahkan episode masa depan sebagai acara mingguan", - "Add": "Menambahkan" + "Add": "Menambahkan", + "Private_Note": "Catatan Pribadi", + "Show_Private_Review": "Tampilkan Catatan Pribadi", + "Show_Private_Review_Desc": "Tampilkan kolom catatan pribadi di layar edit", + "Private_Note_Desc": "Disimpan secara lokal, tidak pernah dikirim ke server", + "Private_Note_Hint": "Tulis catatan pribadi Anda di sini...", + "Private_Note_Local_Only": "Catatan ini hanya bersifat lokal dan tidak akan disinkronkan." } \ No newline at end of file diff --git a/lib/l10n/intl_ja.arb b/lib/l10n/intl_ja.arb index ee1552f..38ee2ae 100644 --- a/lib/l10n/intl_ja.arb +++ b/lib/l10n/intl_ja.arb @@ -1016,5 +1016,11 @@ "Add_To_Calendar_Prompt": "\u30ab\u30ec\u30f3\u30c0\u30fc\u306b\u8ffd\u52a0\u3057\u307e\u3059", "Add_Recurring_Event": "\u6bce\u9031\u7e70\u308a\u8fd4\u3057", "Add_Recurring_Event_Desc": "Add future episodes as weekly events", - "Add": "\u8ffd\u52a0" + "Add": "\u8ffd\u52a0", + "Private_Note": "プライベートノート", + "Show_Private_Review": "プライベートレビューを表示", + "Show_Private_Review_Desc": "編集画面にプライベートノートフィールドを表示する", + "Private_Note_Desc": "ローカルに保存され、サーバーには送信されません", + "Private_Note_Hint": "ここにプライベートノートを書いてください...", + "Private_Note_Local_Only": "このノートはローカルのみであり、同期されません。" } \ No newline at end of file diff --git a/lib/l10n/intl_ko_KR.arb b/lib/l10n/intl_ko_KR.arb index 9efd47f..5efa187 100644 --- a/lib/l10n/intl_ko_KR.arb +++ b/lib/l10n/intl_ko_KR.arb @@ -1016,5 +1016,11 @@ "Add_To_Calendar_Prompt": "\ub2ec\ub825\uc5d0 \ucd94\uac00\ud558\uc2ed\uc2dc\uc624", "Add_Recurring_Event": "\ub9e4\uc8fc \ubc18\ubcf5", "Add_Recurring_Event_Desc": "\uc8fc\uac04 \uc774\ubca4\ud2b8\ub85c \ud5a5\ud6c4 \uc5d0\ud53c\uc18c\ub4dc\ub97c \ucd94\uac00\ud558\uc2ed\uc2dc\uc624", - "Add": "\ucd94\uac00\ud558\ub2e4" + "Add": "\ucd94\uac00\ud558\ub2e4", + "Private_Note": "개인 메모", + "Show_Private_Review": "개인 메모 표시", + "Show_Private_Review_Desc": "편집 화면에서 개인 메모 필드를 표시합니다.", + "Private_Note_Desc": "로컬에 저장되며 서버로 전송되지 않습니다.", + "Private_Note_Hint": "여기에 개인 메모를 작성하세요...", + "Private_Note_Local_Only": "이 메모는 로컬 전용이며 동기화되지 않습니다." } \ No newline at end of file diff --git a/lib/l10n/intl_pt_BR.arb b/lib/l10n/intl_pt_BR.arb index 6e7cbc2..859397b 100644 --- a/lib/l10n/intl_pt_BR.arb +++ b/lib/l10n/intl_pt_BR.arb @@ -1017,5 +1017,11 @@ "Add_To_Calendar_Prompt": "Adicione ao calend\u00e1rio", "Add_Recurring_Event": "Recorrente semanalmente", "Add_Recurring_Event_Desc": "Adicione epis\u00f3dios futuros como eventos semanais", - "Add": "Adicionar" + "Add": "Adicionar", + "Private_Note": "Nota Privada", + "Show_Private_Review": "Mostrar Nota Privada", + "Show_Private_Review_Desc": "Mostrar campo de nota privada na tela de edição", + "Private_Note_Desc": "Salvo localmente, nunca enviado para servidores", + "Private_Note_Hint": "Escreva sua nota privada aqui...", + "Private_Note_Local_Only": "Esta nota é apenas local e não será sincronizada." } \ No newline at end of file diff --git a/lib/l10n/intl_ru_RU.arb b/lib/l10n/intl_ru_RU.arb index 48cc8e9..f74aa72 100644 --- a/lib/l10n/intl_ru_RU.arb +++ b/lib/l10n/intl_ru_RU.arb @@ -1014,5 +1014,11 @@ "Add_To_Calendar_Prompt": "\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432 \u043a\u0430\u043b\u0435\u043d\u0434\u0430\u0440\u044c", "Add_Recurring_Event": "\u041f\u043e\u0432\u0442\u043e\u0440\u044f\u044e\u0449\u0438\u0439\u0441\u044f \u0435\u0436\u0435\u043d\u0435\u0434\u0435\u043b\u044c\u043d\u044b\u0439", "Add_Recurring_Event_Desc": "\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0431\u0443\u0434\u0443\u0449\u0438\u0435 \u044d\u043f\u0438\u0437\u043e\u0434\u044b \u043a\u0430\u043a \u0435\u0436\u0435\u043d\u0435\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u043c\u0435\u0440\u043e\u043f\u0440\u0438\u044f\u0442\u0438\u044f", - "Add": "\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c" + "Add": "\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c", + "Private_Note": "Личная заметка", + "Show_Private_Review": "Показать личную заметку", + "Show_Private_Review_Desc": "Показать поле личной заметки на экране редактирования", + "Private_Note_Desc": "Сохранено локально, никогда не отправляется на серверы", + "Private_Note_Hint": "Напишите здесь свою личную заметку...", + "Private_Note_Local_Only": "Эта заметка только локальная и не будет синхронизирована." } \ No newline at end of file diff --git a/lib/l10n/intl_tr_TR.arb b/lib/l10n/intl_tr_TR.arb index e799cb1..2ba8f51 100644 --- a/lib/l10n/intl_tr_TR.arb +++ b/lib/l10n/intl_tr_TR.arb @@ -1014,5 +1014,11 @@ "Add_To_Calendar_Prompt": "Takvime ekle", "Add_Recurring_Event": "Tekrarlayan haftal\u0131k", "Add_Recurring_Event_Desc": "Haftal\u0131k etkinlikler olarak gelecekteki b\u00f6l\u00fcmleri ekleyin", - "Add": "Eklemek" + "Add": "Eklemek", + "Private_Note": "\u00d6zel Not", + "Show_Private_Review": "\u00d6zel Notu G\u00f6ster", + "Show_Private_Review_Desc": "D\u00fczenleme ekran\u0131nda \u00f6zel not alan\u0131n\u0131 g\u00f6ster", + "Private_Note_Desc": "Yerel olarak kaydedilir, asla sunuculara g\u00f6nderilmez", + "Private_Note_Hint": "\u00d6zel notunuzu buraya yaz\u0131n...", + "Private_Note_Local_Only": "Bu not yaln\u0131zca yereldir ve senkronize edilmeyecektir." } \ No newline at end of file diff --git a/lib/pages/settings/anime_manga_settings.dart b/lib/pages/settings/anime_manga_settings.dart index b8704ce..d2ef3a2 100644 --- a/lib/pages/settings/anime_manga_settings.dart +++ b/lib/pages/settings/anime_manga_settings.dart @@ -138,6 +138,19 @@ class _AnimeMangaSettingsState extends State { onToggled: (value) => _changeAnimeMangaBG(value), ), ), + OptionTile( + text: S.current.Show_Private_Review, + iconData: Icons.notes_rounded, + multiLine: true, + desc: S.current.Show_Private_Review_Desc, + onPressed: () => _changePrivateNotes( + !user.pref.animeMangaPagePreferences.showPrivateNotes), + trailing: ToggleButton( + toggleValue: + user.pref.animeMangaPagePreferences.showPrivateNotes, + onToggled: (value) => _changePrivateNotes(value), + ), + ), OptionTile( text: S.current.Anime_Timezone_Pref, iconData: Icons.timelapse_rounded, @@ -246,4 +259,10 @@ class _AnimeMangaSettingsState extends State { user.setIntance(); setState(() {}); } + + void _changePrivateNotes(bool value) { + user.pref.animeMangaPagePreferences.showPrivateNotes = value; + user.setIntance(); + setState(() {}); + } } diff --git a/lib/pages/settings/backup_restore.dart b/lib/pages/settings/backup_restore.dart index 8a939a9..a4e821d 100644 --- a/lib/pages/settings/backup_restore.dart +++ b/lib/pages/settings/backup_restore.dart @@ -1,3 +1,4 @@ +import 'dart:convert'; import 'dart:io'; import 'package:dailyanimelist/cache/cachemanager.dart'; @@ -55,7 +56,10 @@ class _BackUpAndRestorePageState extends State { if (path != null) { File file = File(path); final bytes = await file.readAsBytes(); - final data = String.fromCharCodes(bytes); + + // Use utf8.decode to properly handle special characters (tildes, ñ, emojis, etc.) + final data = utf8.decode(bytes); + final result = await CacheManager.instance.restoreData(data); if (result) { user = await User.getInstance(); @@ -69,7 +73,9 @@ class _BackUpAndRestorePageState extends State { return; } } - } catch (e) {} + } catch (e) { + print('Restore error: $e'); + } showToast(S.current.Cancelled_Restore); } diff --git a/lib/user/anime_manga_pref.dart b/lib/user/anime_manga_pref.dart index b62b1a6..131ef6f 100644 --- a/lib/user/anime_manga_pref.dart +++ b/lib/user/anime_manga_pref.dart @@ -17,12 +17,14 @@ class AnimeMangaPagePreferences { String? defaultMangaTab; String? defaultAnimeAddToList; String? defaultMangaAddToList; + bool showPrivateNotes; List? contentCardProps; AnimeMangaPagePreferences({ required this.animeTabs, required this.mangaTabs, this.timezonePref = TimezonePref.local, + this.showPrivateNotes = false, this.defaultTab, this.defaultAnimeTab, this.defaultMangaTab, diff --git a/lib/user/anime_manga_pref.g.dart b/lib/user/anime_manga_pref.g.dart index 2f72781..a4a42cf 100644 --- a/lib/user/anime_manga_pref.g.dart +++ b/lib/user/anime_manga_pref.g.dart @@ -20,6 +20,7 @@ AnimeMangaPagePreferences _$AnimeMangaPagePreferencesFromJson( timezonePref: $enumDecodeNullable(_$TimezonePrefEnumMap, json['timezonePref']) ?? TimezonePref.local, + showPrivateNotes: json['showPrivateNotes'] as bool? ?? false, defaultTab: json['defaultTab'] as String?, defaultAnimeTab: json['defaultAnimeTab'] as String?, defaultMangaTab: json['defaultMangaTab'] as String?, @@ -41,6 +42,7 @@ Map _$AnimeMangaPagePreferencesToJson( 'defaultMangaTab': instance.defaultMangaTab, 'defaultAnimeAddToList': instance.defaultAnimeAddToList, 'defaultMangaAddToList': instance.defaultMangaAddToList, + 'showPrivateNotes': instance.showPrivateNotes, 'contentCardProps': instance.contentCardProps, }; diff --git a/lib/util/file_service.dart b/lib/util/file_service.dart index fb31780..63dfc19 100644 --- a/lib/util/file_service.dart +++ b/lib/util/file_service.dart @@ -5,17 +5,18 @@ import 'package:permission_handler/permission_handler.dart'; // To save the file in the device class FileStorage { static Future getExternalDocumentPath() async { - // To check whether permission is given for this app or not. - var status = await Permission.storage.status; - if (!status.isGranted) { - // If not we will ask for permission first - await Permission.storage.request(); - } - Directory _directory = Directory(""); + Directory _directory; + if (Platform.isAndroid) { - // Redirects it to download folder in android + // Android: Check storage permissions and use Download folder + var status = await Permission.storage.status; + if (!status.isGranted) { + await Permission.storage.request(); + } _directory = Directory("/storage/emulated/0/Download"); } else { + // Desktop platforms (Linux, macOS, Windows) and iOS: use app documents directory + // This works generically across all desktop platforms _directory = await getApplicationDocumentsDirectory(); } diff --git a/lib/util/linux_desktop_helper.dart b/lib/util/linux_desktop_helper.dart index cb6cf4d..ecbc547 100644 --- a/lib/util/linux_desktop_helper.dart +++ b/lib/util/linux_desktop_helper.dart @@ -54,15 +54,65 @@ class LinuxDesktopHelper extends TrayListener { try { await _initTimezone(); await _checkDependencies(); + await _extractAppIcon(); // Extract logo for system notifications + await _installSystemIcon(); // Install icon for dock/taskbar await _initWindowManager(); await _instance._initTray(); - await _extractAppIcon(); // Extract logo for system notifications print('DEBUG: Linux Desktop Helper initialized successfully'); } catch (e) { print('ERROR: Failed to initialize Linux Desktop Helper: $e'); } } + /// Installs the app icon in the system icon directories so GNOME/KDE can find it. + /// This makes the icon appear correctly in the dock/taskbar. + static Future _installSystemIcon() async { + try { + final String homeDir = Platform.environment['HOME'] ?? ''; + if (homeDir.isEmpty) return; + + // Icon sizes that desktop environments expect + final List sizes = ['48x48', '128x128', '256x256', '512x512']; + final String iconName = 'com.teen.dailyanimelist.png'; + + for (final size in sizes) { + final String iconDir = '$homeDir/.local/share/icons/hicolor/$size/apps'; + final Directory dir = Directory(iconDir); + + // Create directory if it doesn't exist + if (!await dir.exists()) { + await dir.create(recursive: true); + } + + // Copy icon to system location + final String iconPath = '$iconDir/$iconName'; + final File iconFile = File(iconPath); + + // Only copy if it doesn't exist or is outdated + if (!await iconFile.exists()) { + final ByteData data = await rootBundle.load('assets/images/dal-black-bg.png'); + final List bytes = data.buffer.asUint8List(); + await iconFile.writeAsBytes(bytes); + print('DEBUG: Installed icon to: $iconPath'); + } + } + + // Update icon cache (ignore errors if gtk-update-icon-cache is not available) + try { + await Process.run('gtk-update-icon-cache', [ + '-f', + '-t', + '$homeDir/.local/share/icons/hicolor' + ]); + print('DEBUG: Updated icon cache'); + } catch (e) { + // Icon cache update is optional, app will still work + } + } catch (e) { + print('WARNING: Could not install system icon: $e'); + } + } + /// Extracts the app asset logo to a temporary directory. /// Standard Linux notifications (libnotify) require an absolute file path to display icons. static Future _extractAppIcon() async { diff --git a/lib/widgets/user/contenteditwidget.dart b/lib/widgets/user/contenteditwidget.dart index c0eac59..7af88a0 100644 --- a/lib/widgets/user/contenteditwidget.dart +++ b/lib/widgets/user/contenteditwidget.dart @@ -78,7 +78,8 @@ class _ContentEditWidgetState extends State { dynamic contentDetailed; late TextEditingController episodeController, chapterController, - volumesController; + volumesController, + privateNoteController; bool modifyStartDate = false; @@ -112,6 +113,7 @@ class _ContentEditWidgetState extends State { super.initState(); reset(); contentDetailed = widget.contentDetailed; + _loadPrivateNote(); showAddOptions = isFloating && user.status == AuthStatus.AUTHENTICATED; if (widget.updateCache && user.status == AuthStatus.AUTHENTICATED) { cacheUpdated = false; @@ -156,6 +158,44 @@ class _ContentEditWidgetState extends State { }); } + void _loadPrivateNote() async { + // Try loading with category-specific key first + String? note = await CacheManager.instance.getValueForService( + 'private_note', "${widget.category} - $_id"); + + // Fallback: try loading legacy key (without category) if specific one doesn't exist + if (note == null) { + note = await CacheManager.instance.getValueForService('private_note', "$_id"); + // If legacy note exists, save it with new key format for future + if (note != null) { + CacheManager.instance.setValueForService( + 'private_note', "${widget.category} - $_id", note); + } + } + + if (note != null && mounted) { + privateNoteController.text = note; + } + } + + void _savePrivateNote() { + if (_id != null) { + // Save with category to avoid ID collisions between Anime and Manga + CacheManager.instance.setValueForService( + 'private_note', "${widget.category} - $_id", privateNoteController.text); + } + } + + @override + void dispose() { + _savePrivateNote(); + privateNoteController.dispose(); + episodeController.dispose(); + chapterController.dispose(); + volumesController.dispose(); + super.dispose(); + } + int? get _id { if (widget.id != null) { return widget.id; @@ -171,6 +211,7 @@ class _ContentEditWidgetState extends State { episodeController = new TextEditingController(text: "0"); chapterController = new TextEditingController(text: "0"); volumesController = new TextEditingController(text: "0"); + privateNoteController = new TextEditingController(); statusValue = null; starValue = null; } @@ -864,6 +905,30 @@ class _ContentEditWidgetState extends State { child: rewatchWidget, ), ), + if (user.pref.animeMangaPagePreferences.showPrivateNotes) + Padding( + padding: EdgeInsets.only(top: 10, bottom: 20), + child: field( + S.current.Private_Note, + TextFormField( + controller: privateNoteController, + minLines: 5, + maxLines: null, + scrollPhysics: const AlwaysScrollableScrollPhysics(), + decoration: InputDecoration( + hintText: S.current.Private_Note_Hint, + helperText: S.current.Private_Note_Local_Only, + prefixIcon: Icon(Icons.lock_outline), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + ), + ), + ), + S.current.Private_Note_Desc, + null, + CrossAxisAlignment.start, + EdgeInsets.only(left: 20, bottom: 8)), + ), sectionHeading(S.current.Dates_Priority, isOpen: isDatesOpen, onChange: () { if (mounted) @@ -1429,11 +1494,19 @@ class _ContentEditWidgetState extends State { void _scrollToEpisodeCount() { const duration = const Duration(milliseconds: 200); Future.delayed(duration).then( - (value) => _episodeScrollController.scrollTo( - index: _episodeCount(), - alignment: 0.6, - duration: duration, - ), + (value) { + if (mounted && _episodeScrollController.isAttached) { + try { + _episodeScrollController.scrollTo( + index: _episodeCount(), + alignment: 0.6, + duration: duration, + ); + } catch (e) { + // Ignore scroll errors if list is not ready + } + } + }, ); } diff --git a/linux/my_application.cc b/linux/my_application.cc index 2fb95ef..b1b5948 100644 --- a/linux/my_application.cc +++ b/linux/my_application.cc @@ -17,6 +17,14 @@ G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) // Implements GApplication::activate. static void my_application_activate(GApplication* application) { MyApplication* self = MY_APPLICATION(application); + + // NOTE: This file (my_application.cc) is ONLY compiled for Linux builds. + // It does NOT affect Android, macOS, Windows, or web builds. + // Set application name for GNOME to find the icon in ~/.local/share/icons/ + // This must be set BEFORE creating the window + g_set_application_name("DailyAL"); + g_set_prgname("com.teen.dailyanimelist"); + GtkWindow* window = GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); From f12ff299788e3d610d8d141b5055869a403f592d Mon Sep 17 00:00:00 2001 From: Jishnu Raj Date: Sun, 8 Feb 2026 15:27:27 +0530 Subject: [PATCH 02/16] feat: Add horizontal padding to the private notes section in the content editor and bump the package version. --- lib/widgets/user/contenteditwidget.dart | 16 +++++++++------- pubspec.yaml | 2 +- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/lib/widgets/user/contenteditwidget.dart b/lib/widgets/user/contenteditwidget.dart index 7af88a0..c81f10b 100644 --- a/lib/widgets/user/contenteditwidget.dart +++ b/lib/widgets/user/contenteditwidget.dart @@ -160,12 +160,13 @@ class _ContentEditWidgetState extends State { void _loadPrivateNote() async { // Try loading with category-specific key first - String? note = await CacheManager.instance.getValueForService( - 'private_note', "${widget.category} - $_id"); - + String? note = await CacheManager.instance + .getValueForService('private_note', "${widget.category} - $_id"); + // Fallback: try loading legacy key (without category) if specific one doesn't exist if (note == null) { - note = await CacheManager.instance.getValueForService('private_note', "$_id"); + note = await CacheManager.instance + .getValueForService('private_note', "$_id"); // If legacy note exists, save it with new key format for future if (note != null) { CacheManager.instance.setValueForService( @@ -181,8 +182,8 @@ class _ContentEditWidgetState extends State { void _savePrivateNote() { if (_id != null) { // Save with category to avoid ID collisions between Anime and Manga - CacheManager.instance.setValueForService( - 'private_note', "${widget.category} - $_id", privateNoteController.text); + CacheManager.instance.setValueForService('private_note', + "${widget.category} - $_id", privateNoteController.text); } } @@ -907,7 +908,8 @@ class _ContentEditWidgetState extends State { ), if (user.pref.animeMangaPagePreferences.showPrivateNotes) Padding( - padding: EdgeInsets.only(top: 10, bottom: 20), + padding: + EdgeInsets.only(top: 10, bottom: 20, right: 15, left: 15), child: field( S.current.Private_Note, TextFormField( diff --git a/pubspec.yaml b/pubspec.yaml index afd0e75..4b22f49 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # Read more about iOS versioning at # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 2026.2.3+105 +version: 2026.2.4+106 environment: sdk: '>=3.2.6 <4.0.0' From 25de0a35fd0e5ce19b23d69a23cfb8cb011b7564 Mon Sep 17 00:00:00 2001 From: Jishnu Raj Date: Sun, 8 Feb 2026 15:48:40 +0530 Subject: [PATCH 03/16] feat: Scaffold multi-platform Flutter project for Android, iOS, Linux, macOS, and Web, and integrate Windows build into CI/CD. --- .github/workflows/release.yml | 61 +++++++- .metadata | 25 ++- .../io/github/dailyanimelist/MainActivity.kt | 5 + ios/RunnerTests/RunnerTests.swift | 12 ++ linux/runner/CMakeLists.txt | 26 +++ linux/runner/main.cc | 6 + linux/runner/my_application.cc | 148 ++++++++++++++++++ linux/runner/my_application.h | 21 +++ macos/RunnerTests/RunnerTests.swift | 12 ++ web/icons/Icon-maskable-192.png | Bin 0 -> 5594 bytes web/icons/Icon-maskable-512.png | Bin 0 -> 20998 bytes windows/runner/resources/app_icon.ico | Bin 33772 -> 137918 bytes 12 files changed, 308 insertions(+), 8 deletions(-) create mode 100644 android/app/src/main/kotlin/io/github/dailyanimelist/MainActivity.kt create mode 100644 ios/RunnerTests/RunnerTests.swift create mode 100644 linux/runner/CMakeLists.txt create mode 100644 linux/runner/main.cc create mode 100644 linux/runner/my_application.cc create mode 100644 linux/runner/my_application.h create mode 100644 macos/RunnerTests/RunnerTests.swift create mode 100644 web/icons/Icon-maskable-192.png create mode 100644 web/icons/Icon-maskable-512.png diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0ff8666..de67968 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -10,7 +10,7 @@ permissions: contents: write jobs: - build: + build-linux-android: runs-on: ubuntu-latest steps: @@ -71,11 +71,64 @@ jobs: - name: Upload Artifacts uses: actions/upload-artifact@v4 with: - name: release-artifacts + name: release-artifacts-linux-android path: release-artifacts/* + build-windows: + runs-on: windows-latest + + steps: + - uses: actions/checkout@v4 + + - name: Set up Flutter + uses: subosito/flutter-action@v2 + with: + channel: 'stable' + + - name: Enable Windows Desktop + run: flutter config --enable-windows-desktop + + - name: Get Dependencies + run: flutter pub get + + - name: Build Windows Release + run: flutter build windows --release + + - name: Compress Windows Build + run: | + Compress-Archive -Path build/windows/x64/runner/Release/* -DestinationPath DailyAL-Windows.zip + + - name: Generate SHA1 Checksum + run: | + Get-FileHash DailyAL-Windows.zip -Algorithm SHA1 | Select-Object -ExpandProperty Hash > DailyAL-Windows.zip.sha1 + + - name: Upload Artifacts + uses: actions/upload-artifact@v4 + with: + name: release-artifacts-windows + path: | + DailyAL-Windows.zip + DailyAL-Windows.zip.sha1 + + release: + needs: [build-linux-android, build-windows] + runs-on: ubuntu-latest + if: startsWith(github.ref, 'refs/tags/20') + + steps: + - name: Download Linux/Android Artifacts + uses: actions/download-artifact@v4 + with: + name: release-artifacts-linux-android + path: release-artifacts + + - name: Download Windows Artifacts + uses: actions/download-artifact@v4 + with: + name: release-artifacts-windows + path: release-artifacts + - name: Create Release - if: startsWith(github.ref, 'refs/tags/20') uses: softprops/action-gh-release@v1 with: files: | @@ -83,3 +136,5 @@ jobs: release-artifacts/app-release.apk.sha1 release-artifacts/DailyAL-x86_64.AppImage release-artifacts/DailyAL-x86_64.AppImage.sha1 + release-artifacts/DailyAL-Windows.zip + release-artifacts/DailyAL-Windows.zip.sha1 diff --git a/.metadata b/.metadata index 0691157..08c2478 100644 --- a/.metadata +++ b/.metadata @@ -4,7 +4,7 @@ # This file should be version controlled and should not be manually edited. version: - revision: "9f455d2486bcb28cad87b062475f42edc959f636" + revision: "3b62efc2a3da49882f43c372e0bc53daef7295a6" channel: "stable" project_type: app @@ -13,11 +13,26 @@ project_type: app migration: platforms: - platform: root - create_revision: 9f455d2486bcb28cad87b062475f42edc959f636 - base_revision: 9f455d2486bcb28cad87b062475f42edc959f636 + create_revision: 3b62efc2a3da49882f43c372e0bc53daef7295a6 + base_revision: 3b62efc2a3da49882f43c372e0bc53daef7295a6 - platform: android - create_revision: 9f455d2486bcb28cad87b062475f42edc959f636 - base_revision: 9f455d2486bcb28cad87b062475f42edc959f636 + create_revision: 3b62efc2a3da49882f43c372e0bc53daef7295a6 + base_revision: 3b62efc2a3da49882f43c372e0bc53daef7295a6 + - platform: ios + create_revision: 3b62efc2a3da49882f43c372e0bc53daef7295a6 + base_revision: 3b62efc2a3da49882f43c372e0bc53daef7295a6 + - platform: linux + create_revision: 3b62efc2a3da49882f43c372e0bc53daef7295a6 + base_revision: 3b62efc2a3da49882f43c372e0bc53daef7295a6 + - platform: macos + create_revision: 3b62efc2a3da49882f43c372e0bc53daef7295a6 + base_revision: 3b62efc2a3da49882f43c372e0bc53daef7295a6 + - platform: web + create_revision: 3b62efc2a3da49882f43c372e0bc53daef7295a6 + base_revision: 3b62efc2a3da49882f43c372e0bc53daef7295a6 + - platform: windows + create_revision: 3b62efc2a3da49882f43c372e0bc53daef7295a6 + base_revision: 3b62efc2a3da49882f43c372e0bc53daef7295a6 # User provided section diff --git a/android/app/src/main/kotlin/io/github/dailyanimelist/MainActivity.kt b/android/app/src/main/kotlin/io/github/dailyanimelist/MainActivity.kt new file mode 100644 index 0000000..786741e --- /dev/null +++ b/android/app/src/main/kotlin/io/github/dailyanimelist/MainActivity.kt @@ -0,0 +1,5 @@ +package io.github.dailyanimelist + +import io.flutter.embedding.android.FlutterActivity + +class MainActivity : FlutterActivity() diff --git a/ios/RunnerTests/RunnerTests.swift b/ios/RunnerTests/RunnerTests.swift new file mode 100644 index 0000000..86a7c3b --- /dev/null +++ b/ios/RunnerTests/RunnerTests.swift @@ -0,0 +1,12 @@ +import Flutter +import UIKit +import XCTest + +class RunnerTests: XCTestCase { + + func testExample() { + // If you add code to the Runner application, consider adding tests here. + // See https://developer.apple.com/documentation/xctest for more information about using XCTest. + } + +} diff --git a/linux/runner/CMakeLists.txt b/linux/runner/CMakeLists.txt new file mode 100644 index 0000000..e97dabc --- /dev/null +++ b/linux/runner/CMakeLists.txt @@ -0,0 +1,26 @@ +cmake_minimum_required(VERSION 3.13) +project(runner LANGUAGES CXX) + +# Define the application target. To change its name, change BINARY_NAME in the +# top-level CMakeLists.txt, not the value here, or `flutter run` will no longer +# work. +# +# Any new source files that you add to the application should be added here. +add_executable(${BINARY_NAME} + "main.cc" + "my_application.cc" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" +) + +# Apply the standard set of build settings. This can be removed for applications +# that need different build settings. +apply_standard_settings(${BINARY_NAME}) + +# Add preprocessor definitions for the application ID. +add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") + +# Add dependency libraries. Add any application-specific dependencies here. +target_link_libraries(${BINARY_NAME} PRIVATE flutter) +target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) + +target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") diff --git a/linux/runner/main.cc b/linux/runner/main.cc new file mode 100644 index 0000000..e7c5c54 --- /dev/null +++ b/linux/runner/main.cc @@ -0,0 +1,6 @@ +#include "my_application.h" + +int main(int argc, char** argv) { + g_autoptr(MyApplication) app = my_application_new(); + return g_application_run(G_APPLICATION(app), argc, argv); +} diff --git a/linux/runner/my_application.cc b/linux/runner/my_application.cc new file mode 100644 index 0000000..acbc8b3 --- /dev/null +++ b/linux/runner/my_application.cc @@ -0,0 +1,148 @@ +#include "my_application.h" + +#include +#ifdef GDK_WINDOWING_X11 +#include +#endif + +#include "flutter/generated_plugin_registrant.h" + +struct _MyApplication { + GtkApplication parent_instance; + char** dart_entrypoint_arguments; +}; + +G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) + +// Called when first Flutter frame received. +static void first_frame_cb(MyApplication* self, FlView* view) { + gtk_widget_show(gtk_widget_get_toplevel(GTK_WIDGET(view))); +} + +// Implements GApplication::activate. +static void my_application_activate(GApplication* application) { + MyApplication* self = MY_APPLICATION(application); + GtkWindow* window = + GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); + + // Use a header bar when running in GNOME as this is the common style used + // by applications and is the setup most users will be using (e.g. Ubuntu + // desktop). + // If running on X and not using GNOME then just use a traditional title bar + // in case the window manager does more exotic layout, e.g. tiling. + // If running on Wayland assume the header bar will work (may need changing + // if future cases occur). + gboolean use_header_bar = TRUE; +#ifdef GDK_WINDOWING_X11 + GdkScreen* screen = gtk_window_get_screen(window); + if (GDK_IS_X11_SCREEN(screen)) { + const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen); + if (g_strcmp0(wm_name, "GNOME Shell") != 0) { + use_header_bar = FALSE; + } + } +#endif + if (use_header_bar) { + GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); + gtk_widget_show(GTK_WIDGET(header_bar)); + gtk_header_bar_set_title(header_bar, "dailyanimelist"); + gtk_header_bar_set_show_close_button(header_bar, TRUE); + gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); + } else { + gtk_window_set_title(window, "dailyanimelist"); + } + + gtk_window_set_default_size(window, 1280, 720); + + g_autoptr(FlDartProject) project = fl_dart_project_new(); + fl_dart_project_set_dart_entrypoint_arguments( + project, self->dart_entrypoint_arguments); + + FlView* view = fl_view_new(project); + GdkRGBA background_color; + // Background defaults to black, override it here if necessary, e.g. #00000000 + // for transparent. + gdk_rgba_parse(&background_color, "#000000"); + fl_view_set_background_color(view, &background_color); + gtk_widget_show(GTK_WIDGET(view)); + gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); + + // Show the window when Flutter renders. + // Requires the view to be realized so we can start rendering. + g_signal_connect_swapped(view, "first-frame", G_CALLBACK(first_frame_cb), + self); + gtk_widget_realize(GTK_WIDGET(view)); + + fl_register_plugins(FL_PLUGIN_REGISTRY(view)); + + gtk_widget_grab_focus(GTK_WIDGET(view)); +} + +// Implements GApplication::local_command_line. +static gboolean my_application_local_command_line(GApplication* application, + gchar*** arguments, + int* exit_status) { + MyApplication* self = MY_APPLICATION(application); + // Strip out the first argument as it is the binary name. + self->dart_entrypoint_arguments = g_strdupv(*arguments + 1); + + g_autoptr(GError) error = nullptr; + if (!g_application_register(application, nullptr, &error)) { + g_warning("Failed to register: %s", error->message); + *exit_status = 1; + return TRUE; + } + + g_application_activate(application); + *exit_status = 0; + + return TRUE; +} + +// Implements GApplication::startup. +static void my_application_startup(GApplication* application) { + // MyApplication* self = MY_APPLICATION(object); + + // Perform any actions required at application startup. + + G_APPLICATION_CLASS(my_application_parent_class)->startup(application); +} + +// Implements GApplication::shutdown. +static void my_application_shutdown(GApplication* application) { + // MyApplication* self = MY_APPLICATION(object); + + // Perform any actions required at application shutdown. + + G_APPLICATION_CLASS(my_application_parent_class)->shutdown(application); +} + +// Implements GObject::dispose. +static void my_application_dispose(GObject* object) { + MyApplication* self = MY_APPLICATION(object); + g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev); + G_OBJECT_CLASS(my_application_parent_class)->dispose(object); +} + +static void my_application_class_init(MyApplicationClass* klass) { + G_APPLICATION_CLASS(klass)->activate = my_application_activate; + G_APPLICATION_CLASS(klass)->local_command_line = + my_application_local_command_line; + G_APPLICATION_CLASS(klass)->startup = my_application_startup; + G_APPLICATION_CLASS(klass)->shutdown = my_application_shutdown; + G_OBJECT_CLASS(klass)->dispose = my_application_dispose; +} + +static void my_application_init(MyApplication* self) {} + +MyApplication* my_application_new() { + // Set the program name to the application ID, which helps various systems + // like GTK and desktop environments map this running application to its + // corresponding .desktop file. This ensures better integration by allowing + // the application to be recognized beyond its binary name. + g_set_prgname(APPLICATION_ID); + + return MY_APPLICATION(g_object_new(my_application_get_type(), + "application-id", APPLICATION_ID, "flags", + G_APPLICATION_NON_UNIQUE, nullptr)); +} diff --git a/linux/runner/my_application.h b/linux/runner/my_application.h new file mode 100644 index 0000000..db16367 --- /dev/null +++ b/linux/runner/my_application.h @@ -0,0 +1,21 @@ +#ifndef FLUTTER_MY_APPLICATION_H_ +#define FLUTTER_MY_APPLICATION_H_ + +#include + +G_DECLARE_FINAL_TYPE(MyApplication, + my_application, + MY, + APPLICATION, + GtkApplication) + +/** + * my_application_new: + * + * Creates a new Flutter-based application. + * + * Returns: a new #MyApplication. + */ +MyApplication* my_application_new(); + +#endif // FLUTTER_MY_APPLICATION_H_ diff --git a/macos/RunnerTests/RunnerTests.swift b/macos/RunnerTests/RunnerTests.swift new file mode 100644 index 0000000..61f3bd1 --- /dev/null +++ b/macos/RunnerTests/RunnerTests.swift @@ -0,0 +1,12 @@ +import Cocoa +import FlutterMacOS +import XCTest + +class RunnerTests: XCTestCase { + + func testExample() { + // If you add code to the Runner application, consider adding tests here. + // See https://developer.apple.com/documentation/xctest for more information about using XCTest. + } + +} diff --git a/web/icons/Icon-maskable-192.png b/web/icons/Icon-maskable-192.png new file mode 100644 index 0000000000000000000000000000000000000000..eb9b4d76e525556d5d89141648c724331630325d GIT binary patch literal 5594 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 X>c!)3PgKfL&lX^$Z>Cpu&6)6jvi^Z! literal 0 HcmV?d00001 diff --git a/web/icons/Icon-maskable-512.png b/web/icons/Icon-maskable-512.png new file mode 100644 index 0000000000000000000000000000000000000000..d69c56691fbdb0b7efa65097c7cc1edac12a6d3e GIT binary patch literal 20998 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 MPgg&ebxsLQ025IeI{*Lx literal 0 HcmV?d00001 diff --git a/windows/runner/resources/app_icon.ico b/windows/runner/resources/app_icon.ico index c04e20caf6370ebb9253ad831cc31de4a9c965f6..260f94edf47879274e49c769dc7dfe3e01f88659 100644 GIT binary patch literal 137918 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%0Ar9bA{w>3TSLqJ@W@vQL$~7vs*~8NYT}2hLAqd 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

wWi!n+ZY?xfNfe`yJG5c)`Sb-F6~-a!Hr;EVI(5 zhq1z~bnvXfzNr{TRO^Gd=q99cGyae) z3hd{f42*Wd1wp%9yY|S;`U@H>BJ3-TY8&I|y++;?7T)@^x$#Mw^+fyUp zuIV!KG4jlyyb{0<94GY0yIgUBgPNzBCvi-abI zfGj5mSP9;a!!C1RvQe8Xes2-`iR-37oH2S_gQGE3?IEwpVHs2?2!>&!@$JwwSw!N* z3u;+C6xyBy-7&%h;APo?JTySdgoRD@&Q71bpOUeI2~tA!lhRIjMp3K&0ANh?6-SYBohW|h z-M9TV+;i8yp8kN#_YlA|C(_cP9MU(fvNX$I{c!87sZku0GlgyCa*8OUv^%<+exoM; z)*!7e1~Tv_z)tClm-Faaiq(3Pq}OX@=083de!c26drfs?MHE|@f=(hCXx9(P5f*Pk zqH+$Q@C%P*uCmAVAVOym*Gp)%nLTW?qWYX0j0N;bG4n|H&~|4FHnT{ih3_?_W0oiF zc=co?e`uxS#W z|76Q!IdbHOqBAEDg>LzscaUiMJ8A^_h0+}!@CF|s=b+${P{{!&f3$tHtAg{Md^=2R@ie5PoukhEVbLtpD)Q<1?2Fq z%dsuM%X(|y*Bty_@3MUL`zFXfl8E_iux>E_V=%XiaxK{3Ns8MxRAN$E_Jg)fdTu{X{mc-JdV= zpp+Vggx)OQ3wW2Cz;8pDUF0M8ZS_xM^8qdRx#SOGu&Sx@D`CCId{DhQ9-eFYv0DW> zd|TJTGuLuLsMrBBF-2G#?CQdu*pgzdTAV6ou>%^*r;N;Hdd)=8Ys`YBj?bP=jH6>| zQ(tm-BGh}QrEz(#wI#gMtcoWwg3Qp%q8N&?PWg}zSRahw?fgM;d@-#r@)XT)E=-S? zYjNKz`|nXudVMeWyASz}j9frL{>vHB@E{tT@aC|x|FL%+@KqGsJ3YBKz4xAw4ulXO zA-yNmP(?}rL6jm*DIz2S0*Xin>0rYL3Id|?00E^dAcBHQlNM^|gqr!EGk4Es?q+Wi zY|r<9-XDjV-M!hnGv9ZX+6->FbxFXajCwhZug`WiIy`9ifv2urxwNGJ=yqnF zF>Q;6Kh7VtFUhad=gzy0Qe!3#-euD7<$IA0*1k1j{*eYx_1b81s=U+9UAdmGdM;}T z?}9zH(Y0r3aoNrFTi!f<{OZCf*D@YQy>-3fgHbJvS})SHNS!%rbKOawng8(btct-V zEu1yWqMX_vU$tUfo$THN$M*Ex((m%c_Q`|RnyO|Z8m&%{l^lI|f)^Arc>-V1x zxo?{t7IAgr2jhmVySAe4!tdAQ`}f+qY;xd-OGkBFQo3*IxuvGRr0+WX)5>Sc4*wK2 z^3zApy6?UH=>5q@3QN1++7(;AI(yTt+~f@ph97_KPU6w$FU+)jbo|hiCGT0jX0&vC z{npV*=>&GSM zd**7M9rKIFzh1dMrP0b~c503HZL_{RHrM5RL{qo#1D9VKxpPnIkcXa5h0z;|BTg^c zQnq)&$+8KbuX?p@@RCmgK4YVgKl-ATnNjGdZFi!7HGBEZQ*VS_YO%F*oe^z~H0}4z zUGvP>{pTc|a=N#+kEeB~DaZTl$~nJm*_-=T&z;-4UGa&l8)tWVYOYzY`P#OT_m7Tj z{_Zkuk2RCsxAi%)#Q%+N>unewa~6Jb_e%Dq|Eks3Pc=B!VBSgdyT^xS4BBFq)@bn$ zW0v=7Y`dyp#*y(KT4tSYs2P|s%|T z+r0O4AARtAoqp?PwoVCry!iD7Z$zxU@$B@)$9qkE=|}J9S^Jr$QLPrI7VqzWbz|z5 zD0rx=@#s}M@01STx4OZlZwp-pU+b{FY4PE6&2FmJVBUW!R)o>gM$yx4C!yeNMZ->DKu6so66}?{n*1vUv86dso_+wj0>|t2g5I zZk*A5lH1;o?K>upo#S^h@#FTH-~_VYe`kfIs+(06@qAzHoFLc_^!){j^r2Y=%B}>BVJ}AN<%N zG5h}Uy>BHgnjO65@(*p=FS_;GM_0ywl{UTg;mcn~?d*26RrINKvzG)WT-k99Zrl3h z(Ky&*@6_vXTLAqbK=ow&*o%4oQFpt0-*DMu(Z$n;56rIqqK9Ic~<;r#@S)y?JEPcAM!<%-(sr{p`2S9~k(_ z}#g)#kFc_y{hf1ZQr*V(WF&?N8e^H3)AXu zZS5cb+T_^Np&#CG{`AeA!AD+S5Fejf(#LVo++8teO~&lpvnc+hhQ*H_-zuHzF!U40 z!KIezn<{oKy0`Ok?DF%Qdl+8`v+nYW|D@Xijz)0B;VR?XArm*}eKyd#@TBKGn@J;s z=J)LV^`Mr$v*!=H`rh~z6XVWad~sdE(B-y`?VtK3s@~M(eQQc%Za!P^)9J!G-IHej z+~j_`WK5JUjs2Eawl)fkd~HJu`_w}}e)jF0 z<0D>p?dXHS_t?9f`9nDkX{0RuBq9!5X9kl(<5TE&#sWfdbKyE!xL#fvdJmZT0^ z`gr7uFD-MDc^+^ z&+uz!QeqNhv}>u?&;31{{q%e@yK4^jw7X{-?HdAMV< zpZ3pu-mAg9rmaew*KOpoD(S6#t;(FPG>Yv1>Cb&HuUI?w;OYyuZ!h=U{mq#-POY^0 z*5iYtFaI+6R@~cXo*Hs=_JwYC=k69?*xC5YL$9wcesBBLdP6Uc?he_-#dT>$tzWfr z@w{kveN@@-(DH%x&srLVIG(qBVMkyPzcJ@&;z37rPznzh+y zmp(YDN3P}Mg)ccd_O$P~a!N|!lJ_6k>)$~Qh9@woWP&deaCA)k@oy%jjmjT6<3sD-=VmQ$ThaTi-Yx^PV~79p((2DO11o|y{i~zqj=Oo^ zljwYRtz2@uEZb#YC-Pd|K>>iOj;Dy(0+gL1o z{=To5_34EcVLtiO-NqK&>{vf5a^M!Tp*HY7gWl!K9j}eqQtwFd!O2Hf<(0kk=9I;y zhi48Scc9O+x6Z_EHxBt%-kI|+zp(BZpWHRaHt+K}7Ibr%QK06m3M!oX2af&}F5g_6IJEPkP0@h~mkP>?CU3ZPsQ!sZ zlZU-{^&zCkPGA4~ou>DqN8G*|I{HT|Bkc!^hE}{b&cO;UI`$Y?G}Uoat1B;gJU6y} zXn@zhdbQ{^_`{e_BO?VTJ$CQkEtVaKtGq6b4BKLjUPzUIo+$mL_& z1zlcXoRr$Odr`Ls(L;=$UD31N*85A|?`5~K&9KjnM^4`6Uoz5kyyn?&ZBM+DG3w`c zZ0C=i^z}D!lV9`LWw$5pTFjwa#VsG-U%9zy$QM58LF3P!c>nFD#m>9;rC$1Gz5nnt zvnR(6Z)|+AXZfwVSHCDdGVJ)|+ap7aRt-1>uajK5IPl%P&l-WCW(R{|kBf(`~ zI^QTOzOrLw@dod%j|#(w|2X0NrosDn)@yKa_Vb}jX5Q}PZrtVZpx4bm$Xoh``To@O zJ013QZqliIZnrxh-g#r`&z?bB0zdq5X;RY@Gj?8lYu8WfHl2Ghwbzy8HP`bi9{2q9 zUj@x~d=zN&?4ZMQeeOPEHaF;}`-QDmjoISAy6bG87j5UAxZ^(cxdUuonAs9byR;VB zQNWKb&e5KOqc?1E9$MP-+k+d8PMUpTaXn~UKciRkE)0GcQ~b)rxM@H7>>U_!Y{38@ z&kZgi(Y}W*J9qI|crOrU+~3}~<;_oSg#q`bj=J&jlJP_OWe+(Tzv`?u@ucMygU$SmjBh^u<=b6XjEd{?O6>hfOV6Jf>owK-=2Rn-v735K zKd-suaHE;`m%}sP-fVj;Ww7T}YH?+u&)9Cy?`;&@Gw-c!J||{aotU!W;R_+d zQ?1Vaxct>)Uj!$Vc`kqX;Ok2!UOze4dsJEb2b-LXnrt82phdc4VBU#4qX)jc=GT~R z*LNH~lr?3S`44Y7^v#{LDSxcd`#Zd&%ODMpK+Ijz-gT0P5@a%N_#q+&KZy0yI`?~8p zB90eFJ6f80rXGE(_n_E}^03DvuJ(b(L~Jwfo7TzS5z`IZZ9&v?G`bEetA`MW0u6u;MFOhBXO zj4gg`7!tW@)S!A3@@)1vdN{s)#&^%JVNQ=5n{K#sXw0U;^Bji-m#v@o_0}~9;n79! z|Jbb2!_u9f^f`QcB@FgQ$0wM0O%HCp#6DSj`Or(T#fRNL4$k})a_*81k zaTl@ztQ<6(BhFm9KlEl(-{Q!hEl&AOb||wbsDCl;~96d4JITUS6gZKF&rz)SYpsIKj?yNY^1>)OCEJ z{=}8juWa_cxqsrTT{e1sQ#NPY3ikmocQQWp@Yss-6(1DEo1D7z`DE|iXRNv`e06e^ zN5yo@t^Hn}*z(?qW5HwRPu1M4XLZxwc~gGur0!k9ZoZP{Q77$O+o7wE4Y1CBGwGf2 zZ!T)JOuO&+ym^7a=bLoj9ys*y9IK9@x&C=&U%GE!;Q!*8+5K$ZGJebV=BUM82F@>= zv*Aib!3&Q<9d0|7_!aJs*q@tK)a~!;1RLhS{B6 z6fmN#*|w~)4F~ryyVdQ=Ot&8F*3e61t@Gwg+wODC_3oi`bc7Cq;?uylB|1OGuyu!I8WXji$Urc%xIyA#I&Mf|ezCHV% zaQ@glV|2^bqdT>}TEFn>q>^GYm?0YR&Dbp4=uao7#o6@e^87D@$1Vu&p8U;M@05Bw z&AYOxd1_n}v(vwPd$7gp&t(r8(RRouLA}|qH@nB3FMBzBc%zW=;kIr?=lj3XY3;?8 zUN;{V3>*WV6m#xZ({`^$UDtkL`s=-pG4^H+`<*zpDeT#|Mjmbw**Z1ntiRLQeU6VJ zroA09DSzt%myi#P`r7ulbJ|{i`oo#tuSdi*xtOu4)1W}(?pHVZxxD1jEpYQIv$jQV zv^inEYe3Gi9@{s5d!ugV3k7d=2p#JkJAB}4LrQZT27Y9EtgSY#_rrH)7M=g(ewXP# z?AmtT|2uQYxCoa6Y?w*A(Y?elei=cVxhgeB1CB;!gXPd_M2pnAZmd zpYPsvNHJVxV3)pmkkO?b%d$KgOx#w|{kaA0-TFU@JUMdvl;Te=4*lNP_`^AGSQ*-`Uo%=WoEVN%kN+m}Y(9J%;WxAq^T9=$iJ zxux0Cm){wCt#_C7#a{%x(Zp!iaQ9^q{YpRFGIxO2{*liv-n+_qNz@BB3y(fD?NDqF zJ@e+`6%Hot0xV{&+m^g5r`)Iav~ii?r#(JgYM(!3(c)FMyWVm>k##L$V%Modt<0vb zxj6Wf8|8ECthSzLb3(JQbo{JbhY!!bccAIx@|i|w2ZS6sKXGm0^fMU?a*f^?6ZOpH z``y33HZU>3=;7QC&kl8USTiZD-N?7bUK=@}MH|O{Q=RHA?H@dMPg(B;exXb3zkeGJ z=gPnpK{HDS><`LleRt!AJ+BoGcQq+-+)&bBP4`(-x;?vS_@GNC-+wX9sI28XZ)_>t zR=#3+;<;Jl99tI0yDs`-;Vm2U1zRp89~th`|K6y%aFm<#-*p&Y$YS;u-A<@C`*oA> zK$GxOJ~wZ6eE#e7e_O-v9ov%Sx_Ii%k@Xg&)N@_5eWcg8!kf#!x;5@a_d~|UUu=24 z%c9YaKMq=b)#!~$CheokyWcvw9DdzzQ@h?Ra{_JN{W9*Y!0*OXjG0!};{h}6rzw2r zjArItBlzTJx6E3V(S2+<)Jt%MG5!m{8hl{k|L+GIM`i+bG*ijUpj4VUtP@SSo&FX} z+8^!z|8++~d;jhq5eLGC@Io9BR|_ypFe@;PWLhY#YcTu{ejoo14flcj!hPbt>38UN z=~!UXKc7Fb2dJO1B;OXXCY%vpTQEB?2QVivXD}BqS1>m)cgZ}UM5ATghTp;O;@`kE z-+UjqFWe{Yo4BFm1RfI|BUJzS{6RfHeX7J9{SvW2Ob{Q$3Nb_c5L0h3Uod~LK(Ju2 z5U^0NI+BG!iAKw~4Znlm#lOM7#eLwuaG%Hz;syRD@d1xT)Q5k#03Gr>KZrZ_BO3WR z_A~0U4H)`1Vu8Nv1?C5am?3_MX(U)QSY5DsV6k8gz~aCfg2fAl%V@X_zk}b!zrnx7 zec--upSW-Q4g4+qP5f;<20Ru#COkGnT!2mgd}`4HggeGr#2s}O{T%z(9t^b^ebEOD zu|S^<2SbcvOpJ^hX^c%%?M%$`+)b_82btUSkFc;SiLtbwUeD5DNt~tQ>Ub-sO;yc# zQ=FC4>iU+BOJXb?rsLn>-{L;(VP9I zjjSBEBx;;bC2L%+rD|PorEA^FGqi3Gv$XCN*;;p&qxImHE0>-uSL?~wWotbuGBxfG zGc@ky=^FQ2sT#LyNmj0>60BUdHn4PB7GYsu5@>GI+sV`-9}XBb12qDV1&;}j4UZ9z z6^|K@UDSkscmN%u_^9EIag}@>br$0=`dS27T}xw=rmm)zg@E^%SWAbGn`oR40M-}N zwXTmdwQej6EQjOl4!C+$Yk9Ce53pBSKCH{vdU3;T$d7EWERDzGG>!YkrdF;88d^Gk z415>^8c}FvY}yo$O*%$ARy<}rcG3iF6XvMM?SFVsnJbgdqrYPxVJyWQ4s$Nl)-bRb zQ)A=C@K~n~5f-)+8d^Dg-c;j!4t%>j)7q6~Tf2dQU#nQIHQ-;3s;w@c13Ng3qt2H)D#WqN7!8T#ru#FTKuv)l+voAHgcj{8%sUG8PtfUnztkAr1NW(ap$ zFXK-53#F<8mj{7IdCtuk(BKc~#tLy^O!RoD0;X1J&Wra{&YSAo9Ra zE=YVJ%+*Rs5AGydxo!(Fx9wvJZO1;4`hv6ob0O?2^q2o;4&bp>X4{?n6ch> z!o(Ew!VoY~2mVg60QCru2lEt+Rb2BmrlyTztnH_#*ty)uw1-#^MkUs{k?-3pd|%=K z#~(Q$nv6YRuH#6K9{#8WLJX*`F5pf&P$T{|%@6#>oRIKu2KXZfvNT>dATOM*H8sQQ z4ls^l-(nw&IUy|m$3E!$I7TJxF<%Kn?CVj}P#D zDKGr9&KY5hs3{(x4rFV+ZpT?UPqT!+g+2}d!?7XuIn5FM)f^z~ah?+As&Kv{09M9C zX>DHv?78M=I)Lws#{C}fMZGs**-|W!apwLG7?R)HVO_<*=Mi_MA@+Lf48{V;_iS{Q z1M!};po#`4bAjq&0pQE?0AWr*%nNG59^(KR=)jHo7EZ5WA7fujeU5$qSI-qA_89YV zjE{5GcpekytRlm-Hp7zboiArPxai}K9FXDw^1%@H;(Fu(HyL+WmbsvUzr+dheLc)2 z4#-?EzyZWR2RVTFV_k>`HS&PY86h92{s+zvAP?YN;^k-yhhf;)QlDerBL;}YUokEu z?8RIk=d8m*HP+83**l$4#a_~YERhGb&;sH^^;|$+NPGaCc^ylL4{98!HWwgXaNLmt zpdDNbp#B%cg6iS{&JSQL$k2G6i7>Z+9{U^&`<~_oXiNaB{k_Uvl zSnA>d{0(S>jJpaS)aHl9b!wQ4>#D;aw-E>6ywO^F6N^N|K*9ns`7`4H;!nDd_uBZF zo0vq`v$da@>Hyd2s9;a)vK-a$uV$UVgQ^;U_$y4|_Y@Df|0DheIUwo-U@OIc(gP8H zUf09hFb_E12J%9^b48RN3T18ZM-Jp_z3;(whBM8LO`{PDFvLVWPXLR5*hfwGgX>t^ z_DObt^LXIIOn&a~}H8zQCVCOJD-4U+Ec7mKw#j>2-U_BUUf2Bdp z$5^0dQjU=A0Jv5$)CCD|Dn;K{)N^2&8)?5C;H6i`Wyv@PpboiUF3$&bbzN=IPN z0LLA%SDIc-&~Zc5g&JeQ@0=@!bA}a7tlZ`!CV(_vS4{K6n5QFlzvn}~k9mbW&l9Y% zE&|;zRl~h<9pDW3S1~p073-?vui%7$w=x%yv9H1b*aznTU`g0hDeHg^dp#Z?_Q(q* z?zAjvfrz=XF6MuF^*>;K0LO)Jo}e_`+`b4f3IM~r9I>KY5URiVBlWzB9S^8faDX(T1}-2!Dt({o0taXeD02Y5BkBO+ zFPn-M2>Acmv7p*GpmF~a?s>)QNoh_1_4@Z}0L}B^*aGLA1EX#2hNU{eb-K=w@1dz^ zzmf}8Gyru0xj>~MUdS9UfW1mA5cMF(9XRN;0F1VkBWDjt61Y6MvMx@8fD|m6YJ%w3p*9;tzG? z12+{usNzqtK@WR({oJ57_>&H(a6un`i3@TbfLb8vfLNC~0NX_^;2coN0f-BPHWI8QhlFvEF4%maR_29WRLoFc!b!_7*Q+|8<34hW6D%JTQ@Bld>aiKaMAnsY! zVUODg-LN z!}TJ=VdRJN!gPKRu|!O3^TF?-_TzbFyvD%8&dj`if}``+3>V1vz%oUvqW_hcXQ9tm zYk)QQy2uCa`=kNNQjHhL0f7@b9RMu#^niT6noj%=b9$VquKz+nc!Vs}UOl$KY?Z@#0pXU#=w=YU{cDYXYQ<>=kSj$|XI^wU( z4-k8d1%^2Q*z@gJ5*KuQsKNun-cW21w4f4uz+2>j?DqzEPz?vTHmKn*#R1fX8e>6i za>760`T@{@>oHc&I3Gag1!_AMMC{SzywAeStWG0G$M*^IDkWmgIY7AUFc)(GRs1m@ zByM0`)&Y?R;M=4Dgnvz?f(IBYDmkFzgL*80Z8H8C3smBPh_z7Xc_1!>|I6b;^mDab z;7^PN7#lDS;QfV3TKD%Y0Xx7F=Y%N_L~N`3;C4~_-Tk%NykuwRpDX>G@D@wJoNIx4 znFZUp5#D;G&iAv?|5Z%JUxf!bjvk=>qDiqpiU&&EE0+P=8npo8z03!Z8&F4I7fhKG zsOkX428I6f+)&_zTKpH+DdWF#neqU5R?*MF7PfhSCtjC{alAG$0P)8;BU$@n9UMlb zJHtFb_&EB$IuF!wCr)I!0Jg*dEcNh*ykEi{OETg@75s?@SaK}@{G9+3B@a~mz7l`< zKE?&T@qo&*A^c%Ia>Eb@4B`*i^EpB_4oK_N=7+^~O1zcJgnypatD>>SbrfLvBryPe zpYnbeYjg9+L>HH}8Loi6WSLOv3@~>^6FE`I13kR;@JBA_`??zb#Di+_m$?A_D&bG1 zP8X_be-#eY#Di)$KskY`9+1C_Wi`0VV?_8)wK<`IT#$G`_+y!7?YYL*)B?{7(Rsm| z#sP>wo$GP;x3x`AadA0A*i%^rf6fUV_J}+By*~cpvV=e9ggy^Y7iz}^^m!>a5b^=U zo{aFPc?4D5W$ZB?sQ5pws|kOF4(QDjh}esDLp%`Tz#nn_K#tb)Ot6)GI$(-1pr&&| z6#Hq;$1B#^c}TjeYdPVrEM@=aI)GXrnZ$ug{TK1q)%iBSo1ZJ-@qoAh+hGow&JV~q z1Kzsx$e=gUHHG|IV)?wWG=Ic(0Aqt9FOc#=QkmdvU`5|0~%aHTYHO3+z_LYbvk2TWm^o2Uus=ivV> z{DWBM*f=(*pamPdW?& zP%jLu!}Eb0%mqZ#(*(c-c+kwmSaZhV@T}>8ul!Xt>-yFp}jv!u{JqK8U$Np?4kjbRGB(St!)iECkjY zu%`m+vS#+aIu58@PsXn$GjRPtfi!oJqH%u@u|!P45L-j%1QCCV{m$NYcJV20u6q&l z%9yXL3qCL4PW;GnMf?SmIM6aMn7vrohAp2qgB|#KJ3I5sF?RXBOwxD<%*9_ze#Q?EH z-1A($*|UjhZ0^X>Z0BcRuoFN0$S$5a%YXOM*|Y4|qd&2|8#l8>CF9w1O*2@&vkxou ztHYL#f1MrLxm)*}JK=Z9cI{=0Z%wTkZtX?*WcP99Mj9E)n*2?bF;`OEcWS|G_e=7+~*)_#-E3 z!2`fP+s%V@Z=As1pYj$vbL<#<_}~Gn?sMzfHMZ@OwQOKsGuA&lk6k!@+ThnefA@VJ z7jP^7#?mEXBza6h==et9{^`t?5jSyBBaZ1cZ9Hu!zyV~+-j z{Mm%MaUkf6lP_B{Z;`>jsqKcciQ z#eSaqSz1{5C%U`M5wWicf8qn@0dj-lK57H_e&+^pY~zZR?BV_DeO|49u^M7H?pq2yDI%N)s%V~CAa}ZO&AJ64d4v3i3hw$g~K292|@FaJ)4Kn`j z6a%XIJ>gCz;g9~#4e-zR@nuUUOk{U&SFgL(;lL^wtEhng417fVG5;eS82xlNb{72j z_k61RUCax5#0vNW2mUDkzk1w9{7DC} zL@s2zd$51anuX45us?7E<^(tv_+Z*JHm|sZEuTJveYayrt#bwL|8TE~4tvmH;K2Bv zy;<3%OV$4F1Bgc_4*$s3ELhCukA9Uc89$M2TfK%|y>Ovgy`h~F{`kyN#2@Dhboy@? z|C?pk*r+y7vuEQ|S)WE}>K32Io&oHeJNxVKSIi9|{$!;6Y9+qM0N!12HA3s04j3C6 z1JJxLzt*dPr$?s@54W3$e$>6G4}n{9N)M^!x#w z2TXGE8HCt^(Yav6oIZpANX-~WKM z2n^DlGXTu91w#(tbp$N~L)ey8tE=4)`ajMO>+*kh_EM|1e9U0zkAC^?do~~|pN|>D zc_OOgxG~?wo6R0Rs#@;J_~Y{i^!(rO_z(S`No_;)A&$LmJW^mqVqNIGAnyU!5xNaBK0|CM>6 zS`GmIUy)|-H3P7xYXOw^2I=9S=<58Q4tvC3uo^fZVvqjcJTQ=LU9-ku-(9_Uk@ZQ> z;96gaeN`UdJ*EQ-nlqdaG4!GMufyMqy*XeIyK(iZ>enAZ{=MY2NtM{cc#$v{OT@o( zbOW~Q^9`!|!If3sZr4oLXpJ&2tm>%;u-dV@LOZ^yrpZp^^1FNfde zJRtuUOW3B&2MommVN9quKLGxpsdcY4{wWgv828nEU(^HxJOKYM@b_n5eE6Y3%x>Sf z!A5rKq?;#{@TajOpF5EB0P%mdM^A=1yP=Ql|A2oE;QvOy7ufYHS5&`_^T{h`&t=U# z{pEQ=nlI!!K={Kms_=Z_F9#2)?gv+j_|tWz1-0^j5q~&l%| zwtm?=2KR#-IQ}qJ$aVpL0ehuWXFhLl=#ReNv6DU1Bw3gLqxNIosE7f1E?#WP0K+3fIxdNIOko@1!bwGOgAKqb8`HI@ z#(6wG{zv>>;qRdA)ied>oemm;pWV56i!GfniM8?z=6N9bKQD1E0JzXQA(efzd5gi= zk2}}l595D$E}0(wZ&#E5ar_&rJfjYIAel5LAdd+tFBCOEsMnMe0{&~jw`(*0b4&Ab zTa)QkiGL*z5P#GJq2yeEWylqjJjek2d#9zbUw`@uyUO6_=>Gj|bl0w|Ff5Ga0N$wm zxn5qZO;|V^*ZWy^?C@cOe@h$m@potK!lT%R+c$@5k1^_a4Dyu*CDb>y|EK zQw9&_a{^O`zR1?U`yO2LVL0a#cP8SGF(A*~n~wo%nm5ET;`UG1vpFx1X5)MGW|R8# zWgkqL#(vs=pjzFc->%eu@PB?isiglk;a^Ykf0!@U!(QS6e^#j)4+wJurK|&(3t}vQ zGS3E{N$TYHF5oN9|03q}(L4W>5#%>5)7!m5#-Dh=OLgpt6G{%?IB-~p4sh*7DRr5_ z67zw3<#*vc@ok>#;c{(1diY}ufIP5!qXf1O=J2aKf6Mm|^FjCT-Glk4J1|#$7jS=A z+n*KuAL2jZ?*`+)C&AwU2Xr~1MZT=Td6j=_+4D{Q33cfIa2_XnAnW=$mj2A&@ZU^!=6}zkU4%7JPB<8c*Y0Mj$X9@miuK#6&xVUsk#OIPB2K%dM^m=jvgaPFt356;tnziSs8(V-*j zpO?pQtZ3*%_~$6+kfmGz?#6bG=xSkNXif=%e#mwml{J-?Fm{Bz1WQ5 z!`bXtMzP5QUtmKE3t5M{by=>rH$RVn*Aey2d2;+Y7bN^K79a=k9C3lSAM4s6o{j9# z3C4&++3b;{*z}<#K(4e4Tn%mKh(_kKHA&wU?$Q;Gq^0XZI^{$regvYA`p`VeO~ zy#5!T4XeENM~A*n4|opfDKXkk0Ed1 zbIJVN5cD(54dHW%WW#$6q#}^R!yL8~?#K)^MF>Sre;nB;lYcue4+mde+hTKjCILWeP0E0B?oXB zaaUrlrv-BSe**lKx-Txv*h7EGbvO>Ji?Kk@|KYnFe<%f?udKs*i33<7{vXYLo6mPX zgliTn?E!oE@FBmB4f8({f1UONt~>@vCFX}}CSxw~K!H2)0Iwfv?isw;)XWU${nYOJ zkzkh#8VB-ufP$EaKG}X=cV%Bke}gr#fLP~zKpw!p(NGJh6gdI-=fZUZ zFSTsT&n?b-rI_hk37bA-7;EhZ*Pf#8izdc@s&o9|domBCx{?F5EN~&$&hu_TKzJWO z*U-3M241QV{x}byZ4wj^R}d0#N)KBRXG3+uAGZ_!h^tT+wE*XZxGC~N9S7jrCBXl= ztSt7+p+o$BAUvlh8s0m!YW{qE{pa{gTo7>=>x8+oREq=11=Ij;m3g5q9>98;15gJJ z9DqNMM8+QVp!WDTbMgN*!OJfWu>@0I^C>}IrI2Glh?l1) z#DEpD{!2cuuLtUWFZ()iflA~7n20~sxenlVfd@Pm;5j6iE9eJvfJ0zzU~uc!vJGj~ znhk;F?ul>>4vZsZzbF64Qp8-WbKK!?_&o>kJ>miPdswgJfs8+F<9Ng0h`3{2hyz%! ze2)Qalg5iW>;X$9{&2l9z2}t228soG_#+3v$lujUNduaD2CWQr^Tg)>*GBt^2&4fR z18njlLI>pr`BZQY_(FRiAK-dGWpx@r+X#Ef|G6fp@Ia>n(5DIxP>#T_EdY#Zen7v3 zzY{T6tBcrEoiG`_ylj;Kgh<#1?7r6NUm>nG17%`NvM8B@>hhl)GvxB{Ji|Fu$+5TRDzkoZ{ zYr>tjtKm;P5KGDjC4IpBPfZW_dgREH@Ib_!>V!FzSwg*XJRsptv4DKOI{b+bYFdEn z^f(|ba~?>1Ak0bsX<6WatOqI@fY%VV^sTed+14Jf_fUJ@LrpxO7{K$u{Cd$X^F#cv ziTI0kSql`L$oBE%u_9aKfK=D%0BV6`fOl0LKl@YNj$*0WJ7U4exALEJFf%YIFGES0k9uQ126~B6o*;C-jc zTmbGrzm^{y*%Cm0lDtpJ3FH9I7g)sv`1!Pmsw*b zz`t^SK*G8T2VftD@Q3wukAa*Q%6<=h4;lXDQpUV&NyURJ?2YpDs&P(ufUo`#o+0r`H0nvyTd>#3}Tms&5Jb=HW zv7xFC2;5NNz;Dt4JublhRW$&xQ{e$}fOCWNpGx2YaX@c;AaMYBftXk70M@~j{*Q4$ z!kkLV0}y-U06eqqZi~S1=MXb6#ICyeKGrwdPrKi3D!0pt?!1HAS8pXY&ajDR=yeW|3ns0H-QYR&_~ zUMdNHd^Ukz{FksN|JU(AAAeB;2zM%FEdcCsT?_Bv?I|JQ;eaZ}{om^QL<&6(XdPE? zKwhxlJsJBdIw1Hz#(B~MivMCM`M4MpD#r%EAq59$S(yv!%^j<7APd*2#R9;b-(!OJ zoDlw8^N|CUF#x$hIRIgfCC6IQ0E+z-19T<$BVb*LJ8FQm4l(E259_45h`(N483(xk zgVx)k!G3s&+7G_(j177v_Q@WRPdL_2WlLUase5C;sM@^C~!bGFI33`(gMy0 zMJ~X30X|RH6o@&YA^b59pco)x&vOAK{^^I3Sj?|HE}9h(C`9JO=>mNCU7W+^MA8PbzD|pZq@)d>^hkz1=!Ax)*?k z=lKw;-xK!H^1K$OYv1kN(e1 z@_jumKy8qWIHAY~Weq?MDDcM^U@#6y8lb!1SQiU;UB&;o?xW@lIe>^e<^tURu@p3* z*7zIXff)aFb$$KE>rM*;!q+zp48iw4KIvQ^VO&#bVq$E}<3Q`i4GLOBhMd*;K4CB7 z5B)7@0bwrZ15#eV*9&6+hNrU&Ufcg?`M$^j)Buaz zhV>)c#72La69D(?`U6Ig6Y|*4Ra9PhJ{ipnpbU`jykgpXYy}ZWSNNO&;xCyl7tnD4>(y}pwV*2g z@VBBq$hm;J7AWzTb-)1rqyakrhkbG#sKmVze^{py1Nb_F_>%@a0sb-v09SaoiM|HF z{savW@o(uJbfqw=ero_5^L^6&KNElC6>-4a-_z5fLqgoE&BBAqQ3G^ViMu`zU_0gn zdSgTQE?SI2Yjh z5yTwF1u_Q|*AZ|HP{Us(2Iw>a@Z-2+3H#>;brE~0qM$>KwkqYV*!r~dRm~5 zzfKEa9mN4j3poCiCo1znDHqi9f35*K{AKKs2MYY<lAV{3$*td4S7GE{ML*_23CPpq2;d`M)~;ReWF1{{eS3{E-6^ z4^aDw4>(WQIxy^b`+5y2=40Rgk@GxiI9In$&IPPATJ2NG3Ef)P4KK~+V}i;UQ2ST_ zm`HO2JTHVepyPqASf6@Rf;rqWq19a~+fxnlzP^kf! z1L*PqSSM%ze-AQXt`-My9pX=h^MSGs2)HBu9DBcz(vGo>x>;#7cwXNOIv=tBPx!vb z31jIv%$=PaZ8{}48Q3biP8o54bO1S^9}55joIBQ=AE0F@5oakU6ytxDx`;c~Rqi=e zK9|T~4hV4}6Jh{=ezh_d!1d+gyN&RAbHZING3IjvU8g$YjCFX9sm`E|nvctfKl!_| zlsJH6f|kBPWu59Z9O&%m$e-W*H^H8G0Mky!JQjop_&9Vd{OnM;25cf(%h093dRG>M9I?vk1~s<3Xj zUM$d$0TdGeA0ZaVx=;FF9p;EV#~m;=h(G8#ae;7`N_-xLocjx0K>a7vz0(Tzq0oQ6 zti&FdxxWLh&Z5D3S^p)>N&i)10FDV-`G=G}-5`Ec!yt}5<$8Zt?5l7fGSJVyb86zi zHua-Q`T0U=o|tk1eJHu;8pFbe-fIpK! z;y|Si0EQ|Ypco+gKj(x3d*X!10TF-lfAD=gk60L7r}XK#Mgt>#eQ{p@ub$r_EPrcB zvA_&+LhH_HO}n;>i#eVfq?;q6@nQA&1AY_(s1$LhI%z-Li>kXf9rZxs0^yI(EFlg^ zelP34jK97PDDfvPP{UtU2b8{#%S!AO_-8n{@MjmdtrKzl>G;N7U7+s(0JFcj<{RRO z%mEl1T0Nbb*z&2y4Zdp@7AVaR08V;i0$9cvAjbiy6Yf+J=3*)158vk;fRga%C2~Q) zpE!XfVK4bVX@KroB=9#v4A85qXnN@l$@lX;eObrIy59lzEv>99`Tg4e zrPvcEWDdXzi%uztv0aiHzXy5YT|OSfa|U|j0bB+nym>w-EDN~H_aKV+OL$j4j|eap z@For5F<;UFuKfc3ggwRrJj7(gp8+?(9^X{}iIIj&K0R&)&BtBHA@>ECR8|68#a|IXOd#DsGoJiyF#AI|HTNqzKp&+$cEpQMiM!to*J zL7U`+(5`8T6CpP|1J{*Hv7q+&(|zfca{>DJlMblk4>-v>An`y=18|*)JJz|+OMWl& zKnNwhfOw)1^_9iEZNIL!m#o&r5yt{}p>^9{+F-z<(1#(*`3rC*0+dd|vW;Ypr4(OIC1`z&S@0~&G(ZJ{N9ha>`>fGwmFn%5Qe0H$6H|F=K_1G8KFKGWO zA8adWfoW!gx~@eTDMe2w#&3gjNag%oGQw+-h8L=K49^EzOOCHH;7|M8jjqyvPv z6btB`mx#AG79{@{OA&vJ3y68EkdTTFb?Y7K)+AwWm!?f~^5YufIUBfGHSWP8k{VQiMRvLrQo`Nb4I#%6#(x1odtk1JiAn0N4^dv zz0ZpLUB+F0*D>UFzyaC7-*uV~d7K-}*FcVd*Ba*g`Lfnwb?$VmU;jksMvdMtN=|;R zQ`4q(!+d=3`iy^YuL0y*Z00gywx0b{X-VNl8Ohy>(vsfpoDlyN#E3JX z4Ue1G31<0$exMIJKFIH|P{ki`CCot!bnm$qaF;lMb4a~B@jB;Kh*T8h`xX{nK2Q zr6#`!HlcfJ@_eurJyOt;xOIn;TXNF;?#am$ijtFF?3$cZ)Fmk?r&DrLRELyguV#(n z9isvR@jeT}7E8pNexD!HpVQ=j_F7F3P`^_t`y%2a8I856#4(s5qwk3EoAyJ$A(qt~ z+CQ8A13e&OLv_OMNlW^BvHTA->7Sqcrw9J&fq#17pC0(92maU|;4iZ)!F`%mzSmCo z6Y}zP-LgHcIHg;*q-EWrk&(1qLCeLu758Y_U$-pn4qis6Ti#0Br6VYzWn;cw-kp(A zF|K$-n~jW8aarD-k&(Y*ng77n%J1_d7MA%BR&F-pKPW6?i-e!!2cWl{%9z|b{5v=R z;c$2hmCL8Z{lfum6_??Fl*{5~JV3o=I6%d+&|A2rSnqJ5$CS%@hY#Bo%l>+Y4-Kkm z`IP?g*ejMTx9V?KE}JU0S6MF6|9ex#vaxbm|LgxO{jc?ak`Fa4Z`JRhD*SuG?UtwX z_gAC;DE&+6kBa3g{;c$Gr5-4jtLTSPPgsfA02O`ODsBfoJ0&iI0P8hKxeR)#cfg>h z%4NL+V(=07kIP#tS8zR7E(-_1h z6afFjCyoFASN=!iYaE~Byo@;*UIUBsZFn8DXt)ly;dk)6_&4w7 zvoSGi>~3b2A7pObCCtLMf3&6j$QVoe(J__|qp==tVb?#%+@_0%sV3jn#2nvm5GMUC z?gRIQ`^3H=UO@G4@xgW@K6uUmF~e(s{58g=4gAct?V*ih8(TT8O47I-NYlEW&(ONv z$kMvs%hq~SI*tu6vuUp}HfwkuOZ!QQ8mFDm-Yc2bZWZ|6GXB0&d~Y2$4=5#r_UCCm zWy{xkF|u5(S4Eb_^Gb@wZD#{Zr%B#s+5-Fy>9_DVi4RcyOF!7}s8M*GAL1S2XRc}6 zP~)&H#oFa`rnM_?Grg}(Y=31x814h?59)&g=nu3!=!;B^=jkR^uFC?=ZQ9~*O25tT zC4%~2#Rb9~&x`uFn^|Tx&^jzgwRS1RXB8{oS@2u?fZ9)Gfz})P!5jJoo=>XrENyJ% zvcS_!lZD3sM$gE@WBW5dxPOdO&T#Wqc%+r>kR%)DA2azg``|u9d~UPKdmH}fKA?Wc z(0Ke<*TQj#xv>d`d%PwEkL}Ou1JpQ-M{Z7L76}cl9hRiqy4;~>7R%2o=g+Q&>nIfc zK<_ms{)?rk1-S}65Pd<(1?&gVh&!N_OI%DX6Y$uiWBjB00Nal7$KBh)DmTH#Xne(Z~??{E>-_y5SStGf`hwc8SBgB~eSrNSI5f`ZKR4V%*PwRcVfu-{RXgg{_ZT$daovpW} zrfISR=$+oZ?QjhyKHmt8x1UPDU;o`F&|Z88j?n%bsB=U7xj}pFu-(K5>H{4IRQsV8 zdVqZ)_5%V@KTzod@&PKvK7btYe7J>u9<~k45C_QbJ(@T;EfDYT)%64L zp5N~erLz67%-;usZ5K`Gha9SNKY+H`ONQ+hEEn32#`OT}e^4K!XxtY7@|YJH(gCjd zf!5YZsm?B^)b4Y{_T&AndM5V;v>l#}uGfC*3ursGAKz!d%NqIs+b;Kk*nX^wJg9{p z5D#*+UZ)^0N`m$qiUmC0H*|0u18uLMd;WAKU@komNU!a@FW}x(d^R|}4+Q(bKtJf( zk9{B+aezvJ2YP+*ggj7=nQ;C9#?2Lp8n-dfezkmnbKk+jA~4z6d7F$q-sj4#vi;Z( z^jsYMzR>jpZ#(q??+17`Fg)8-XT$-q4`3a&AIm?e4@d{7L>^>mJ-0cTSp};20Jh&M z!rm@B&DHfX-S?ySOc=4<$OXWj=S5KFxWY3rfdiTFoEM4>8TJr6Btt#Sk^2Dp0+#tW z0dl5XCoj$i97ppU0pcOP=a&q}(c}x+TIhQXY$LORI#{-)WLEH9AxEILQwchFImXHf z^I{wqV4LZ~bwA$O=_P1;g=+hy`=RmKXsCw;-hOOI%hqhkgh_18q9ttkv>B|VYj@Tv zAcPIfZ_eh8E@5xKQq1O#8pC?T!#lhoHu64zw&%Hcv;OJ1Y{8hZY|Z>dY~_qOY+|pz ztbK44>)kko%^fkC&3n0+y*;v+^-s;^a|s1bK5SgqUTpr$C2Zb^;wmFhcAJ6L&e z|32Hf{tNce%(?8*!-w*=g=5BXF0}FpV&8qWU0$zNxpKagJyX9a%K;vUbE={qWN1C! zhpU@$t_byxK4u=)+MrZ7*FAJEl-@nD&=2^mH0*~wxcBkH88g}AM~~DFfmJ+y%x>Sf zA#ZyO%j0_V;_c6Y_p8nt{xZ9F_pZEMS-ExnI>W!A&w|lob?x^IVh6T;O{-PQtECrs z`?D2(Ahti-+H;S$r45b=sQu^%=5_4t8m76sp2d4bGq9}+!)Jxz{oaF`w_rD}Ue){k z3#ZSpJ)1VMAHVsQ-7hcK+eYnAw{>DY8z-^TKmVe)z3k#8_U)Hj*}<=O==B?YiQ3;% z(f&I(Z?RA2E@bacc$2+{HgO7@KeB|i_l;mV8k}c`SSe@$^+B%I^K7J*13qIK&(mPr z(JW$JUGm_5sq5nXae8%*zbpIK%vp43ygayLCwndG9^&k)v!_>-Ma#E6U-((+mBtnaFPC$m(>1NiuPYVcb;{Pif5Tt&J1-i zTcfiat<-j@{mMSbv-Y|kZ|jb^Amu^4{qb%touK{Y%6kN{59pae&HMw{w_CQz$A|v@ zN|&xI-O-spI~ZdEJo|&~-LzT$4z_+I+0C`uk!dzB~HxOY;vzmbbmA83CC-ZLlPD~oly zZyxZ6d!*Qref#9&!(-^)B!O!py=xEq;9oOm%ip2)V~pJR;R<>Ey}RXXWV@%}+2`>5 z1SdFdh>!R#gy}2ZYG-?BFChy0M*kEJqKz$g$p9w8UVs1IJvOFuH->ov zZ$I<_&MD3x{VKzlK_6^Cz6Z`w`?K)e8jcr;16bBDpO~z1?WfZIzPkHo0dwiTS>%EE zJiS~WANJL{b#!PPr+LLC{CTQ4UP_1Ya`z^Q?9|btmES@AhxTKxggJuvL4RoG>92bZ zI`E)FooKFw;&*uaAvaQOf89nrHpp`b)CWTQ^>`qS7oh!pq5Y!%nKkuvdlv2~uFyS8 z0Q&&)9Le~z#()cWkLawIU)IA1Ik4!p32ab{maMpY5739L;^FgHhV4(Yb7aL`i&**X zJM#8BH*d0)v*xlFTNH9%*u3&%_V7Vv?8h&1{$u;StNMR8L+w{^K!0}d*Qu)gpvA8rh;|TT z{(MSedNc7%jH_30sX3(x@iz`ngKzc3GQj>8XEd%H9OV0-eHQceANhZN^`%$~zqx-u zUps$3f9N*f@t^9SbZO!YW}K(8v~e1Le#ayH=*J(6y8rU?&-w4)d`qkkHe7TG|K$H2 z66@nn@jJ~2bUwyJ{L{WkwgF*hk^Cd~x4pN;nh#gRrxt;4{rW#R-;!o&&a&(mu?2K7 z2edZe7lWAQ#jb1zU)0#hSM>Mu3)|ZG^t?PV7d*IeqgK6Q{FnUGIkcDuXpW@)(}L<+ zzM^M3zu4Q!hw_Vr-T<+I`MiqBNY#8^c{R=fb78+oXTJyN|HT;pQ2&~48SP)%nP}fg zbAq%zYkeTjvfrJQX7S@cC_F04&}_@tD&lZ}e$MCPpfX><^IY`|)t&du;KOp_VsBRs+sXC;d4Dhep|Il7%F7Yq-&1eG} z?<5DE-PK112^m|%qoW8jL1Uk|a6|W@O^(dvh&OOr#v&PwKL-9~EIOSW^yibwGm4ra z4?X{4|93w2f7m<7HG;^|4wUnUk(+dhWB^@43)TagE(J2^2LG?^eV)_0fyUX7fBylW zQ&j28zmNgsDB1yXDFdt#)OF(N=A=xr2T%-3jekW7EVwS)T8&sNM~Q!m!J)|_A`^)dkev^Ku5v6Wxb zKg_R2y1b*8ccmdl1av6E&Op3t{F4lH{F59YgSI&H(fZUZ!U^d6zREreDoD4OS{<3s zHD~(qF5^!5J~c{=GwXDS{r~K zP;Cdwc!1Buw@g&`GHGX$<2#?RK;@s>!CA=wJPH{ob+6$Mz`Gug)RvI`LA}N90kdQ3 zUMGN{nE3d}c9-L)B95=*Tc3k>ah5m9K^cIZ^0Qk!yB$)W3#B(esb{_EhUn4d87e{zFB$G8WWQ;H*Nt!oyn3 zQo%ps5=lAeWFXGAmgiV%?Et*{v;%xTlMLw05#oP58PL3_+L`2e!+M*uw7-wxAM>L( z(Q>#YGpCAp4-b)QFI}zs-Uh`Q6C*nEbJmT(sAo!4_cCD~5Hir(0CeNDHbCF#Fx%I~Bqp56_9>(g z9xCJ$)KZw2+u^kRZZwWH$pHOX<)7MuUIsKy1{@Ou$binMlH-7~W}pA5!r1H?bpqe!r=eA#7l zlCF#9`-#RqAE6+IAAJt;WIGJqg|1t1#>HvhnD*e&zbyzE=*L9dV+_#N2T}&8`+(<^ zQT>l;1K?TOoumx>>tF2$0-r>6kEEO@n0mT9EBjWD%_i2m(c#qm&;E*uq@j|rmLhk0 zw>$S~dFGSW27LI3JS6|>ydc+$QUA{kKqV?69ix4qJp=P4kL<0F)MJa_Ju{{YTe z-1JqJRCX8S9Pn=kqCM!wM1L8GcA)kHp+^%kI0OH*ZiKCg&gG)^FKzE)zbNtxeb+efS68*hgu+lMIM|!Xjc^=*qOe(pOMKww<#c>&{gweUr-a zdkgb+A&&3q(Ro4TTem*)l>vCv>C%KgQRQF6X~&+KWFTw}a^K)%b5+{_@h+2E|D;!I zHKm>IvE}UQ^%UoyD?jJ*d>BQA!qqpq(%fI_xdrQkFO_)#{EPLGDhFBrS{ndwl7EU@ zNqQ4%2ati}UvFm-`z9a$!8hSBB=5+ZRQ|o@j4%6g^KR)aDKkUq#3I%HdMvl%zh9>Rwm>dOJ%X{xuv1_$Ew_!gng~%(8vhpI>m(Kv}s%(lObdEpNZKoK{Kv zwP#sojw=M`1eXk!6>jLx&v_s1;k1;4#yiPC;~#Y`<2Firqgwxp{T;kgY)&l>J9L?5 z^XV>|{eAGgVMbYbNv6vc%C|lkP?7V!2>=E4Rg0;Hy>ZK0<|rr(8Lq8%;@tG*(~I(- z>2f;$09kxPdnS^Dj9ICVQ%W{RpZJu-H|#7lHndtS-*nh)f9P{MpBXGFT0UG=m7C*n zhy2Tx*9aDWI&1Ft$?Ak<4NM`m8e@A_U%~j6AF=6Er^Jp-nN&JdS-NPT#Iw22?RvS( zm3^oq+xD5)p80i~HRBsyoW^gw*37Rv?AFhqQ$N(}%ze4vU9fqmq-4=ZRaI$UO-(Gn zZVlUc;YFg18>W-{+yC4vDGp=gi%+vHOXjhM=MS;c+9@GJ^|cAJ>ZUkGs;efCOseP{ zt}353QdvHCq_S-8a7Fp7;mV56kx7-4XHKbc4As^q6xURT?3y{k?w&h`{q_Ezvy7y~ z|G5lLK$$5{8IyOeTFGvmH=AvoGr~5^n9gqK>0sA)wIg}i4ajfl?_>Ws3%|`ik3G8L zGV#X57}~o0-}PNeKnXg4*;7O_s8{3OSk>qUGL8*G7_22Kv^X_d>;my`qw!^ATp1Y; zBmNNm8*u0QM8-m7zE=4hBy;8Cceid;-~Zp0X?#k4_bHTU@;Ib?j!<(=erjA0tCX`A zGeUWOv|jen7pSL0l%w8c>>U3zHL zG)i<&-_dXMjQTA75B=}=%?r^@%1pw$C&EWKH#02Ci+BWAR7ECkMLdF+>Z6k1X^c)e zJS{r)kCd9CQx7*rrM?4y`x;bU${IVEuo`d9*9;M@ehOXoWeyz{A+X!9THB2)I3geR_mk1#FP zlIh)Q8MyuXU3e$Sh1#t#J|wKDC^ByKR727mz;B%pb|}>jD{QekY=(wY)8REGW}9-t zuEYQT1pK|HB6DtpVPuLS@#Uu2+onmH6rPkZceh6^ygnzYP-*I>|jc zJ~S-9DkfnI{K}7${#vu+kWCXj_#_qIqGA4Ye4K4P5FhXfIZi&32_fO6HxWFXOC^A3 zVmT7D=S_-D*wz%E{7oRgXw5dQ@d0~}9;@Y77lC*fuO7g|H}GxRmJkv_Q(2@+(;3+S z;Y53QbV!J;DmLM6oYDJ@)FErOG}We}(XU|)M)5`hccj(FDE>4M4}toF+Md2aJ=|>w z3bheU=nrS49}mzNnN${QT+?VY9oO`Lqzm-3iH*TXsC-Dwl%5CaYv<#CJHfal`vbKl z#3oroG^w;93w)`vkIpy5_SYwvj!Fy=JNnD z6y?j>G8V#xgYP<&BAcL2XL z$&2QHIZj&&G%jJyaUe6yKw~Q5th5XF^f9u`Xk6B4NSY!Eys%aJ z@Bp49{bP6l-9CPh)F<$rpa0*u^*~tO3HrmdX!EX^kT8mcLi4MJv&^g8iQS`Op_=t|mU(O&Q2xBgY&^W0J%o z(%35e_w;idd{oF!Mfj@dc+l4a#-byh$b`utoW^88Ncu5^?bU`DQG9ZgXPoO`HqdZ@s}QZ zg73WR9)3mF0KaZzF5h|Q7XH}noB8qvufWdTIA;-m;?8^c1HatIci;N}f9Adi z`NKcGoe$eQiqDs>EfEj!cio#17D@B5pxG4uysp_AbT*eZi-o_qbEi@UF!_(& zwV4m*yZQ7S7vFmGI?X4M=*L<1{HBFVwC~>gm)H3P4XvDf8?Wpg6!>j=5%~!E(@(yQ z*A2~u535P@Z69x~(Q2@~o*SJ&aqk5E`Np{X#l4e1HUua9rb-0 zYjFQHU#r1<5Pg{D0ivI|jd6vb|A>!&71;p62VuwGfAdX2)Bgvietvb0u=mi|G~_Pi zAHMgV_)XC7Ddt<@cPlUQwI%;j>0kTkrn|&Xg8n6FKY{3n{I&gqjt@N#h)sB;IKo&+ zw9{3X5btR;ryS92H^NT{^n-`?tStWOb9+U(BqQ<*YR|~zZDtGKaLJ|o*k2XDNYQ@W zMSR1>mkM7|`iI~A@&!KAU4nTojh|m#C;AP2uhAa^`ER+Gz7lQjx*^CvDoMfo%e8la zJrLT}kw`?X*5J@;?pG*-!LJo>L42K~`0{rY{7o(G!WV$282VpCj_es@|*dQ*DZ z@04@!6nmP)6HuG#FUa@t&ysWy2Alk9=_2~6KM=O;pRT@UjNi@izaGPw`my|1zJ3|T zPe1t+{Y__}U+k@8&A%%&rV0!W@sOTijBCm??-4dZ)fVW33jhy8#YKGU`t|(HS6>zV zdGA9H!N+no|NYx<`_NDGbh`yU;R_b=f8O&9fB%g)`GI{e@mnvxjBi|VB|iW^Eb_x7 z|5Eaw(YGH-zw{dsbG6!zd~`Fh<~FK;5ecOlr5=H*f7o;=Y$_H}ud3UB=tTDVPi0fvt3g0-wz0s|BMq9=_*k(^kyR?SW0$xeOY7svwK7nu< zg9Qcr;J+z8O=A8nDHGTn&5uFFDhj-=#4XEpAFWrB9=Yuf_yvE>zl2}F4+duPCIkF- z)qPwbe+7(9*qda`(+I~6-+e!uYR@cc$+CPjYGWrmI}*{a<3ZwY$&N~M!!z5r3*Swe z;|2@d0&k}IBKY91v96OmsQxHK|J>3lewnwMU((vi`)w|vpBbfJ)z3)0J?a4K){p9v zGm7|%t$G$%t|cv|#h&q~4^BwpMN}T7Z-L~2Fx6dlJMYQP7CCI;8h&&P599a`kZyzK z2=X0J@Y2*iKsV`^^g1S$ht>qkqq(Lu+JkAAJvvHYKU#8ZbAW$5E_eul`O)KGB@Yt! zC-I*W|0;5cg_re!_7u3EvXb zgN7fK*h!Us4L>e*15&Ty!^5b))tj8Tdump;=?_a+jU`#@!Z$8wf#3gK@b z(ny@>hVS_WtMwEZy4<<90Hb{>AP;_Ht2W2^V{s)8*M|p{ew7DWb13=%MJFKj#n8{3 z0^azRT4%oDsX4UeJ-dr+u-h(}$J)w@jNNYMCVw83J`MQ?}|Gr;Y`+EQDW@zxYoC2>)R6O z^PeBIIhyEK6YYVB4?PA{>NOyHf&Z1*N1|P&A2B74bz8I7w-po`@9G?2{P9=Lg>>y% z{;Mb0wu=_9mh#f*zLJ6q+jFfS3;!oQrqQPkKr7a-M1MdWr_>E-Jb-4Eehs&omi}>X zw)4W~qT=YEbo8+=uDV{M=iA)y$M0jCm(9l_J3FYqqPP}V?WfVN#rzzd z9uzDlWQ=vIrWXi6KVc7vhn5uciB7Bi>FN2NTIO~I-P$|&ZO9$>f9}2da`q2{oosqd zWdbm^3xKP91sFQ9){tvfNxy=n1l_uL6@mwqejof`n)x{NORw~~@)z`#l_&gYY7@J< zmsI_K|BKcgs|LH-#+Dj3IAv1uKv~f+aIz0|D0o1Bz&h_F z&Y%CVJ3ITK{sQ;#KzT*-Pm0UgRV{6Qf1(4tF)k^AUEb|wE9sw)p<9#ck8rMXe2NX-x%t62*_SwL}cp)+CP9OwJgoo@5`HT!l0#W4NX| zak!;9;(k1{th}6EP*=wm)YpIi1W!<6Wo|Z`Ikko@ZE0dlo155@X^lwWt*MbMoz}!g zYN}afwqt@focm9ND~iB!ns8u2l+!ElN5G5LFm{YS*E6QTj?^5H1`pBq5sdAl9GYyI zucgn>ipiWl{%^e2645$7_R(h@pNHr(_!n}4JcOLAs@xzif#-t!I6a3y3Ooxr{vn<| zL%{XO$+&GpYCzI(T1I^M+b*(=gd@>DkMzW8YNC7kj(($O{+<`4B``83oR3n4vqBaE zkF;S*l<7gl<=It-R2!B2;N(ct2AqGg5OKW8Z4-2) zsWv2TZ;DC&VmvI3(7&pBd})V(Jr1@m%NO-gsoR}lB8Dm9bk0^5^ju6)bljZ!Skt=# zTcY7Guy4kGGoT*Zj|OSyZ;7(J3k=d6dgocvU??@jFKdi5eJZda*sF{Ex~6l$J~@C6 zG>{x54ZuQuit|6nK1tZRfLC6$_$jYiKCd!TI9R;R~61i}Kz zy3o^58DTmPg@^N>i{9%`N02i*rmEg(`ge(M&~O=`L&E~7Ixrs`gS6R7oAWqzfta@c z?hZFn|L|!G{JirSa4p6u#>D$I`@Y=wQcmSV2chUuu+AVn0_ad^fDKk}zdr*Fz@*)8 z2o5!Vl|!N!y-MQZyI>Rhi(L0gpGDd~1+vF$ws>j(JxdzU7XDHdY3h7bHem;EgDtroF;5Y*gnN-X zj2XNmUQKZs7^mn=AmyAOj132iA`^x*gy0UwaZ@lCR@f&@A;Dwj?3lBZYXF7_7 z&68w+@;Pj^YpHCc@VeCGE&9Dox5EMZ%xnDQ@e_RAg%|ODXC8m#jyuIWpV_vZ|6q8Q zDDU5XbAZpUsNqYePD2d4ck%pjVGsX@i&u(gw{O_U+v9P*LIUhs5>KJFhh~F$3uemj zu;Adx`qbnd(#A(}7<9XZ{f=VA&8e*7wK1`L?YsqA`8O}QK-}+n;6cTXmuTj%?Ak48 zB73|nf7`mB!0zR1ccgLB3mR~C*bba^5E&U38rfh@*`e6DXkQJVSeupqcHce`w{Gi? z*YRb|E&Qb?o>a<5yxNt0{UW9i#U{OaV3_}K&U{X>9VsU572PQRk`>}vQ9f+xn%z*f zR}l>@hO`|~p<$6MBs8=!J$19RQPCcm?BzEsUc|rpLa{-SEsA0T(M9&19(y*Y*mrbM z{8WmsO6^3{f6t&+{sY86l`rQDoxQ9j*1VZThlcV?XS2qPwAFHtDEH}Y8R`6*Su^<~ zcizdj+;}6uef4T#>w9j;4iR@@M!tvNe$6WW_~tE~>SO%{%lXgO-NI)VRq&0MDeZ6D zdXx`as>F6kdkf7M&9Uay+%}6XDRQxfEK46^sU0I4^tv;W1GUSB#6-S&4ymU(|K%f( zLYEKR2=tXSK9H_V&KF9&pCrEFqDw`8x#x#B30s_;vm~Y%^>M5z-qLqLvWpG4oouQt z!vS5``+@XEq>m>W7S`1vPTOt##wAM>TY_E(FYF(vQ|PZL*2rK^K3`VX%!gfts=a{b zY>eZS$X*be_I_Pbx?_ephm~0~n8jiaZLwwC3lR>0MVeg0g(P& z#obVxP+C8Td6U)-a{WN-7o+7agl`KiO{TDBj4doHV9hz!2E?-ZvtIwC#A-nq&_PMN zgwTiU;&CW8EtE_8drBk&K?CmfI#*i95dU$he{M<6Y?yCxin8gC*OSjGaF}P<_}IfEYcrR z`ItYIbrkA5)$&G{E!#_F_j!uhs`^%0T)=$IP!H>?sbcdAb69VwC$}@taR>BipHaWi z^l7RsUelwYUn)N6uo+U>paEmlXC0Z=J9?aXxpT}`)>Tx>E~{$_Sf>A%KUp}Ng{52B ztjc2Ok?OcC?HKIm?{-*in|g9xwf$4; z!iMwQEZk;g=T%PjFJ{8eAtAx+>-%nF1CuM*aH*TkU%WVYprSal*OS))UDlP*W!(l{ z)&m_5O7`2jaj!|7uEC8g|*l~*%0KFoyWo$1HU%2GB`RmKK9 zF4mczA|AhL)wRJ_ty(QMsvYn#A8$KmYUmzd6_(RY-?89Dlt+FQa z?Ht#kF`r={1T2MISIK=} zOO*L}?Dss2;*@c|IzExP4Y6kI@17Iqfsrkm@ZGeJQr9P94~w-Cy@U1%tx=ZeN+J@? z^(rs52}!FITL#8Cb#C#0hrq_EYfO62w5T*;m@G9KGl3y~oyLXM6f^I&=O9L;owp}r zeVUxf`!aHQPnw-~CS~z{b1ok+yLd+o_7lJVZshxSKg)+5h1?r!rv1~YY0+uR>dh%jq5D4Bm2KxQ zJpMR;{^3XX!FT=@=SkemfAhkN{Fw)~3w$KS!=`-*o&TWfX-+m9(v~)4quVQg0W(c4Ri+^Yd-I1NdBJy@daXP4hNb)6KB29S~y= ztx>T~Uox$U&nhhwu{sF@44)8+rNc+^vDcvevRLz^9%wRJ%ri1fti_(bQp{@@%V|ER zaZ6jzU=9;Dbj;f#E)VG)Xw70YuN(|BGOyFd+FbUeR(r-SiY2AZM>H4FTrB56xo4$4 zdt%zI*0ii7FWT*NrBpi2e#<{=(S835`MU5k literal 33772 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 From 751075f3616236fd56c169ca9d5e3c1f174a01ee Mon Sep 17 00:00:00 2001 From: Jishnu Raj Date: Sun, 8 Feb 2026 15:55:25 +0530 Subject: [PATCH 04/16] feat: Add msix dev dependency. --- pubspec.lock | 40 ++++++++++++++++++++++++++++++++++++++++ pubspec.yaml | 1 + 2 files changed, 41 insertions(+) diff --git a/pubspec.lock b/pubspec.lock index e089f4d..1b95faa 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -162,6 +162,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.4" + cli_util: + dependency: transitive + description: + name: cli_util + sha256: ff6785f7e9e3c38ac98b2fb035701789de90154024a75b6cb926445e83197d1c + url: "https://pub.dev" + source: hosted + version: "0.4.2" clock: dependency: transitive description: @@ -210,6 +218,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.1" + console: + dependency: transitive + description: + name: console + sha256: e04e7824384c5b39389acdd6dc7d33f3efe6b232f6f16d7626f194f6a01ad69a + url: "https://pub.dev" + source: hosted + version: "4.1.0" convert: dependency: transitive description: @@ -652,6 +668,14 @@ packages: url: "https://pub.dev" source: hosted version: "9.0.0" + get_it: + dependency: transitive + description: + name: get_it + sha256: "1d648d2dd2047d7f7450d5727ca24ee435f240385753d90b49650e3cdff32e56" + url: "https://pub.dev" + source: hosted + version: "9.2.0" glob: dependency: transitive description: @@ -724,6 +748,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.1.2" + image: + dependency: transitive + description: + name: image + sha256: "492bd52f6c4fbb6ee41f781ff27765ce5f627910e1e0cbecfa3d9add5562604c" + url: "https://pub.dev" + source: hosted + version: "4.7.2" image_picker: dependency: "direct main" description: @@ -932,6 +964,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.0" + msix: + dependency: "direct dev" + description: + name: msix + sha256: b6b08e7a7b5d1845f2b1d31216d5b1fb558e98251efefe54eb79ed00d27bc2ac + url: "https://pub.dev" + source: hosted + version: "3.16.13" native_toolchain_c: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 4b22f49..df4627e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -95,6 +95,7 @@ dev_dependencies: json_serializable: ^6.7.1 build_runner: ^2.1.7 intl_utils: ^2.8.4 + msix: ^3.16.13 flutter: generate: true From 394589f5744b4b0b33831b633e8c2d66971b366c Mon Sep 17 00:00:00 2001 From: Jishnu Raj Date: Sun, 8 Feb 2026 15:59:14 +0530 Subject: [PATCH 05/16] feat: Add MSIX configuration and update the Windows release workflow to build and upload MSIX packages instead of ZIP archives. --- .github/workflows/release.yml | 16 ++++------------ pubspec.yaml | 10 ++++++++++ 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index de67968..f033dac 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -94,21 +94,14 @@ jobs: - name: Build Windows Release run: flutter build windows --release - - name: Compress Windows Build - run: | - Compress-Archive -Path build/windows/x64/runner/Release/* -DestinationPath DailyAL-Windows.zip - - - name: Generate SHA1 Checksum - run: | - Get-FileHash DailyAL-Windows.zip -Algorithm SHA1 | Select-Object -ExpandProperty Hash > DailyAL-Windows.zip.sha1 + - name: Create MSIX + run: dart run msix:create - name: Upload Artifacts uses: actions/upload-artifact@v4 with: name: release-artifacts-windows - path: | - DailyAL-Windows.zip - DailyAL-Windows.zip.sha1 + path: build/windows/runner/Release/*.msix release: needs: [build-linux-android, build-windows] @@ -136,5 +129,4 @@ jobs: release-artifacts/app-release.apk.sha1 release-artifacts/DailyAL-x86_64.AppImage release-artifacts/DailyAL-x86_64.AppImage.sha1 - release-artifacts/DailyAL-Windows.zip - release-artifacts/DailyAL-Windows.zip.sha1 + release-artifacts/*.msix diff --git a/pubspec.yaml b/pubspec.yaml index df4627e..923b5b8 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -193,3 +193,13 @@ flutter: # see https://flutter.dev/custom-fonts/#from-packages flutter_intl: enabled: true + +msix_config: + display_name: DailyAL + publisher_display_name: Teen + identity_name: com.teen.dailyanimelist + publisher: CN=Teen + msix_version: 1.0.0.0 + logo_path: windows/runner/resources/app_icon.ico + capabilities: + - internetClient From b3c166222a79982c38dda3e79974f6a1f925cf25 Mon Sep 17 00:00:00 2001 From: Jishnu Raj Date: Sun, 8 Feb 2026 16:03:23 +0530 Subject: [PATCH 06/16] chore: Update MSIX publisher and identity information. --- pubspec.yaml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/pubspec.yaml b/pubspec.yaml index 923b5b8..e790da0 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -196,10 +196,9 @@ flutter_intl: msix_config: display_name: DailyAL - publisher_display_name: Teen - identity_name: com.teen.dailyanimelist - publisher: CN=Teen + publisher_display_name: JICA98 + identity_name: io.github.jica98.dailyal + publisher: CN=JICA98 msix_version: 1.0.0.0 logo_path: windows/runner/resources/app_icon.ico - capabilities: - - internetClient + capabilities: internetClient From e432c5065512ab34206d6d1859408d26a19ac4de Mon Sep 17 00:00:00 2001 From: Jishnu Raj Date: Sun, 8 Feb 2026 19:34:37 +0530 Subject: [PATCH 07/16] feat: Add compressed Windows build and its SHA1 checksum to release artifacts. --- .github/workflows/release.yml | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f033dac..2a548bd 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -97,11 +97,22 @@ jobs: - name: Create MSIX run: dart run msix:create + - name: Compress Windows Build + run: | + Compress-Archive -Path build/windows/x64/runner/Release/* -DestinationPath DailyAL-Windows.zip + + - name: Generate SHA1 Checksum + run: | + Get-FileHash DailyAL-Windows.zip -Algorithm SHA1 | Select-Object -ExpandProperty Hash > DailyAL-Windows.zip.sha1 + - name: Upload Artifacts uses: actions/upload-artifact@v4 with: name: release-artifacts-windows - path: build/windows/runner/Release/*.msix + path: | + build/windows/runner/Release/*.msix + DailyAL-Windows.zip + DailyAL-Windows.zip.sha1 release: needs: [build-linux-android, build-windows] @@ -130,3 +141,5 @@ jobs: release-artifacts/DailyAL-x86_64.AppImage release-artifacts/DailyAL-x86_64.AppImage.sha1 release-artifacts/*.msix + release-artifacts/DailyAL-Windows.zip + release-artifacts/DailyAL-Windows.zip.sha1 From 9d739895d20f9cd7b47f0515cd8cedfe637250df Mon Sep 17 00:00:00 2001 From: Jishnu Raj Date: Sun, 8 Feb 2026 19:49:27 +0530 Subject: [PATCH 08/16] feat: Enable dynamic node selection and repositioning in the anime graph, adjust graph layout, and disable certificate installation for MSIX builds. --- lib/widgets/anime_graph.dart | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/lib/widgets/anime_graph.dart b/lib/widgets/anime_graph.dart index 238a0f4..33c7c72 100644 --- a/lib/widgets/anime_graph.dart +++ b/lib/widgets/anime_graph.dart @@ -7,7 +7,7 @@ import 'package:dailyanimelist/enums.dart'; import 'package:dailyanimelist/generated/l10n.dart'; import 'package:dailyanimelist/screens/contentdetailedscreen.dart'; import 'package:dailyanimelist/screens/plainscreen.dart'; -import 'package:dailyanimelist/widgets/common/image_preview.dart'; + import 'package:dailyanimelist/widgets/home/animecard.dart'; import 'package:dailyanimelist/widgets/selectbottom.dart'; import 'package:dal_commons/commons.dart' as dal; @@ -54,18 +54,20 @@ class _AnimeGraphWidgetState extends State { _GraphOrderType.by_sequel: S.current.Graph_Order_By_Sequel, _GraphOrderType.from_selected: S.current.Graph_Order_From_Selected, }; - _GraphOrderType _graphOrderType = _GraphOrderType.by_sequel; + _GraphOrderType _graphOrderType = _GraphOrderType.from_selected; + late int _selectedId; @override void initState() { super.initState(); + _selectedId = widget.id; widget.graph.nodes?.forEach((node) => _nodeMap[node.id!] = node); _setGraph(); _algorithm = SugiyamaAlgorithm(SugiyamaConfiguration() ..bendPointShape = CurvedBendPointShape(curveLength: 120.0) - ..nodeSeparation = 40 - ..levelSeparation = 80); + ..nodeSeparation = 60 + ..levelSeparation = 100); WidgetsBinding.instance.addPostFrameCallback((_) { _setInitialPosition(); @@ -151,7 +153,7 @@ class _AnimeGraphWidgetState extends State { void _setInitialPosition([Size? size]) { final position = _algorithm.nodeData.keys.firstWhere((e) { - return e.key?.value == widget.id; + return e.key?.value == _selectedId; }).position; final contextSize = size ?? MediaQuery.of(context).size; _controller.value = Matrix4.identity() @@ -229,6 +231,7 @@ class _AnimeGraphWidgetState extends State { children: [ IconButton.filled( onPressed: () { + _selectedId = widget.id; _setInitialPosition(); if (mounted) setState(() {}); }, @@ -327,7 +330,7 @@ class _AnimeGraphWidgetState extends State { child: Center( child: AutoSizeText( a.title ?? "", - maxLines: 2, + maxLines: 3, minFontSize: 10.0, textAlign: TextAlign.center, ), @@ -419,7 +422,7 @@ class _AnimeGraphWidgetState extends State { child: InkWell( borderRadius: BorderRadius.circular(64), onTap: () => _setExpanded(a), - onLongPress: () => zoomInImage(context, imageUrl), + onLongPress: () => _onNodeSelect(a), child: Ink( child: CircleAvatar( backgroundImage: NetworkImage(imageUrl), @@ -430,6 +433,7 @@ class _AnimeGraphWidgetState extends State { final myListStatus = widget.statusMap[a.id]; final value = NodeStatusValue.fromListStatus(myListStatus); final contains = _expandedIds.contains(a.id); + final isSelected = _selectedId == a.id; final statusOutline = Container( height: 140.0, width: 140.0, @@ -471,7 +475,7 @@ class _AnimeGraphWidgetState extends State { width: 140.0, child: Stack( children: [ - if (widget.id == a.id) centerBorder, + if (isSelected) centerBorder, if (value.color != null || contains) statusOutline, Positioned( top: 10, @@ -496,4 +500,12 @@ class _AnimeGraphWidgetState extends State { )), )); } + + void _onNodeSelect(dal.GraphNode a) { + if (a.id != null) { + _selectedId = a.id!; + _setInitialPosition(); + if (mounted) setState(() {}); + } + } } From cf57230332722a8e2090c1d4fb22c2eadd29cf08 Mon Sep 17 00:00:00 2001 From: Jishnu Raj Date: Sun, 8 Feb 2026 19:52:54 +0530 Subject: [PATCH 09/16] build: disable certificate installation during MSIX creation for Windows builds. --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2a548bd..e71c914 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -95,7 +95,7 @@ jobs: run: flutter build windows --release - name: Create MSIX - run: dart run msix:create + run: dart run msix:create --install-certificate false - name: Compress Windows Build run: | From f6cb9d00c065473ed6e6526bf3fafdaf1ff7c44b Mon Sep 17 00:00:00 2001 From: Jishnu Raj Date: Sun, 8 Feb 2026 20:42:03 +0530 Subject: [PATCH 10/16] feat: Add functionality to capture and share anime graph images with branding, and refine the condition for showing the graph loading snackbar. --- .../animedetailed/relatedanimewidget.dart | 2 +- lib/widgets/anime_graph.dart | 145 +++++++++++++++++- 2 files changed, 138 insertions(+), 9 deletions(-) diff --git a/lib/pages/animedetailed/relatedanimewidget.dart b/lib/pages/animedetailed/relatedanimewidget.dart index ff8eefe..1ff031f 100644 --- a/lib/pages/animedetailed/relatedanimewidget.dart +++ b/lib/pages/animedetailed/relatedanimewidget.dart @@ -76,7 +76,7 @@ class _RelatedAnimeWidgetState extends State if (_graph is AnimeGraph && nullOrEmpty(_graph.edges)) { throw Error(); } - if ((then - now) > 1) { + if ((then - now) > 1 && _selectedView == RelatedSelectedView.list) { showSnackBar(_graphSnackBar(), Duration(seconds: 3)); } } catch (e) { diff --git a/lib/widgets/anime_graph.dart b/lib/widgets/anime_graph.dart index 33c7c72..e17580e 100644 --- a/lib/widgets/anime_graph.dart +++ b/lib/widgets/anime_graph.dart @@ -13,6 +13,12 @@ import 'package:dailyanimelist/widgets/selectbottom.dart'; import 'package:dal_commons/commons.dart' as dal; import 'package:flutter/material.dart'; import 'package:graphview/GraphView.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter/rendering.dart'; +import 'dart:ui' as ui; +import 'dart:io'; +import 'package:path_provider/path_provider.dart'; +import 'package:share_plus/share_plus.dart'; enum _GraphOrderType { by_sequel, @@ -56,6 +62,7 @@ class _AnimeGraphWidgetState extends State { }; _GraphOrderType _graphOrderType = _GraphOrderType.from_selected; late int _selectedId; + final GlobalKey _globalKey = GlobalKey(); @override void initState() { @@ -185,14 +192,17 @@ class _AnimeGraphWidgetState extends State { minScale: 0.01, maxScale: 5.6, transformationController: _controller, - child: GraphView( - graph: _graph, - algorithm: _algorithm, - animated: false, - builder: (Node node) { - var a = node.key?.value as int?; - return rectangleWidget(_nodeMap[a]!); - }, + child: RepaintBoundary( + key: _globalKey, + child: GraphView( + graph: _graph, + algorithm: _algorithm, + animated: false, + builder: (Node node) { + var a = node.key?.value as int?; + return rectangleWidget(_nodeMap[a]!); + }, + ), ), ), _bottomBar(), @@ -241,6 +251,11 @@ class _AnimeGraphWidgetState extends State { IconButton.filled( onPressed: () => _onEdgeInfo(), icon: Icon(Icons.info), + ), + SB.w20, + IconButton.filled( + onPressed: () => _captureAndSharePng(), + icon: Icon(Icons.camera_alt), ) ], ), @@ -501,6 +516,120 @@ class _AnimeGraphWidgetState extends State { )); } + Future _captureAndSharePng() async { + try { + RenderRepaintBoundary boundary = _globalKey.currentContext! + .findRenderObject() as RenderRepaintBoundary; + + ui.Image? graphImage; + // Try higher pixel ratios for better quality + final ratios = [50.0, 30.0, 15.0, 10.0, 5.0, 3.0, 1.0]; + + for (final ratio in ratios) { + try { + graphImage = await boundary.toImage(pixelRatio: ratio); + break; + } catch (e) { + debugPrint('Failed to capture at ratio $ratio: $e'); + } + } + + if (graphImage == null) { + if (mounted) showToast(S.current.Couldnt_generate_graph); + return; + } + + // Load Logo + final logoBytes = await rootBundle.load('assets/images/dal-black-bg.png'); + final logoCodec = await ui.instantiateImageCodec( + logoBytes.buffer.asUint8List(), + ); + final logoFrame = await logoCodec.getNextFrame(); + final logoImage = logoFrame.image; + + // Calculate sizes + // Footer height relative to graph height, but at least enough for logo + padding + final footerHeight = (graphImage.height * 0.15).clamp(100.0, 400.0); + final totalWidth = graphImage.width; + final totalHeight = graphImage.height + footerHeight.toInt(); + final scaleFactor = totalWidth / 1000.0; // Base scale on width + + // Create Canvas + final recorder = ui.PictureRecorder(); + final canvas = Canvas( + recorder, + Rect.fromPoints(Offset.zero, + Offset(totalWidth.toDouble(), totalHeight.toDouble()))); + + // Draw Graph + canvas.drawImage(graphImage, Offset.zero, Paint()); + + // Draw Footer Background + final footerRect = Rect.fromLTWH( + 0, graphImage.height.toDouble(), totalWidth.toDouble(), footerHeight); + canvas.drawRect(footerRect, Paint()..color = const Color(0xFF151515)); + + // Draw Logo + final logoSize = footerHeight * 0.7; // Logo takes 80% of footer height + final logoY = graphImage.height + (footerHeight - logoSize) / 2; + final logoX = 50.0 * scaleFactor; // Padding from left + final logoRect = Rect.fromLTWH(logoX, logoY, logoSize, logoSize); + + // Paint logo with high quality filtering + paintImage( + canvas: canvas, + rect: logoRect, + image: logoImage, + fit: BoxFit.contain, + filterQuality: FilterQuality.high, + ); + + // Draw Text + final textSpan = TextSpan( + text: 'Created from DailyAL App', + style: TextStyle( + color: Colors.white, + fontSize: (footerHeight * 0.35).clamp(24.0, 100.0), + fontFamily: 'Roboto', // Default flutter font or app font + fontWeight: FontWeight.bold, + ), + ); + final textPainter = TextPainter( + text: textSpan, + textDirection: TextDirection.ltr, + ); + textPainter.layout(); + + final textX = logoX + logoSize + (40.0 * scaleFactor); + final textY = graphImage.height + (footerHeight - textPainter.height) / 2; + + textPainter.paint(canvas, Offset(textX, textY)); + + // Finalize Image + final picture = recorder.endRecording(); + final finalImage = await picture.toImage(totalWidth, totalHeight); + + ByteData? byteData = + await finalImage.toByteData(format: ui.ImageByteFormat.png); + Uint8List pngBytes = byteData!.buffer.asUint8List(); + + final tempDir = await getTemporaryDirectory(); + final node = _nodeMap[widget.id]; + final title = + node?.title?.replaceAll(RegExp(r'[^\w\s]+'), '') ?? 'anime_graph'; + final timestamp = DateTime.now().millisecondsSinceEpoch; + final fileName = '${title}_${widget.id}_$timestamp.png'; + + final file = await File('${tempDir.path}/$fileName').create(); + await file.writeAsBytes(pngBytes); + + await Share.shareXFiles([XFile(file.path)], text: fileName); + } catch (e) { + dal.logDal(e.toString()); + if (mounted) showToast(S.current.Couldnt_generate_graph); + } + } + void _onNodeSelect(dal.GraphNode a) { if (a.id != null) { _selectedId = a.id!; From 98241faefd5b376c93c3f7d821f7b824cfa7ed6c Mon Sep 17 00:00:00 2001 From: Jishnu Raj Date: Sun, 8 Feb 2026 21:40:43 +0530 Subject: [PATCH 11/16] fix: There is a typo "Top Manga Bypopularity". (also, shouldn't "By" be lowercased, just like in "Top Anime by Score"?) --- lib/generated/intl/messages_de_DE.dart | 2 +- lib/generated/intl/messages_en_US.dart | 2 +- lib/generated/l10n.dart | 4 ++-- lib/l10n/intl_de_DE.arb | 4 ++-- lib/l10n/intl_en.arb | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/generated/intl/messages_de_DE.dart b/lib/generated/intl/messages_de_DE.dart index 803c191..a553402 100644 --- a/lib/generated/intl/messages_de_DE.dart +++ b/lib/generated/intl/messages_de_DE.dart @@ -1587,7 +1587,7 @@ class MessageLookup extends MessageLookupByLibrary { ), "Top_Manga": MessageLookupByLibrary.simpleMessage("Top Manga"), "Top_Manga_Bypopularity": MessageLookupByLibrary.simpleMessage( - "Top Manga Bypopularity.", + "Top Manga nach Popularität", ), "Top_Manhua": MessageLookupByLibrary.simpleMessage("Top Mannblume."), "Top_Manhwa": MessageLookupByLibrary.simpleMessage("Top Manhwa"), diff --git a/lib/generated/intl/messages_en_US.dart b/lib/generated/intl/messages_en_US.dart index ee86e7a..8298817 100644 --- a/lib/generated/intl/messages_en_US.dart +++ b/lib/generated/intl/messages_en_US.dart @@ -1504,7 +1504,7 @@ class MessageLookup extends MessageLookupByLibrary { ), "Top_Manga": MessageLookupByLibrary.simpleMessage("Top Manga"), "Top_Manga_Bypopularity": MessageLookupByLibrary.simpleMessage( - "Top Manga Bypopularity", + "Top Manga by Popularity", ), "Top_Manhua": MessageLookupByLibrary.simpleMessage("Top Manhua"), "Top_Manhwa": MessageLookupByLibrary.simpleMessage("Top Manhwa"), diff --git a/lib/generated/l10n.dart b/lib/generated/l10n.dart index c4ad36a..a936993 100644 --- a/lib/generated/l10n.dart +++ b/lib/generated/l10n.dart @@ -239,10 +239,10 @@ class S { return Intl.message('Top Manhua', name: 'Top_Manhua', desc: '', args: []); } - /// `Top Manga Bypopularity` + /// `Top Manga by Popularity` String get Top_Manga_Bypopularity { return Intl.message( - 'Top Manga Bypopularity', + 'Top Manga by Popularity', name: 'Top_Manga_Bypopularity', desc: '', args: [], diff --git a/lib/l10n/intl_de_DE.arb b/lib/l10n/intl_de_DE.arb index 84f3008..f4bbf8c 100644 --- a/lib/l10n/intl_de_DE.arb +++ b/lib/l10n/intl_de_DE.arb @@ -23,7 +23,7 @@ "Top_Novels": "Top Romane", "Top_Manhwa": "Top Manhwa", "Top_Manhua": "Top Mannblume.", - "Top_Manga_Bypopularity": "Top Manga Bypopularity.", + "Top_Manga_Bypopularity": "Top Manga nach Popularität", "Top_Favorite_Manga": "Top Favoriten Manga.", "View_All": "Alle ansehen", "Search_Bar_Text": "Suche hier...", @@ -1024,4 +1024,4 @@ "Private_Note_Desc": "Lokal gespeichert, wird nie an Server gesendet", "Private_Note_Hint": "Schreiben Sie hier Ihre private Notiz...", "Private_Note_Local_Only": "Diese Notiz ist nur lokal und wird nicht synchronisiert." -} +} \ No newline at end of file diff --git a/lib/l10n/intl_en.arb b/lib/l10n/intl_en.arb index 411f3b2..b945541 100644 --- a/lib/l10n/intl_en.arb +++ b/lib/l10n/intl_en.arb @@ -23,7 +23,7 @@ "Top_Novels": "Top Novels", "Top_Manhwa": "Top Manhwa", "Top_Manhua": "Top Manhua", - "Top_Manga_Bypopularity": "Top Manga Bypopularity", + "Top_Manga_Bypopularity": "Top Manga by Popularity", "Top_Favorite_Manga": "Top Favorite Manga", "View_All": "View All", "Search_Bar_Text": "search here...", From 1e3e83306506b8eea89fd4da65e912b74127a010 Mon Sep 17 00:00:00 2001 From: Jishnu Raj Date: Mon, 9 Feb 2026 10:40:09 +0530 Subject: [PATCH 12/16] feat: Implement functionality to download and share .ics calendar files for anime schedules. --- lib/generated/intl/messages_en_US.dart | 8 ++ lib/generated/l10n.dart | 35 ++++++ lib/l10n/intl_en.arb | 4 + lib/widgets/home/anime_calendar.dart | 146 +++++++++++++++++++++++-- 4 files changed, 184 insertions(+), 9 deletions(-) diff --git a/lib/generated/intl/messages_en_US.dart b/lib/generated/intl/messages_en_US.dart index 8298817..a252470 100644 --- a/lib/generated/intl/messages_en_US.dart +++ b/lib/generated/intl/messages_en_US.dart @@ -397,6 +397,7 @@ class MessageLookup extends MessageLookupByLibrary { "Do you wish to logout?", ), "Doujunshi": MessageLookupByLibrary.simpleMessage("Doujunshi"), + "Download_ICS": MessageLookupByLibrary.simpleMessage("Download .ics"), "Drag_the_field": MessageLookupByLibrary.simpleMessage( "Drag the field or use arrow keys to move the field", ), @@ -466,6 +467,9 @@ class MessageLookup extends MessageLookupByLibrary { "Error_Adding_Event_To_Calendar": MessageLookupByLibrary.simpleMessage( "Error adding event to calendar", ), + "Error_Saving_File": MessageLookupByLibrary.simpleMessage( + "Error saving file!", + ), "Error_removing_image": MessageLookupByLibrary.simpleMessage( "Error removing image", ), @@ -518,6 +522,9 @@ class MessageLookup extends MessageLookupByLibrary { ), "Female": MessageLookupByLibrary.simpleMessage("Female"), "Figures": MessageLookupByLibrary.simpleMessage("Figures"), + "File_Saved": MessageLookupByLibrary.simpleMessage( + "File saved to download folder!", + ), "Filter": MessageLookupByLibrary.simpleMessage("Filter"), "Filter_After_search": MessageLookupByLibrary.simpleMessage( "These filters will be used when you do your next search", @@ -1302,6 +1309,7 @@ class MessageLookup extends MessageLookupByLibrary { "Setup Timed out. Please try again.", ), "Share": MessageLookupByLibrary.simpleMessage("Share"), + "Share_ICS": MessageLookupByLibrary.simpleMessage("Share .ics"), "Shoujo": MessageLookupByLibrary.simpleMessage("Shoujo"), "Should_be_aplhanumeric": MessageLookupByLibrary.simpleMessage( "Should be alphanumeric", diff --git a/lib/generated/l10n.dart b/lib/generated/l10n.dart index a936993..7bc5074 100644 --- a/lib/generated/l10n.dart +++ b/lib/generated/l10n.dart @@ -5759,6 +5759,41 @@ class S { ); } + /// `Download .ics` + String get Download_ICS { + return Intl.message( + 'Download .ics', + name: 'Download_ICS', + desc: '', + args: [], + ); + } + + /// `Share .ics` + String get Share_ICS { + return Intl.message('Share .ics', name: 'Share_ICS', desc: '', args: []); + } + + /// `File saved to download folder!` + String get File_Saved { + return Intl.message( + 'File saved to download folder!', + name: 'File_Saved', + desc: '', + args: [], + ); + } + + /// `Error saving file!` + String get Error_Saving_File { + return Intl.message( + 'Error saving file!', + name: 'Error_Saving_File', + desc: '', + args: [], + ); + } + /// `Discord Invite` String get DiscordInvite { return Intl.message( diff --git a/lib/l10n/intl_en.arb b/lib/l10n/intl_en.arb index b945541..29d16d7 100644 --- a/lib/l10n/intl_en.arb +++ b/lib/l10n/intl_en.arb @@ -798,6 +798,10 @@ "NoMoreItemsFound": "No more items found...", "ConfirmNotifPerm": "Allow Notifications", "ConfirmNotifPermDesc": "Do you wish to allow notifications for this app. This includes notifications when an episode is aired from your PTW (Plan To Watch) and Watching list.", + "Download_ICS": "Download .ics", + "Share_ICS": "Share .ics", + "File_Saved": "File saved to download folder!", + "Error_Saving_File": "Error saving file!", "DiscordInvite": "Discord Invite", "DiscordInviteDesc": "Click here to join the official Discord Server", "Adaptations": "Adaptations", diff --git a/lib/widgets/home/anime_calendar.dart b/lib/widgets/home/anime_calendar.dart index 6a2aea0..353be6e 100644 --- a/lib/widgets/home/anime_calendar.dart +++ b/lib/widgets/home/anime_calendar.dart @@ -3,6 +3,8 @@ import 'dart:collection'; import 'package:collection/collection.dart'; import 'package:dailyanimelist/api/dalapi.dart'; import 'package:dailyanimelist/constant.dart'; +import 'package:dailyanimelist/util/file_service.dart'; +import 'dart:io'; import 'package:dailyanimelist/generated/l10n.dart'; import 'package:dailyanimelist/pages/animedetailed/synopsiswidget.dart'; import 'package:dailyanimelist/screens/contentdetailedscreen.dart'; @@ -16,6 +18,7 @@ import 'package:dal_commons/commons.dart'; import 'package:flutter/material.dart'; import 'package:add_2_calendar/add_2_calendar.dart'; import 'package:intl/intl.dart'; +import 'package:share_plus/share_plus.dart'; import '../../api/malapi.dart'; @@ -657,10 +660,13 @@ class __ScheduleCustomListState extends State<_ScheduleCustomList> { canRecurring: canRecurring, initialRecurring: recurring, onConfirm: (useRecurring) { - Navigator.of(context).pop(); _createCalendarEvent(node, startDate, endDate, useRecurring: useRecurring); }, + onDownloadICS: (useRecurring) => _downloadICS(node, useRecurring), + onShareICS: Platform.isLinux + ? null + : (useRecurring) => _shareICS(node, useRecurring), ); }, ), @@ -717,16 +723,22 @@ class __ScheduleCustomListState extends State<_ScheduleCustomList> { } String _getCalendarTitle( - ScheduleData schedule, Node anime, Recurrence? recurrence) { + ScheduleData schedule, Node anime, Recurrence? recurrence, + [int? episode]) { return recurrence != null ? '${anime.title} Episode Release Reminder' - : 'Ep ${schedule.episode ?? '?'} - ${anime.title}'; - } - - _getAnimeDescription(Node anime, ScheduleData schedule) { - final title = '${anime.title} - Episode ${schedule.episode ?? '?'}'; - final airDate = DateFormat.yMMMd().format( - DateTime.fromMillisecondsSinceEpoch(schedule.timestamp! * 1000)); + : 'Ep ${episode ?? schedule.episode ?? '?'} - ${anime.title}'; + } + + _getAnimeDescription(Node anime, ScheduleData schedule, + [int? episode, int? timestamp]) { + final title = + '${anime.title} - Episode ${episode ?? schedule.episode ?? '?'}'; + final stamp = timestamp ?? schedule.timestamp; + final airDate = stamp != null + ? DateFormat.yMMMd() + .format(DateTime.fromMillisecondsSinceEpoch(stamp * 1000)) + : '?'; final relatedLinks = schedule.relatedLinks; final linksBuffer = StringBuffer(); @@ -753,6 +765,85 @@ class __ScheduleCustomListState extends State<_ScheduleCustomList> { return '$title\nAir Date: $airDate\n\nLinks:\n${linksBuffer.toString()}\n' 'This is a reminder for the scheduled episode of $title. \n\n Generated by DailyAL.'; } + + void _shareICS(SchduledNode node, bool useRecurring) async { + Navigator.of(context).pop(); + final file = await _generateICSFile(node, useRecurring); + if (file != null) { + Share.shareXFiles([XFile(file.path)]); + } + } + + void _downloadICS(SchduledNode node, bool useRecurring) async { + Navigator.of(context).pop(); + final file = await _generateICSFile(node, useRecurring); + if (file != null) { + showToast(S.current.File_Saved); + } + } + + Future _generateICSFile(SchduledNode node, bool useRecurring) async { + final anime = node.anime; + final schedule = node.scheduleData; + final startDate = + DateTime.fromMillisecondsSinceEpoch(schedule.timestamp! * 1000); + final endDate = startDate.add(Duration(minutes: 25)); + + int occurrences = 1; + if (useRecurring && anime.numEpisodes != null && schedule.episode != null) { + final total = anime.numEpisodes!; + final nextEp = schedule.episode!; + occurrences = total - nextEp + 1; + if (occurrences < 1) occurrences = 1; + } + + final buffer = StringBuffer(); + buffer.writeln('BEGIN:VCALENDAR'); + buffer.writeln('VERSION:2.0'); + buffer.writeln('PRODID:-//DailyAL//NONSGML v1.0//EN'); + + for (int i = 0; i < occurrences; i++) { + final ep = (schedule.episode ?? 1) + i; + final start = startDate.add(Duration(days: 7 * i)); + final end = endDate.add(Duration(days: 7 * i)); + final timestamp = start.millisecondsSinceEpoch ~/ 1000; + + final description = + _getAnimeDescription(anime, schedule, ep, timestamp).toString(); + final title = _getCalendarTitle(schedule, anime, null, ep); + + buffer.write(_generateEventString(title, description, start, end)); + } + + buffer.writeln('END:VCALENDAR'); + + final fileName = '${anime.title ?? "anime"}_calendar.ics' + .replaceAll(RegExp(r'[^\w\s\.]'), ''); + + try { + return await FileStorage.writeFile(buffer.toString(), fileName); + } catch (e) { + logDal(e); + showToast(S.current.Error_Saving_File); + return null; + } + } + + String _generateEventString( + String title, String description, DateTime start, DateTime end) { + final dateFormat = DateFormat("yyyyMMdd'T'HHmmss'Z'"); + final buffer = StringBuffer(); + buffer.writeln('BEGIN:VEVENT'); + buffer.writeln( + 'UID:${start.millisecondsSinceEpoch}-${title.hashCode}@dailyal'); + buffer.writeln('DTSTAMP:${dateFormat.format(DateTime.now().toUtc())}'); + buffer.writeln('DTSTART:${dateFormat.format(start.toUtc())}'); + buffer.writeln('DTEND:${dateFormat.format(end.toUtc())}'); + buffer.writeln('SUMMARY:$title'); + buffer.writeln('DESCRIPTION:${description.replaceAll('\n', '\\n')}'); + buffer.writeln('END:VEVENT'); + return buffer.toString(); + } } class _AddToCalendarSheetContent extends StatefulWidget { @@ -762,6 +853,8 @@ class _AddToCalendarSheetContent extends StatefulWidget { final bool canRecurring; final bool initialRecurring; final ValueChanged onConfirm; + final ValueChanged? onDownloadICS; + final ValueChanged? onShareICS; const _AddToCalendarSheetContent({ Key? key, @@ -771,6 +864,8 @@ class _AddToCalendarSheetContent extends StatefulWidget { required this.canRecurring, required this.initialRecurring, required this.onConfirm, + this.onDownloadICS, + this.onShareICS, }) : super(key: key); @override @@ -833,6 +928,38 @@ class _AddToCalendarSheetContentState ), ], SB.h20, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + if (widget.onShareICS != null) + PlainButton( + onPressed: () => + widget.onShareICS!(_recurring && widget.canRecurring), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(Icons.share, size: 18), + SB.w10, + Text(S.current.Share_ICS), + ], + ), + ), + if (widget.onDownloadICS != null) + PlainButton( + onPressed: () => + widget.onDownloadICS!(_recurring && widget.canRecurring), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(Icons.download, size: 18), + SB.w10, + Text(S.current.Download_ICS), + ], + ), + ), + ], + ), + SB.h20, Row( mainAxisAlignment: MainAxisAlignment.end, children: [ @@ -848,6 +975,7 @@ class _AddToCalendarSheetContentState ), ], ), + SB.h20, ], ), ); From 6720da8c10e4d710aad68d9737ef73b8ffa236f0 Mon Sep 17 00:00:00 2001 From: Jishnu Raj Date: Mon, 9 Feb 2026 17:06:55 +0530 Subject: [PATCH 13/16] Add translations --- lib/generated/intl/messages_ar_EG.dart | 16 ++++++++++ lib/generated/intl/messages_de_DE.dart | 18 +++++++++++ lib/generated/intl/messages_es_ES.dart | 18 +++++++++++ lib/generated/intl/messages_fr_FR.dart | 34 ++++++++++++++++++++ lib/generated/intl/messages_id_ID.dart | 16 ++++++++++ lib/generated/intl/messages_ja.dart | 16 ++++++++++ lib/generated/intl/messages_ko_KR.dart | 14 ++++++++ lib/generated/intl/messages_pt_BR.dart | 18 +++++++++++ lib/generated/intl/messages_ru_RU.dart | 16 ++++++++++ lib/generated/intl/messages_tr_TR.dart | 16 ++++++++++ lib/l10n/intl_ar_EG.arb | 44 +++++++++++++++----------- lib/l10n/intl_de_DE.arb | 22 +++++++++---- lib/l10n/intl_es_ES.arb | 22 +++++++++---- lib/l10n/intl_fr_FR.arb | 30 +++++++++++++----- lib/l10n/intl_id_ID.arb | 10 +++++- lib/l10n/intl_ja.arb | 44 +++++++++++++++----------- lib/l10n/intl_ko_KR.arb | 44 +++++++++++++++----------- lib/l10n/intl_pt_BR.arb | 28 ++++++++++------ lib/l10n/intl_ru_RU.arb | 44 +++++++++++++++----------- lib/l10n/intl_tr_TR.arb | 24 +++++++++----- py-req.txt => python/py-req.txt | 0 21 files changed, 381 insertions(+), 113 deletions(-) rename py-req.txt => python/py-req.txt (100%) diff --git a/lib/generated/intl/messages_ar_EG.dart b/lib/generated/intl/messages_ar_EG.dart index 639f366..0fc63cc 100644 --- a/lib/generated/intl/messages_ar_EG.dart +++ b/lib/generated/intl/messages_ar_EG.dart @@ -197,6 +197,7 @@ class MessageLookup extends MessageLookupByLibrary { "دعم تطوير هذا التطبيق هنا", ), "CGDCT": MessageLookupByLibrary.simpleMessage("CGDCT"), + "Calendar": MessageLookupByLibrary.simpleMessage("تقويم"), "Cancel": MessageLookupByLibrary.simpleMessage("يلغي"), "Cancelled_Restore": MessageLookupByLibrary.simpleMessage( "تم إلغاء الاستعادة", @@ -378,6 +379,7 @@ class MessageLookup extends MessageLookupByLibrary { "هل ترغب في تسجيل الخروج؟", ), "Doujunshi": MessageLookupByLibrary.simpleMessage("طريقة الاتجاه"), + "Download_ICS": MessageLookupByLibrary.simpleMessage("تحميل .ics"), "Drag_the_field": MessageLookupByLibrary.simpleMessage( "اسحب الحقل أو استخدم مفاتيح الأسهم لتحريك الحقل", ), @@ -443,6 +445,9 @@ class MessageLookup extends MessageLookupByLibrary { "Error_Adding_Event_To_Calendar": MessageLookupByLibrary.simpleMessage( "خطأ في إضافة حدث إلى التقويم", ), + "Error_Saving_File": MessageLookupByLibrary.simpleMessage( + "خطأ في حفظ الملف!", + ), "Error_removing_image": MessageLookupByLibrary.simpleMessage( "حدث خطأ أثناء إزالة الصورة", ), @@ -493,6 +498,9 @@ class MessageLookup extends MessageLookupByLibrary { ), "Female": MessageLookupByLibrary.simpleMessage("أنثى"), "Figures": MessageLookupByLibrary.simpleMessage("الأرقام"), + "File_Saved": MessageLookupByLibrary.simpleMessage( + "تم حفظ الملف في مجلد التنزيل!", + ), "Filter": MessageLookupByLibrary.simpleMessage("منقي"), "Filter_After_search": MessageLookupByLibrary.simpleMessage( "سيتم استخدام هذه المرشحات عند إجراء البحث التالي", @@ -1201,6 +1209,7 @@ class MessageLookup extends MessageLookupByLibrary { "Sci_fi": MessageLookupByLibrary.simpleMessage("SCI-FI."), "Score": MessageLookupByLibrary.simpleMessage("نتيجة"), "Score_Distribution": MessageLookupByLibrary.simpleMessage("توزيع النتيجة"), + "Score_Stats": MessageLookupByLibrary.simpleMessage("إحصائيات النتيجة"), "Screening": MessageLookupByLibrary.simpleMessage("تحري"), "Search": MessageLookupByLibrary.simpleMessage("يبحث"), "SearchBarHintText": MessageLookupByLibrary.simpleMessage( @@ -1280,6 +1289,7 @@ class MessageLookup extends MessageLookupByLibrary { "ضبط مهلة.حاول مرة اخرى.", ), "Share": MessageLookupByLibrary.simpleMessage("يشارك"), + "Share_ICS": MessageLookupByLibrary.simpleMessage("مشاركة .ics"), "Shoujo": MessageLookupByLibrary.simpleMessage("شوجو"), "Should_be_aplhanumeric": MessageLookupByLibrary.simpleMessage( "يجب أن تكون أبجدية رقمية", @@ -1315,6 +1325,9 @@ class MessageLookup extends MessageLookupByLibrary { "إظهار حقل الملاحظة الخاصة في شاشة التحرير", ), "Show_Spoiler": MessageLookupByLibrary.simpleMessage("عرض المفسد"), + "Show_dub_status_AnimeList_Desc": MessageLookupByLibrary.simpleMessage( + "إظهار حالة الدبلجة (الإنجليزية) لأنيمي في القائمة", + ), "Show_priority_in_anime_manga_list": MessageLookupByLibrary.simpleMessage( "إظهار الأولوية في قائمة أنيمي / مانغا", ), @@ -1554,6 +1567,9 @@ class MessageLookup extends MessageLookupByLibrary { "Video_Game": MessageLookupByLibrary.simpleMessage("لعبة فيديو"), "Videos": MessageLookupByLibrary.simpleMessage("أشرطة فيديو"), "View_All": MessageLookupByLibrary.simpleMessage("عرض الكل"), + "View_Related_Graph_Tooltip": MessageLookupByLibrary.simpleMessage( + "عرض الرسم البياني أنيمي / مانغا ذات الصلة", + ), "View_all_Discussions": MessageLookupByLibrary.simpleMessage( "عرض جميع المناقشات", ), diff --git a/lib/generated/intl/messages_de_DE.dart b/lib/generated/intl/messages_de_DE.dart index a553402..a8e2c0c 100644 --- a/lib/generated/intl/messages_de_DE.dart +++ b/lib/generated/intl/messages_de_DE.dart @@ -215,6 +215,7 @@ class MessageLookup extends MessageLookupByLibrary { "Unterstütze die Entwicklung dieser App hier", ), "CGDCT": MessageLookupByLibrary.simpleMessage("CGDCT"), + "Calendar": MessageLookupByLibrary.simpleMessage("Kalender"), "Cancel": MessageLookupByLibrary.simpleMessage("Abbrechen"), "Cancelled_Restore": MessageLookupByLibrary.simpleMessage( "Wiederherstellung abgebrochen", @@ -418,6 +419,9 @@ class MessageLookup extends MessageLookupByLibrary { "Möchten Sie mich abmelden?", ), "Doujunshi": MessageLookupByLibrary.simpleMessage("Richtungsart"), + "Download_ICS": MessageLookupByLibrary.simpleMessage( + "Laden Sie .ics herunter", + ), "Drag_the_field": MessageLookupByLibrary.simpleMessage( "Ziehen Sie das Feld oder verwenden Sie die Pfeiltasten, um das Feld zu verschieben", ), @@ -487,6 +491,9 @@ class MessageLookup extends MessageLookupByLibrary { "Error_Adding_Event_To_Calendar": MessageLookupByLibrary.simpleMessage( "Fehler beim Addieren von Ereignissen zum Kalender", ), + "Error_Saving_File": MessageLookupByLibrary.simpleMessage( + "Fehler beim Speichern der Datei!", + ), "Error_removing_image": MessageLookupByLibrary.simpleMessage( "Fehler beim Entfernen des Bildes", ), @@ -539,6 +546,9 @@ class MessageLookup extends MessageLookupByLibrary { ), "Female": MessageLookupByLibrary.simpleMessage("Weiblich"), "Figures": MessageLookupByLibrary.simpleMessage("Zahlen"), + "File_Saved": MessageLookupByLibrary.simpleMessage( + "Datei im Download-Ordner gespeichert!", + ), "Filter": MessageLookupByLibrary.simpleMessage("Filter"), "Filter_After_search": MessageLookupByLibrary.simpleMessage( "Diese Filter werden verwendet, wenn Sie Ihre nächste Suche durchführen", @@ -1285,6 +1295,7 @@ class MessageLookup extends MessageLookupByLibrary { "Score_Distribution": MessageLookupByLibrary.simpleMessage( "Punkteverteilung", ), + "Score_Stats": MessageLookupByLibrary.simpleMessage("Punktestatistiken"), "Screening": MessageLookupByLibrary.simpleMessage("Screening."), "Search": MessageLookupByLibrary.simpleMessage("Suchen"), "SearchBarHintText": MessageLookupByLibrary.simpleMessage( @@ -1376,6 +1387,7 @@ class MessageLookup extends MessageLookupByLibrary { "Setup zeitlich herausgestellt.Bitte versuche es erneut.", ), "Share": MessageLookupByLibrary.simpleMessage("Teilen"), + "Share_ICS": MessageLookupByLibrary.simpleMessage("Teilen Sie .ics"), "Shoujo": MessageLookupByLibrary.simpleMessage("Shoujo"), "Should_be_aplhanumeric": MessageLookupByLibrary.simpleMessage( "Sollte alphanumerisch sein", @@ -1409,6 +1421,9 @@ class MessageLookup extends MessageLookupByLibrary { "Privates Notizfeld im Bearbeitungsbildschirm anzeigen", ), "Show_Spoiler": MessageLookupByLibrary.simpleMessage("Spoiler zeigen"), + "Show_dub_status_AnimeList_Desc": MessageLookupByLibrary.simpleMessage( + "Dub-Status (Englisch) eines Animes in der Liste anzeigen", + ), "Show_priority_in_anime_manga_list": MessageLookupByLibrary.simpleMessage( "Priorität in Anime / Manga-Liste anzeigen", ), @@ -1664,6 +1679,9 @@ class MessageLookup extends MessageLookupByLibrary { "Video_Game": MessageLookupByLibrary.simpleMessage("Videospiel"), "Videos": MessageLookupByLibrary.simpleMessage("Videos"), "View_All": MessageLookupByLibrary.simpleMessage("Alle ansehen"), + "View_Related_Graph_Tooltip": MessageLookupByLibrary.simpleMessage( + "Zugehöriges Anime-/Manga-Diagramm anzeigen", + ), "View_all_Discussions": MessageLookupByLibrary.simpleMessage( "Alle Diskussionen anzeigen.", ), diff --git a/lib/generated/intl/messages_es_ES.dart b/lib/generated/intl/messages_es_ES.dart index 566d4a7..ceab83c 100644 --- a/lib/generated/intl/messages_es_ES.dart +++ b/lib/generated/intl/messages_es_ES.dart @@ -213,6 +213,7 @@ class MessageLookup extends MessageLookupByLibrary { "Apoye el desarrollo de esta aplicación aquí", ), "CGDCT": MessageLookupByLibrary.simpleMessage("CGDCT"), + "Calendar": MessageLookupByLibrary.simpleMessage("Calendario"), "Cancel": MessageLookupByLibrary.simpleMessage("Cancelar"), "Cancelled_Restore": MessageLookupByLibrary.simpleMessage( "Restauración cancelada", @@ -420,6 +421,7 @@ class MessageLookup extends MessageLookupByLibrary { "¿Deseas cerrar sesión?", ), "Doujunshi": MessageLookupByLibrary.simpleMessage("Forma de dirección"), + "Download_ICS": MessageLookupByLibrary.simpleMessage("Descargar .ics"), "Drag_the_field": MessageLookupByLibrary.simpleMessage( "Arrastre el campo o use las teclas de flecha para mover el campo", ), @@ -495,6 +497,9 @@ class MessageLookup extends MessageLookupByLibrary { "Error_Adding_Event_To_Calendar": MessageLookupByLibrary.simpleMessage( "Error a agregar evento al calendario", ), + "Error_Saving_File": MessageLookupByLibrary.simpleMessage( + "¡Error al guardar el archivo!", + ), "Error_removing_image": MessageLookupByLibrary.simpleMessage( "Error al eliminar la imagen", ), @@ -549,6 +554,9 @@ class MessageLookup extends MessageLookupByLibrary { ), "Female": MessageLookupByLibrary.simpleMessage("Mujer"), "Figures": MessageLookupByLibrary.simpleMessage("Cifras"), + "File_Saved": MessageLookupByLibrary.simpleMessage( + "¡Archivo guardado en la carpeta de descargas!", + ), "Filter": MessageLookupByLibrary.simpleMessage("Filtrar"), "Filter_After_search": MessageLookupByLibrary.simpleMessage( "Estos filtros se utilizarán cuando realice su próxima búsqueda.", @@ -1307,6 +1315,9 @@ class MessageLookup extends MessageLookupByLibrary { "Score_Distribution": MessageLookupByLibrary.simpleMessage( "Distribución de puntuación", ), + "Score_Stats": MessageLookupByLibrary.simpleMessage( + "Estadísticas de puntuación", + ), "Screening": MessageLookupByLibrary.simpleMessage("Poner en pantalla"), "Search": MessageLookupByLibrary.simpleMessage("Buscar"), "SearchBarHintText": MessageLookupByLibrary.simpleMessage( @@ -1402,6 +1413,7 @@ class MessageLookup extends MessageLookupByLibrary { "Configuración programada.Inténtalo de nuevo.", ), "Share": MessageLookupByLibrary.simpleMessage("Cuota"), + "Share_ICS": MessageLookupByLibrary.simpleMessage("Compartir .ics"), "Shoujo": MessageLookupByLibrary.simpleMessage("Shoujo"), "Should_be_aplhanumeric": MessageLookupByLibrary.simpleMessage( "debe ser alfanumérico", @@ -1435,6 +1447,9 @@ class MessageLookup extends MessageLookupByLibrary { "Mostrar el campo de notas privadas en la pantalla de edición", ), "Show_Spoiler": MessageLookupByLibrary.simpleMessage("Mostrar spoiler"), + "Show_dub_status_AnimeList_Desc": MessageLookupByLibrary.simpleMessage( + "Mostrar el estado de doblaje (inglés) de un anime en la lista", + ), "Show_priority_in_anime_manga_list": MessageLookupByLibrary.simpleMessage( "Mostrar prioridad en la lista de anime / manga", ), @@ -1702,6 +1717,9 @@ class MessageLookup extends MessageLookupByLibrary { "Video_Game": MessageLookupByLibrary.simpleMessage("Videojuego"), "Videos": MessageLookupByLibrary.simpleMessage("Vídeos"), "View_All": MessageLookupByLibrary.simpleMessage("Ver todo"), + "View_Related_Graph_Tooltip": MessageLookupByLibrary.simpleMessage( + "Ver gráfico de anime/manga relacionado", + ), "View_all_Discussions": MessageLookupByLibrary.simpleMessage( "Ver todas las discusiones", ), diff --git a/lib/generated/intl/messages_fr_FR.dart b/lib/generated/intl/messages_fr_FR.dart index bbec63a..f5912ab 100644 --- a/lib/generated/intl/messages_fr_FR.dart +++ b/lib/generated/intl/messages_fr_FR.dart @@ -219,6 +219,7 @@ class MessageLookup extends MessageLookupByLibrary { "Soutenez le développement de cette application ici", ), "CGDCT": MessageLookupByLibrary.simpleMessage("CGDCT"), + "Calendar": MessageLookupByLibrary.simpleMessage("Calendrier"), "Cancel": MessageLookupByLibrary.simpleMessage("Annuler"), "Cancelled_Restore": MessageLookupByLibrary.simpleMessage( "Restauration annulée", @@ -430,6 +431,7 @@ class MessageLookup extends MessageLookupByLibrary { "Souhaitez-vous vous déconnecter?", ), "Doujunshi": MessageLookupByLibrary.simpleMessage("Façon de direction"), + "Download_ICS": MessageLookupByLibrary.simpleMessage("Télécharger .ics"), "Drag_the_field": MessageLookupByLibrary.simpleMessage( "Faites glisser le champ ou utilisez les touches fléchées pour déplacer le champ", ), @@ -507,6 +509,9 @@ class MessageLookup extends MessageLookupByLibrary { "Error_Adding_Event_To_Calendar": MessageLookupByLibrary.simpleMessage( "Erreur d\'ajout d\'événement au calendrier", ), + "Error_Saving_File": MessageLookupByLibrary.simpleMessage( + "Erreur lors de l\'enregistrement du fichier !", + ), "Error_removing_image": MessageLookupByLibrary.simpleMessage( "Erreur lors de la suppression de l\'image", ), @@ -561,6 +566,9 @@ class MessageLookup extends MessageLookupByLibrary { ), "Female": MessageLookupByLibrary.simpleMessage("Femelle"), "Figures": MessageLookupByLibrary.simpleMessage("Les figures"), + "File_Saved": MessageLookupByLibrary.simpleMessage( + "Fichier enregistré dans le dossier de téléchargement !", + ), "Filter": MessageLookupByLibrary.simpleMessage("Filtre"), "Filter_After_search": MessageLookupByLibrary.simpleMessage( "Ces filtres seront utilisés lorsque vous faites votre prochaine recherche", @@ -1178,6 +1186,16 @@ class MessageLookup extends MessageLookupByLibrary { "Priority_level_qn": MessageLookupByLibrary.simpleMessage( "Quel est votre niveau de priorité pour regarder / lire ceci?", ), + "Private_Note": MessageLookupByLibrary.simpleMessage("Note privée"), + "Private_Note_Desc": MessageLookupByLibrary.simpleMessage( + "Enregistré localement, jamais envoyé aux serveurs", + ), + "Private_Note_Hint": MessageLookupByLibrary.simpleMessage( + "Écrivez votre note privée ici...", + ), + "Private_Note_Local_Only": MessageLookupByLibrary.simpleMessage( + "Cette note est locale uniquement et ne sera pas synchronisée.", + ), "Profile": MessageLookupByLibrary.simpleMessage("Profil"), "Profile_Page": MessageLookupByLibrary.simpleMessage("Page de profil"), "Profile_bg_removed": MessageLookupByLibrary.simpleMessage( @@ -1323,6 +1341,9 @@ class MessageLookup extends MessageLookupByLibrary { "Score_Distribution": MessageLookupByLibrary.simpleMessage( "Répartition des scores", ), + "Score_Stats": MessageLookupByLibrary.simpleMessage( + "Statistiques des scores", + ), "Screening": MessageLookupByLibrary.simpleMessage("Dépistage"), "Search": MessageLookupByLibrary.simpleMessage("Recherche"), "SearchBarHintText": MessageLookupByLibrary.simpleMessage( @@ -1418,6 +1439,7 @@ class MessageLookup extends MessageLookupByLibrary { "Configuration expirée.Veuillez réessayer.", ), "Share": MessageLookupByLibrary.simpleMessage("Partager"), + "Share_ICS": MessageLookupByLibrary.simpleMessage("Partager .ics"), "Shoujo": MessageLookupByLibrary.simpleMessage("Shoujo"), "Should_be_aplhanumeric": MessageLookupByLibrary.simpleMessage( "Doit être alphanumérique", @@ -1446,7 +1468,16 @@ class MessageLookup extends MessageLookupByLibrary { "Show_Original": MessageLookupByLibrary.simpleMessage( "Montrer l\'original", ), + "Show_Private_Review": MessageLookupByLibrary.simpleMessage( + "Afficher l\'avis privé", + ), + "Show_Private_Review_Desc": MessageLookupByLibrary.simpleMessage( + "Afficher le champ de note privée dans l\'écran d\'édition", + ), "Show_Spoiler": MessageLookupByLibrary.simpleMessage("Show spoiler"), + "Show_dub_status_AnimeList_Desc": MessageLookupByLibrary.simpleMessage( + "Afficher le statut de doublage (anglais) d\'un anime dans la liste", + ), "Show_priority_in_anime_manga_list": MessageLookupByLibrary.simpleMessage( "Afficher la priorité dans la liste anime / manga", ), @@ -1698,6 +1729,9 @@ class MessageLookup extends MessageLookupByLibrary { "Video_Game": MessageLookupByLibrary.simpleMessage("Jeu vidéo"), "Videos": MessageLookupByLibrary.simpleMessage("Vidéos"), "View_All": MessageLookupByLibrary.simpleMessage("Voir tout"), + "View_Related_Graph_Tooltip": MessageLookupByLibrary.simpleMessage( + "Voir le graphique anime/manga associé", + ), "View_all_Discussions": MessageLookupByLibrary.simpleMessage( "Voir toutes les discussions", ), diff --git a/lib/generated/intl/messages_id_ID.dart b/lib/generated/intl/messages_id_ID.dart index cb20b3f..1a36ae7 100644 --- a/lib/generated/intl/messages_id_ID.dart +++ b/lib/generated/intl/messages_id_ID.dart @@ -205,6 +205,7 @@ class MessageLookup extends MessageLookupByLibrary { "Dukung pengembangan aplikasi ini di sini", ), "CGDCT": MessageLookupByLibrary.simpleMessage("CGDCT"), + "Calendar": MessageLookupByLibrary.simpleMessage("Kalender"), "Cancel": MessageLookupByLibrary.simpleMessage("Membatalkan"), "Cancelled_Restore": MessageLookupByLibrary.simpleMessage( "Pemulihan Dibatalkan", @@ -402,6 +403,7 @@ class MessageLookup extends MessageLookupByLibrary { "Apakah Anda ingin keluar?", ), "Doujunshi": MessageLookupByLibrary.simpleMessage("Cara arah"), + "Download_ICS": MessageLookupByLibrary.simpleMessage("Unduh .ics"), "Drag_the_field": MessageLookupByLibrary.simpleMessage( "Seret bidang atau gunakan tombol panah untuk memindahkan bidang", ), @@ -475,6 +477,9 @@ class MessageLookup extends MessageLookupByLibrary { "Error_Adding_Event_To_Calendar": MessageLookupByLibrary.simpleMessage( "Kesalahan Menambahkan Acara ke Kalender", ), + "Error_Saving_File": MessageLookupByLibrary.simpleMessage( + "Terjadi kesalahan saat menyimpan file!", + ), "Error_removing_image": MessageLookupByLibrary.simpleMessage( "Terjadi kesalahan saat menghapus gambar", ), @@ -527,6 +532,9 @@ class MessageLookup extends MessageLookupByLibrary { ), "Female": MessageLookupByLibrary.simpleMessage("Perempuan"), "Figures": MessageLookupByLibrary.simpleMessage("Angka"), + "File_Saved": MessageLookupByLibrary.simpleMessage( + "File disimpan ke folder unduhan!", + ), "Filter": MessageLookupByLibrary.simpleMessage("Saring"), "Filter_After_search": MessageLookupByLibrary.simpleMessage( "Filter ini akan digunakan ketika Anda melakukan pencarian berikutnya", @@ -1263,6 +1271,7 @@ class MessageLookup extends MessageLookupByLibrary { "Score_Distribution": MessageLookupByLibrary.simpleMessage( "Distribusi Skor", ), + "Score_Stats": MessageLookupByLibrary.simpleMessage("Statistik Skor"), "Screening": MessageLookupByLibrary.simpleMessage("Penyaringan"), "Search": MessageLookupByLibrary.simpleMessage("Mencari"), "SearchBarHintText": MessageLookupByLibrary.simpleMessage( @@ -1344,6 +1353,7 @@ class MessageLookup extends MessageLookupByLibrary { "Pengaturan waktu habis.Silakan coba lagi.", ), "Share": MessageLookupByLibrary.simpleMessage("Membagikan"), + "Share_ICS": MessageLookupByLibrary.simpleMessage("Bagikan .ics"), "Shoujo": MessageLookupByLibrary.simpleMessage("Shoujo."), "Should_be_aplhanumeric": MessageLookupByLibrary.simpleMessage( "Harus alfanumerik", @@ -1379,6 +1389,9 @@ class MessageLookup extends MessageLookupByLibrary { "Tampilkan kolom catatan pribadi di layar edit", ), "Show_Spoiler": MessageLookupByLibrary.simpleMessage("Tampilkan Spoiler."), + "Show_dub_status_AnimeList_Desc": MessageLookupByLibrary.simpleMessage( + "Tampilkan status dubbing (Bahasa Inggris) suatu anime dalam daftar", + ), "Show_priority_in_anime_manga_list": MessageLookupByLibrary.simpleMessage( "Tampilkan prioritas dalam daftar anime / manga", ), @@ -1632,6 +1645,9 @@ class MessageLookup extends MessageLookupByLibrary { "Video_Game": MessageLookupByLibrary.simpleMessage("Video game"), "Videos": MessageLookupByLibrary.simpleMessage("Video"), "View_All": MessageLookupByLibrary.simpleMessage("Lihat semua"), + "View_Related_Graph_Tooltip": MessageLookupByLibrary.simpleMessage( + "Lihat grafik anime/manga terkait", + ), "View_all_Discussions": MessageLookupByLibrary.simpleMessage( "Lihat semua Diskusi", ), diff --git a/lib/generated/intl/messages_ja.dart b/lib/generated/intl/messages_ja.dart index 645e908..7d11293 100644 --- a/lib/generated/intl/messages_ja.dart +++ b/lib/generated/intl/messages_ja.dart @@ -177,6 +177,7 @@ class MessageLookup extends MessageLookupByLibrary { "ここでこのアプリの開発をサポート", ), "CGDCT": MessageLookupByLibrary.simpleMessage("CGDCT"), + "Calendar": MessageLookupByLibrary.simpleMessage("カレンダー"), "Cancel": MessageLookupByLibrary.simpleMessage("キャンセル"), "Cancelled_Restore": MessageLookupByLibrary.simpleMessage("キャンセルされた復元"), "Cannot_launch": MessageLookupByLibrary.simpleMessage("起動できません"), @@ -328,6 +329,7 @@ class MessageLookup extends MessageLookupByLibrary { "あなたはログアウトしたいですか?", ), "Doujunshi": MessageLookupByLibrary.simpleMessage("道順し"), + "Download_ICS": MessageLookupByLibrary.simpleMessage(".icsをダウンロード"), "Drag_the_field": MessageLookupByLibrary.simpleMessage( "フィールドをドラッグするか、矢印キーを使用してフィールドを移動します", ), @@ -393,6 +395,9 @@ class MessageLookup extends MessageLookupByLibrary { "Error_Adding_Event_To_Calendar": MessageLookupByLibrary.simpleMessage( "カレンダーにイベントを追加するエラー", ), + "Error_Saving_File": MessageLookupByLibrary.simpleMessage( + "ファイルの保存中にエラーが発生しました!", + ), "Error_removing_image": MessageLookupByLibrary.simpleMessage( "画像の削除中にエラーが発生しました", ), @@ -443,6 +448,9 @@ class MessageLookup extends MessageLookupByLibrary { ), "Female": MessageLookupByLibrary.simpleMessage("女性"), "Figures": MessageLookupByLibrary.simpleMessage("数字"), + "File_Saved": MessageLookupByLibrary.simpleMessage( + "ダウンロードフォルダにファイルが保存されました!", + ), "Filter": MessageLookupByLibrary.simpleMessage("フィルター"), "Filter_After_search": MessageLookupByLibrary.simpleMessage( "次回の検索が行われるときは、これらのフィルタが使用されます。", @@ -1065,6 +1073,7 @@ class MessageLookup extends MessageLookupByLibrary { "Sci_fi": MessageLookupByLibrary.simpleMessage("サイド"), "Score": MessageLookupByLibrary.simpleMessage("スコア"), "Score_Distribution": MessageLookupByLibrary.simpleMessage("スコア分布"), + "Score_Stats": MessageLookupByLibrary.simpleMessage("スコア統計"), "Screening": MessageLookupByLibrary.simpleMessage("ふるい分け"), "Search": MessageLookupByLibrary.simpleMessage("検索"), "SearchBarHintText": MessageLookupByLibrary.simpleMessage("アニメ、マンガなどを検索"), @@ -1134,6 +1143,7 @@ class MessageLookup extends MessageLookupByLibrary { "セットアップがタイムアウトしました。もう一度やり直してください。", ), "Share": MessageLookupByLibrary.simpleMessage("シェア"), + "Share_ICS": MessageLookupByLibrary.simpleMessage(".icsを共有する"), "Shoujo": MessageLookupByLibrary.simpleMessage("千条"), "Should_be_aplhanumeric": MessageLookupByLibrary.simpleMessage( "英数字である必要があります", @@ -1167,6 +1177,9 @@ class MessageLookup extends MessageLookupByLibrary { "編集画面にプライベートノートフィールドを表示する", ), "Show_Spoiler": MessageLookupByLibrary.simpleMessage("スポイラーを見せる"), + "Show_dub_status_AnimeList_Desc": MessageLookupByLibrary.simpleMessage( + "アニメの吹き替え(英語)ステータスをリストに表示します", + ), "Show_priority_in_anime_manga_list": MessageLookupByLibrary.simpleMessage( "アニメ/マンガリストの優先順位を表示します", ), @@ -1371,6 +1384,9 @@ class MessageLookup extends MessageLookupByLibrary { "Video_Game": MessageLookupByLibrary.simpleMessage("テレビゲーム"), "Videos": MessageLookupByLibrary.simpleMessage("動画"), "View_All": MessageLookupByLibrary.simpleMessage("全体を見る"), + "View_Related_Graph_Tooltip": MessageLookupByLibrary.simpleMessage( + "関連するアニメ/マンガのグラフを表示", + ), "View_all_Discussions": MessageLookupByLibrary.simpleMessage( "すべてのディスカッションを表示します", ), diff --git a/lib/generated/intl/messages_ko_KR.dart b/lib/generated/intl/messages_ko_KR.dart index 699a698..e901a50 100644 --- a/lib/generated/intl/messages_ko_KR.dart +++ b/lib/generated/intl/messages_ko_KR.dart @@ -169,6 +169,7 @@ class MessageLookup extends MessageLookupByLibrary { "여기에서 이 앱의 개발을 지원하세요.", ), "CGDCT": MessageLookupByLibrary.simpleMessage("CGDCT"), + "Calendar": MessageLookupByLibrary.simpleMessage("달력"), "Cancel": MessageLookupByLibrary.simpleMessage("취소"), "Cancelled_Restore": MessageLookupByLibrary.simpleMessage("취소된 복원"), "Cannot_launch": MessageLookupByLibrary.simpleMessage("실행할 수 없음"), @@ -322,6 +323,7 @@ class MessageLookup extends MessageLookupByLibrary { "로그 아웃하고 싶습니까?", ), "Doujunshi": MessageLookupByLibrary.simpleMessage("방향의 방법"), + "Download_ICS": MessageLookupByLibrary.simpleMessage(".ics 다운로드"), "Drag_the_field": MessageLookupByLibrary.simpleMessage( "필드를 드래그하거나 화살표 키를 사용하여 필드를 이동하세요.", ), @@ -383,6 +385,9 @@ class MessageLookup extends MessageLookupByLibrary { "Error_Adding_Event_To_Calendar": MessageLookupByLibrary.simpleMessage( "캘린더에 이벤트를 추가하는 오류", ), + "Error_Saving_File": MessageLookupByLibrary.simpleMessage( + "파일을 저장하는 중에 오류가 발생했습니다.", + ), "Error_removing_image": MessageLookupByLibrary.simpleMessage( "이미지를 삭제하는 중에 오류가 발생했습니다.", ), @@ -433,6 +438,7 @@ class MessageLookup extends MessageLookupByLibrary { ), "Female": MessageLookupByLibrary.simpleMessage("여자"), "Figures": MessageLookupByLibrary.simpleMessage("수치"), + "File_Saved": MessageLookupByLibrary.simpleMessage("다운로드 폴더에 파일이 저장되었습니다!"), "Filter": MessageLookupByLibrary.simpleMessage("필터"), "Filter_After_search": MessageLookupByLibrary.simpleMessage( "이 필터는 다음 검색을 수행 할 때 사용됩니다.", @@ -1041,6 +1047,7 @@ class MessageLookup extends MessageLookupByLibrary { "Sci_fi": MessageLookupByLibrary.simpleMessage("Sci-Fi"), "Score": MessageLookupByLibrary.simpleMessage("점수"), "Score_Distribution": MessageLookupByLibrary.simpleMessage("점수 분포"), + "Score_Stats": MessageLookupByLibrary.simpleMessage("점수 통계"), "Screening": MessageLookupByLibrary.simpleMessage("상영"), "Search": MessageLookupByLibrary.simpleMessage("찾다"), "SearchBarHintText": MessageLookupByLibrary.simpleMessage("애니메이션, 만화 등 검색"), @@ -1108,6 +1115,7 @@ class MessageLookup extends MessageLookupByLibrary { "설정 시간이 초과되었습니다.다시 시도하십시오.", ), "Share": MessageLookupByLibrary.simpleMessage("공유하다"), + "Share_ICS": MessageLookupByLibrary.simpleMessage(".ics 공유"), "Shoujo": MessageLookupByLibrary.simpleMessage("쇼 조"), "Should_be_aplhanumeric": MessageLookupByLibrary.simpleMessage( "영숫자여야 합니다.", @@ -1137,6 +1145,9 @@ class MessageLookup extends MessageLookupByLibrary { "편집 화면에서 개인 메모 필드를 표시합니다.", ), "Show_Spoiler": MessageLookupByLibrary.simpleMessage("쇼 스포일러"), + "Show_dub_status_AnimeList_Desc": MessageLookupByLibrary.simpleMessage( + "목록에 있는 애니메이션의 더빙(영어) 상태 표시", + ), "Show_priority_in_anime_manga_list": MessageLookupByLibrary.simpleMessage( "Anime / Manga 목록에서 우선 순위를 표시합니다", ), @@ -1345,6 +1356,9 @@ class MessageLookup extends MessageLookupByLibrary { "Video_Game": MessageLookupByLibrary.simpleMessage("비디오 게임"), "Videos": MessageLookupByLibrary.simpleMessage("비디오"), "View_All": MessageLookupByLibrary.simpleMessage("모두보기"), + "View_Related_Graph_Tooltip": MessageLookupByLibrary.simpleMessage( + "관련 애니메이션/만화 그래프 보기", + ), "View_all_Discussions": MessageLookupByLibrary.simpleMessage("모든 토론을 봅니다"), "Views": MessageLookupByLibrary.simpleMessage("견해"), "Visual_Arts": MessageLookupByLibrary.simpleMessage("시각예술"), diff --git a/lib/generated/intl/messages_pt_BR.dart b/lib/generated/intl/messages_pt_BR.dart index 066e2bd..d307b2a 100644 --- a/lib/generated/intl/messages_pt_BR.dart +++ b/lib/generated/intl/messages_pt_BR.dart @@ -213,6 +213,7 @@ class MessageLookup extends MessageLookupByLibrary { "Apoie o desenvolvimento deste aplicativo aqui", ), "CGDCT": MessageLookupByLibrary.simpleMessage("CGDCT"), + "Calendar": MessageLookupByLibrary.simpleMessage("Calendário"), "Cancel": MessageLookupByLibrary.simpleMessage("Cancelar"), "Cancelled_Restore": MessageLookupByLibrary.simpleMessage( "Restauração cancelada", @@ -420,6 +421,7 @@ class MessageLookup extends MessageLookupByLibrary { "Você deseja fazer logout?", ), "Doujunshi": MessageLookupByLibrary.simpleMessage("Maneira de direção"), + "Download_ICS": MessageLookupByLibrary.simpleMessage("Baixar .ics"), "Drag_the_field": MessageLookupByLibrary.simpleMessage( "Arraste o campo ou use as teclas de seta para movê-lo", ), @@ -495,6 +497,9 @@ class MessageLookup extends MessageLookupByLibrary { "Error_Adding_Event_To_Calendar": MessageLookupByLibrary.simpleMessage( "Erro adicionando evento ao calendário", ), + "Error_Saving_File": MessageLookupByLibrary.simpleMessage( + "Erro ao salvar o arquivo!", + ), "Error_removing_image": MessageLookupByLibrary.simpleMessage( "Erro ao remover imagem", ), @@ -549,6 +554,9 @@ class MessageLookup extends MessageLookupByLibrary { ), "Female": MessageLookupByLibrary.simpleMessage("Female"), "Figures": MessageLookupByLibrary.simpleMessage("Figuras"), + "File_Saved": MessageLookupByLibrary.simpleMessage( + "Arquivo salvo na pasta de download!", + ), "Filter": MessageLookupByLibrary.simpleMessage("Filtro"), "Filter_After_search": MessageLookupByLibrary.simpleMessage( "Esses filtros serão usados quando você fizer sua próxima pesquisa", @@ -1313,6 +1321,9 @@ class MessageLookup extends MessageLookupByLibrary { "Score_Distribution": MessageLookupByLibrary.simpleMessage( "Distribuição de pontuação", ), + "Score_Stats": MessageLookupByLibrary.simpleMessage( + "Estatísticas de pontuação", + ), "Screening": MessageLookupByLibrary.simpleMessage("Triagem"), "Search": MessageLookupByLibrary.simpleMessage("Procurar"), "SearchBarHintText": MessageLookupByLibrary.simpleMessage( @@ -1404,6 +1415,7 @@ class MessageLookup extends MessageLookupByLibrary { "Configuração expirou.Por favor, tente novamente.", ), "Share": MessageLookupByLibrary.simpleMessage("Compartilhar"), + "Share_ICS": MessageLookupByLibrary.simpleMessage("Compartilhe .ics"), "Shoujo": MessageLookupByLibrary.simpleMessage("Shoujo."), "Should_be_aplhanumeric": MessageLookupByLibrary.simpleMessage( "Deve ser alfanumérico", @@ -1437,6 +1449,9 @@ class MessageLookup extends MessageLookupByLibrary { "Mostrar campo de nota privada na tela de edição", ), "Show_Spoiler": MessageLookupByLibrary.simpleMessage("Mostrar spoiler"), + "Show_dub_status_AnimeList_Desc": MessageLookupByLibrary.simpleMessage( + "Mostrar status de dublagem (inglês) de um anime na lista", + ), "Show_priority_in_anime_manga_list": MessageLookupByLibrary.simpleMessage( "Mostrar prioridade na lista de anime / mangá", ), @@ -1694,6 +1709,9 @@ class MessageLookup extends MessageLookupByLibrary { "Video_Game": MessageLookupByLibrary.simpleMessage("Videogame"), "Videos": MessageLookupByLibrary.simpleMessage("Vídeos"), "View_All": MessageLookupByLibrary.simpleMessage("Ver tudo"), + "View_Related_Graph_Tooltip": MessageLookupByLibrary.simpleMessage( + "Ver gráfico de anime/mangá relacionado", + ), "View_all_Discussions": MessageLookupByLibrary.simpleMessage( "Ver todas as discussões", ), diff --git a/lib/generated/intl/messages_ru_RU.dart b/lib/generated/intl/messages_ru_RU.dart index 594504a..51c06f4 100644 --- a/lib/generated/intl/messages_ru_RU.dart +++ b/lib/generated/intl/messages_ru_RU.dart @@ -211,6 +211,7 @@ class MessageLookup extends MessageLookupByLibrary { "Поддержите разработку этого приложения здесь", ), "CGDCT": MessageLookupByLibrary.simpleMessage("КГДКТ"), + "Calendar": MessageLookupByLibrary.simpleMessage("Календарь"), "Cancel": MessageLookupByLibrary.simpleMessage("Отмена"), "Cancelled_Restore": MessageLookupByLibrary.simpleMessage( "Отменено восстановление", @@ -408,6 +409,7 @@ class MessageLookup extends MessageLookupByLibrary { "Вы хотите выйти из системы?", ), "Doujunshi": MessageLookupByLibrary.simpleMessage("Как патрулировать"), + "Download_ICS": MessageLookupByLibrary.simpleMessage("Скачать .ics"), "Drag_the_field": MessageLookupByLibrary.simpleMessage( "Перетащите поле или используйте клавиши со стрелками для перемещения поля.", ), @@ -483,6 +485,9 @@ class MessageLookup extends MessageLookupByLibrary { "Error_Adding_Event_To_Calendar": MessageLookupByLibrary.simpleMessage( "Ошибка добавления события в календарь", ), + "Error_Saving_File": MessageLookupByLibrary.simpleMessage( + "Ошибка сохранения файла!", + ), "Error_removing_image": MessageLookupByLibrary.simpleMessage( "Ошибка удаления изображения.", ), @@ -535,6 +540,9 @@ class MessageLookup extends MessageLookupByLibrary { ), "Female": MessageLookupByLibrary.simpleMessage("Женский"), "Figures": MessageLookupByLibrary.simpleMessage("Цифры"), + "File_Saved": MessageLookupByLibrary.simpleMessage( + "Файл сохранен в папке загрузки!", + ), "Filter": MessageLookupByLibrary.simpleMessage("Фильтр"), "Filter_After_search": MessageLookupByLibrary.simpleMessage( "Эти фильтры будут использоваться при следующем поиске.", @@ -1287,6 +1295,7 @@ class MessageLookup extends MessageLookupByLibrary { "Score_Distribution": MessageLookupByLibrary.simpleMessage( "Распределение очков", ), + "Score_Stats": MessageLookupByLibrary.simpleMessage("Статистика очков"), "Screening": MessageLookupByLibrary.simpleMessage("Скрининг"), "Search": MessageLookupByLibrary.simpleMessage("Поиск"), "SearchBarHintText": MessageLookupByLibrary.simpleMessage( @@ -1370,6 +1379,7 @@ class MessageLookup extends MessageLookupByLibrary { "Время установки истекло. Пожалуйста, попробуйте еще раз.", ), "Share": MessageLookupByLibrary.simpleMessage("Делиться"), + "Share_ICS": MessageLookupByLibrary.simpleMessage("Поделиться .ics"), "Shoujo": MessageLookupByLibrary.simpleMessage("Сёдзё"), "Should_be_aplhanumeric": MessageLookupByLibrary.simpleMessage( "Должно быть буквенно-цифровым", @@ -1403,6 +1413,9 @@ class MessageLookup extends MessageLookupByLibrary { "Показать поле личной заметки на экране редактирования", ), "Show_Spoiler": MessageLookupByLibrary.simpleMessage("Показать спойлер"), + "Show_dub_status_AnimeList_Desc": MessageLookupByLibrary.simpleMessage( + "Показывать статус дубляжа (английского) аниме в списке", + ), "Show_priority_in_anime_manga_list": MessageLookupByLibrary.simpleMessage( "Показывать приоритет в списке аниме/манги", ), @@ -1670,6 +1683,9 @@ class MessageLookup extends MessageLookupByLibrary { "Video_Game": MessageLookupByLibrary.simpleMessage("Видео игра"), "Videos": MessageLookupByLibrary.simpleMessage("Видео"), "View_All": MessageLookupByLibrary.simpleMessage("Посмотреть все"), + "View_Related_Graph_Tooltip": MessageLookupByLibrary.simpleMessage( + "Посмотреть связанный график аниме/манги", + ), "View_all_Discussions": MessageLookupByLibrary.simpleMessage( "Просмотреть все обсуждения", ), diff --git a/lib/generated/intl/messages_tr_TR.dart b/lib/generated/intl/messages_tr_TR.dart index 9ed2e88..d18418b 100644 --- a/lib/generated/intl/messages_tr_TR.dart +++ b/lib/generated/intl/messages_tr_TR.dart @@ -211,6 +211,7 @@ class MessageLookup extends MessageLookupByLibrary { "Bu uygulamanın gelişimini buradan destekleyin", ), "CGDCT": MessageLookupByLibrary.simpleMessage("CGDCT"), + "Calendar": MessageLookupByLibrary.simpleMessage("Takvim"), "Cancel": MessageLookupByLibrary.simpleMessage("İptal etmek"), "Cancelled_Restore": MessageLookupByLibrary.simpleMessage( "İptal Edilen Geri Yükleme", @@ -402,6 +403,7 @@ class MessageLookup extends MessageLookupByLibrary { "Oturumu kapatmak istiyor musunuz?", ), "Doujunshi": MessageLookupByLibrary.simpleMessage("Devriye nasıl yapılır"), + "Download_ICS": MessageLookupByLibrary.simpleMessage(".ics\'i indirin"), "Drag_the_field": MessageLookupByLibrary.simpleMessage( "Alanı sürükleyin veya alanı taşımak için ok tuşlarını kullanın", ), @@ -473,6 +475,9 @@ class MessageLookup extends MessageLookupByLibrary { "Error_Adding_Event_To_Calendar": MessageLookupByLibrary.simpleMessage( "Takvime olay ekleme hatası", ), + "Error_Saving_File": MessageLookupByLibrary.simpleMessage( + "Dosya kaydedilirken hata oluştu!", + ), "Error_removing_image": MessageLookupByLibrary.simpleMessage( "Resim kaldırılırken hata oluştu", ), @@ -525,6 +530,9 @@ class MessageLookup extends MessageLookupByLibrary { ), "Female": MessageLookupByLibrary.simpleMessage("Dişi"), "Figures": MessageLookupByLibrary.simpleMessage("Rakamlar"), + "File_Saved": MessageLookupByLibrary.simpleMessage( + "Dosya indirme klasörüne kaydedildi!", + ), "Filter": MessageLookupByLibrary.simpleMessage("Filtre"), "Filter_After_search": MessageLookupByLibrary.simpleMessage( "Bir sonraki aramanızı yaptığınızda bu filtreler kullanılacaktır", @@ -1245,6 +1253,7 @@ class MessageLookup extends MessageLookupByLibrary { "Sci_fi": MessageLookupByLibrary.simpleMessage("Bilim kurgu"), "Score": MessageLookupByLibrary.simpleMessage("Gol"), "Score_Distribution": MessageLookupByLibrary.simpleMessage("Puan Dağılımı"), + "Score_Stats": MessageLookupByLibrary.simpleMessage("Puan İstatistikleri"), "Screening": MessageLookupByLibrary.simpleMessage("Tarama"), "Search": MessageLookupByLibrary.simpleMessage("Aramak"), "SearchBarHintText": MessageLookupByLibrary.simpleMessage( @@ -1332,6 +1341,7 @@ class MessageLookup extends MessageLookupByLibrary { "Kurulum Zaman aşımına uğradı. Lütfen tekrar deneyin.", ), "Share": MessageLookupByLibrary.simpleMessage("Paylaşmak"), + "Share_ICS": MessageLookupByLibrary.simpleMessage(".ics\'i paylaşın"), "Shoujo": MessageLookupByLibrary.simpleMessage("Shoujo"), "Should_be_aplhanumeric": MessageLookupByLibrary.simpleMessage( "Alfasayısal olmalı", @@ -1365,6 +1375,9 @@ class MessageLookup extends MessageLookupByLibrary { "Düzenleme ekranında özel not alanını göster", ), "Show_Spoiler": MessageLookupByLibrary.simpleMessage("Spoiler\'ı Göster"), + "Show_dub_status_AnimeList_Desc": MessageLookupByLibrary.simpleMessage( + "Listede bir animenin dub (İngilizce) durumunu göster", + ), "Show_priority_in_anime_manga_list": MessageLookupByLibrary.simpleMessage( "Anime/manga listesinde önceliği göster", ), @@ -1624,6 +1637,9 @@ class MessageLookup extends MessageLookupByLibrary { "Video_Game": MessageLookupByLibrary.simpleMessage("Video oyunu"), "Videos": MessageLookupByLibrary.simpleMessage("Videolar"), "View_All": MessageLookupByLibrary.simpleMessage("Hepsini gör"), + "View_Related_Graph_Tooltip": MessageLookupByLibrary.simpleMessage( + "İlgili anime/manga grafiğini görüntüleyin", + ), "View_all_Discussions": MessageLookupByLibrary.simpleMessage( "Tüm Tartışmaları Görüntüle", ), diff --git a/lib/l10n/intl_ar_EG.arb b/lib/l10n/intl_ar_EG.arb index 6f6850d..8388e52 100644 --- a/lib/l10n/intl_ar_EG.arb +++ b/lib/l10n/intl_ar_EG.arb @@ -685,18 +685,18 @@ "Auto_Add_Start_End_Date_Desc": "\u064a\u0636\u064a\u0641 \u062a\u0627\u0631\u064a\u062e \u0627\u0644\u0628\u062f\u0621 \u0648\u0627\u0644\u0627\u0646\u062a\u0647\u0627\u0621 \u062a\u0644\u0642\u0627\u0626\u064a\u064b\u0627 \u0639\u0646\u062f \u0646\u0642\u0644 \u0627\u0644\u062d\u0627\u0644\u0629 \u0625\u0644\u0649 \u0627\u0644\u0645\u0634\u0627\u0647\u062f\u0629 / \u0627\u0644\u0627\u0643\u062a\u0645\u0627\u0644.", "Show_Airing_info_AnimeList": "\u0639\u0631\u0636 \u0648\u0642\u062a \u0627\u0644\u0628\u062b \u0639\u0644\u0649 \u0642\u0627\u0626\u0645\u0629 \u0627\u0644\u0631\u0633\u0648\u0645 \u0627\u0644\u0645\u062a\u062d\u0631\u0643\u0629", "Show_Airing_info_AnimeList_Desc": "\u0627\u0639\u0631\u0636 \u0645\u0639\u0644\u0648\u0645\u0627\u062a \u0627\u0644\u0628\u062b \u0644\u0644\u0623\u0646\u0645\u064a \u0627\u0644\u062c\u0627\u0631\u064a \u0628\u0639\u062f\u062f \u0627\u0644\u062d\u0644\u0642\u0629 \u0627\u0644\u062a\u0627\u0644\u064a\u0629", - "Dub_Settings": "\u0625\u0639\u062F\u0627\u062F\u0627\u062A \u0627\u0644\u062F\u0628\u0644\u062C\u0629", - "Dub_Settings_Desc": "\u062A\u062E\u0635\u064A\u0635 \u0625\u0639\u062F\u0627\u062F\u0627\u062A \u0627\u0644\u062F\u0628\u0644\u062C\u0629 \u0627\u0644\u062E\u0627\u0635\u0629 \u0628\u0643", - "Dub_Show_Icon": "\u0625\u0638\u0647\u0627\u0631 \u0631\u0645\u0632 \u0627\u0644\u062F\u0628\u0644\u062C\u0629", - "Dub_Show_Icon_Desc": "\u062A\u0645\u0643\u064A\u0646 \u0623\u064A\u0642\u0648\u0646\u0629 \u0627\u0644\u062F\u0628\u0644\u062C\u0629 \u0628\u062C\u0648\u0627\u0631 \u0627\u0644\u0623\u0646\u0645\u064A \u0627\u0644\u0645\u062F\u0628\u0644\u062C", - "Dub_Language": "\u0644\u063A\u0629 \u0627\u0644\u062F\u0628\u0644\u062C\u0629", - "Dub_Language_Desc": "\u062D\u062F\u062F \u0627\u0644\u0644\u063A\u0629 \u0644\u0644\u062F\u0628\u0644\u062C\u0629", - "Dub_Confidence": "\u062B\u0642\u0629 \u0627\u0644\u062F\u0628\u0644\u062C\u0629", - "Dub_Confidence_Desc": "\u0627\u0644\u062D\u062F \u0627\u0644\u0623\u062F\u0646\u0649 \u0644\u0639\u062F\u062F \u0627\u0644\u0645\u0635\u0627\u062F\u0631 \u0627\u0644\u0645\u0637\u0644\u0648\u0628\u0629 \u0644\u0648\u0636\u0639 \u0639\u0644\u0627\u0645\u0629 \u0639\u0644\u0649 \u0623\u0646\u0645\u064A \u0628\u0623\u0646\u0647 \u0645\u062F\u0628\u0644\u062C (\u0625\u0638\u0647\u0627\u0631 \u0631\u0645\u0632 \u0627\u0644\u062F\u0628\u0644\u062C\u0629)", - "Dub_Icon_Style": "\u0646\u0645\u0637 \u0627\u0644\u0623\u064A\u0642\u0648\u0646\u0629", - "Dub_Icon_Style_Desc": "\u062D\u062F\u062F \u0646\u0645\u0637 \u0627\u0644\u0623\u064A\u0642\u0648\u0646\u0627\u062A \u0644\u0644\u0623\u0646\u0645\u064A \u0627\u0644\u0645\u062F\u0628\u0644\u062C \u0648\u0627\u0644\u0645\u062F\u0628\u0644\u062C \u062C\u0632\u0626\u064A\u064B\u0627", - "Dub_Report": "\u0627\u0644\u0625\u0628\u0644\u0627\u063A \u0639\u0646 \u0627\u0644\u062F\u0628\u0644\u062C\u0629 \u063A\u064A\u0631 \u0627\u0644\u062F\u0642\u064A\u0642\u0629", - "Dub_Support": "\u0627\u062F\u0639\u0645 \u0645\u0634\u0631\u0648\u0639 MyDubList", + "Dub_Settings": "\u0625\u0639\u062f\u0627\u062f\u0627\u062a \u0627\u0644\u062f\u0628\u0644\u062c\u0629", + "Dub_Settings_Desc": "\u062a\u062e\u0635\u064a\u0635 \u0625\u0639\u062f\u0627\u062f\u0627\u062a \u0627\u0644\u062f\u0628\u0644\u062c\u0629 \u0627\u0644\u062e\u0627\u0635\u0629 \u0628\u0643", + "Dub_Show_Icon": "\u0625\u0638\u0647\u0627\u0631 \u0631\u0645\u0632 \u0627\u0644\u062f\u0628\u0644\u062c\u0629", + "Dub_Show_Icon_Desc": "\u062a\u0645\u0643\u064a\u0646 \u0623\u064a\u0642\u0648\u0646\u0629 \u0627\u0644\u062f\u0628\u0644\u062c\u0629 \u0628\u062c\u0648\u0627\u0631 \u0627\u0644\u0623\u0646\u0645\u064a \u0627\u0644\u0645\u062f\u0628\u0644\u062c", + "Dub_Language": "\u0644\u063a\u0629 \u0627\u0644\u062f\u0628\u0644\u062c\u0629", + "Dub_Language_Desc": "\u062d\u062f\u062f \u0627\u0644\u0644\u063a\u0629 \u0644\u0644\u062f\u0628\u0644\u062c\u0629", + "Dub_Confidence": "\u062b\u0642\u0629 \u0627\u0644\u062f\u0628\u0644\u062c\u0629", + "Dub_Confidence_Desc": "\u0627\u0644\u062d\u062f \u0627\u0644\u0623\u062f\u0646\u0649 \u0644\u0639\u062f\u062f \u0627\u0644\u0645\u0635\u0627\u062f\u0631 \u0627\u0644\u0645\u0637\u0644\u0648\u0628\u0629 \u0644\u0648\u0636\u0639 \u0639\u0644\u0627\u0645\u0629 \u0639\u0644\u0649 \u0623\u0646\u0645\u064a \u0628\u0623\u0646\u0647 \u0645\u062f\u0628\u0644\u062c (\u0625\u0638\u0647\u0627\u0631 \u0631\u0645\u0632 \u0627\u0644\u062f\u0628\u0644\u062c\u0629)", + "Dub_Icon_Style": "\u0646\u0645\u0637 \u0627\u0644\u0623\u064a\u0642\u0648\u0646\u0629", + "Dub_Icon_Style_Desc": "\u062d\u062f\u062f \u0646\u0645\u0637 \u0627\u0644\u0623\u064a\u0642\u0648\u0646\u0627\u062a \u0644\u0644\u0623\u0646\u0645\u064a \u0627\u0644\u0645\u062f\u0628\u0644\u062c \u0648\u0627\u0644\u0645\u062f\u0628\u0644\u062c \u062c\u0632\u0626\u064a\u064b\u0627", + "Dub_Report": "\u0627\u0644\u0625\u0628\u0644\u0627\u063a \u0639\u0646 \u0627\u0644\u062f\u0628\u0644\u062c\u0629 \u063a\u064a\u0631 \u0627\u0644\u062f\u0642\u064a\u0642\u0629", + "Dub_Support": "\u0627\u062f\u0639\u0645 \u0645\u0634\u0631\u0648\u0639 MyDubList", "Made_With_Flutter": "\u0645\u0635\u0646\u0648\u0639 \u0645\u0646", "Cannot_launch": "\u0644\u0627 \u064a\u0645\u0643\u0646 \u0625\u0637\u0644\u0627\u0642", "Anime_Manga_BG": "\u062e\u0644\u0641\u064a\u0629 \u0644\u0623\u0646\u0645\u064a / \u0645\u0627\u0646\u063a\u0627", @@ -1017,10 +1017,18 @@ "Add_Recurring_Event": "\u0645\u062a\u0643\u0631\u0631 \u0623\u0633\u0628\u0648\u0639\u064a", "Add_Recurring_Event_Desc": "\u0623\u0636\u0641 \u0627\u0644\u062d\u0644\u0642\u0627\u062a \u0627\u0644\u0645\u0633\u062a\u0642\u0628\u0644\u064a\u0629 \u0643\u0623\u062d\u062f\u0627\u062b \u0623\u0633\u0628\u0648\u0639\u064a\u0629", "Add": "\u064a\u0636\u064a\u0641", - "Private_Note": "ملاحظة خاصة", - "Show_Private_Review": "إظهار الملاحظة الخاصة", - "Show_Private_Review_Desc": "إظهار حقل الملاحظة الخاصة في شاشة التحرير", - "Private_Note_Desc": "يتم حفظها محليًا، ولن يتم إرسالها إلى الخوادم أبدًا", - "Private_Note_Hint": "اكتب ملاحظتك الخاصة هنا...", - "Private_Note_Local_Only": "هذه الملاحظة محلية فقط ولن يتمت مزامنتها." + "Private_Note": "\u0645\u0644\u0627\u062d\u0638\u0629 \u062e\u0627\u0635\u0629", + "Show_Private_Review": "\u0625\u0638\u0647\u0627\u0631 \u0627\u0644\u0645\u0644\u0627\u062d\u0638\u0629 \u0627\u0644\u062e\u0627\u0635\u0629", + "Show_Private_Review_Desc": "\u0625\u0638\u0647\u0627\u0631 \u062d\u0642\u0644 \u0627\u0644\u0645\u0644\u0627\u062d\u0638\u0629 \u0627\u0644\u062e\u0627\u0635\u0629 \u0641\u064a \u0634\u0627\u0634\u0629 \u0627\u0644\u062a\u062d\u0631\u064a\u0631", + "Private_Note_Desc": "\u064a\u062a\u0645 \u062d\u0641\u0638\u0647\u0627 \u0645\u062d\u0644\u064a\u064b\u0627\u060c \u0648\u0644\u0646 \u064a\u062a\u0645 \u0625\u0631\u0633\u0627\u0644\u0647\u0627 \u0625\u0644\u0649 \u0627\u0644\u062e\u0648\u0627\u062f\u0645 \u0623\u0628\u062f\u064b\u0627", + "Private_Note_Hint": "\u0627\u0643\u062a\u0628 \u0645\u0644\u0627\u062d\u0638\u062a\u0643 \u0627\u0644\u062e\u0627\u0635\u0629 \u0647\u0646\u0627...", + "Private_Note_Local_Only": "\u0647\u0630\u0647 \u0627\u0644\u0645\u0644\u0627\u062d\u0638\u0629 \u0645\u062d\u0644\u064a\u0629 \u0641\u0642\u0637 \u0648\u0644\u0646 \u064a\u062a\u0645\u062a \u0645\u0632\u0627\u0645\u0646\u062a\u0647\u0627.", + "Score_Stats": "\u0625\u062d\u0635\u0627\u0626\u064a\u0627\u062a \u0627\u0644\u0646\u062a\u064a\u062c\u0629", + "Show_dub_status_AnimeList_Desc": "\u0625\u0638\u0647\u0627\u0631 \u062d\u0627\u0644\u0629 \u0627\u0644\u062f\u0628\u0644\u062c\u0629 (\u0627\u0644\u0625\u0646\u062c\u0644\u064a\u0632\u064a\u0629) \u0644\u0623\u0646\u064a\u0645\u064a \u0641\u064a \u0627\u0644\u0642\u0627\u0626\u0645\u0629", + "Download_ICS": "\u062a\u062d\u0645\u064a\u0644 .ics", + "Share_ICS": "\u0645\u0634\u0627\u0631\u0643\u0629 .ics", + "File_Saved": "\u062a\u0645 \u062d\u0641\u0638 \u0627\u0644\u0645\u0644\u0641 \u0641\u064a \u0645\u062c\u0644\u062f \u0627\u0644\u062a\u0646\u0632\u064a\u0644!", + "Error_Saving_File": "\u062e\u0637\u0623 \u0641\u064a \u062d\u0641\u0638 \u0627\u0644\u0645\u0644\u0641!", + "View_Related_Graph_Tooltip": "\u0639\u0631\u0636 \u0627\u0644\u0631\u0633\u0645 \u0627\u0644\u0628\u064a\u0627\u0646\u064a \u0623\u0646\u064a\u0645\u064a / \u0645\u0627\u0646\u063a\u0627 \u0630\u0627\u062a \u0627\u0644\u0635\u0644\u0629", + "Calendar": "\u062a\u0642\u0648\u064a\u0645" } \ No newline at end of file diff --git a/lib/l10n/intl_de_DE.arb b/lib/l10n/intl_de_DE.arb index f4bbf8c..952cef6 100644 --- a/lib/l10n/intl_de_DE.arb +++ b/lib/l10n/intl_de_DE.arb @@ -23,7 +23,7 @@ "Top_Novels": "Top Romane", "Top_Manhwa": "Top Manhwa", "Top_Manhua": "Top Mannblume.", - "Top_Manga_Bypopularity": "Top Manga nach Popularität", + "Top_Manga_Bypopularity": "Top Manga nach Popularit\u00e4t", "Top_Favorite_Manga": "Top Favoriten Manga.", "View_All": "Alle ansehen", "Search_Bar_Text": "Suche hier...", @@ -68,7 +68,7 @@ "Statistics": "Statistiken", "No_Recommendations_yet": "Noch keine Empfehlungen...", "No_Related_Content_yet": "Noch keine verwandte Inhalte...", - "Opening_Songs": "Eröffnungslieder", + "Opening_Songs": "Er\u00f6ffnungslieder", "Ending Songs": "Schlusslieder", "Background": "Hintergrund", "None": "Keiner", @@ -505,7 +505,7 @@ "No_Image": "Kein Bild", "Filter_After_search": "Diese Filter werden verwendet, wenn Sie Ihre n\u00e4chste Suche durchf\u00fchren", "Cancel": "Abbrechen", - "Close": "Schließen", + "Close": "Schlie\u00dfen", "Apply_Filters": "Filter anwenden", "Filter_along_with": "Bitte verwenden Sie den Filter * 1 zusammen mit * 2", "Filter_cannot_with": "Sie k\u00f6nnen * 1-Filter nicht zusammen mit * 2 verwenden", @@ -691,13 +691,13 @@ "Dub_Show_Icon": "Dub-Symbol anzeigen", "Dub_Show_Icon_Desc": "Aktivieren Sie das Synchronisationssymbol neben synchronisierten Animes", "Dub_Language": "Synchronsprache", - "Dub_Language_Desc": "W\u00E4hlen Sie die Sprache f\u00FCr die Synchronisation", + "Dub_Language_Desc": "W\u00e4hlen Sie die Sprache f\u00fcr die Synchronisation", "Dub_Confidence": "Dub-Vertrauen", "Dub_Confidence_Desc": "Mindestanzahl an Quellen, die erforderlich sind, um einen Anime als synchronisiert zu markieren (das Synchronisationssymbol anzeigen)", "Dub_Icon_Style": "Symbolstil", - "Dub_Icon_Style_Desc": "W\u00E4hlen Sie den Symbolstil f\u00FCr synchronisierte und teilweise synchronisierte Anime", + "Dub_Icon_Style_Desc": "W\u00e4hlen Sie den Symbolstil f\u00fcr synchronisierte und teilweise synchronisierte Anime", "Dub_Report": "Ungenaue Dubs melden", - "Dub_Support": "Unterstützen Sie das MyDubList-Projekt", + "Dub_Support": "Unterst\u00fctzen Sie das MyDubList-Projekt", "Made_With_Flutter": "Gemacht mit", "Cannot_launch": "Kann nicht starten", "Anime_Manga_BG": "Hintergrund f\u00fcr Anime/Manga", @@ -1023,5 +1023,13 @@ "Show_Private_Review_Desc": "Privates Notizfeld im Bearbeitungsbildschirm anzeigen", "Private_Note_Desc": "Lokal gespeichert, wird nie an Server gesendet", "Private_Note_Hint": "Schreiben Sie hier Ihre private Notiz...", - "Private_Note_Local_Only": "Diese Notiz ist nur lokal und wird nicht synchronisiert." + "Private_Note_Local_Only": "Diese Notiz ist nur lokal und wird nicht synchronisiert.", + "Score_Stats": "Punktestatistiken", + "Show_dub_status_AnimeList_Desc": "Dub-Status (Englisch) eines Animes in der Liste anzeigen", + "Download_ICS": "Laden Sie .ics herunter", + "Share_ICS": "Teilen Sie .ics", + "File_Saved": "Datei im Download-Ordner gespeichert!", + "Error_Saving_File": "Fehler beim Speichern der Datei!", + "View_Related_Graph_Tooltip": "Zugeh\u00f6riges Anime-/Manga-Diagramm anzeigen", + "Calendar": "Kalender" } \ No newline at end of file diff --git a/lib/l10n/intl_es_ES.arb b/lib/l10n/intl_es_ES.arb index a8fc0cf..16ca233 100644 --- a/lib/l10n/intl_es_ES.arb +++ b/lib/l10n/intl_es_ES.arb @@ -686,14 +686,14 @@ "Auto_Add_Start_End_Date_Desc": "Agrega autom\u00e1ticamente la fecha de inicio y finalizaci\u00f3n cuando el estado se mueve a viendo/completado.", "Show_Airing_info_AnimeList": "Mostrar el tiempo de emisi\u00f3n en la lista de anime", "Show_Airing_info_AnimeList_Desc": "Mostrar informaci\u00f3n de transmisi\u00f3n del anime en curso con el pr\u00f3ximo recuento de episodios", - "Dub_Settings": "Configuraci\u00F3n de doblaje", - "Dub_Settings_Desc": "Personaliza tu configuraci\u00F3n de doblaje", + "Dub_Settings": "Configuraci\u00f3n de doblaje", + "Dub_Settings_Desc": "Personaliza tu configuraci\u00f3n de doblaje", "Dub_Show_Icon": "Mostrar icono de doblaje", "Dub_Show_Icon_Desc": "Habilitar el icono de doblaje junto al anime doblado", "Dub_Language": "Lenguaje de doblaje", "Dub_Language_Desc": "Seleccione el idioma para los doblajes", "Dub_Confidence": "Dub confianza", - "Dub_Confidence_Desc": "N\u00FAmero m\u00EDnimo de fuentes necesarias para marcar un anime como doblado (mostrar el \u00EDcono de doblaje)", + "Dub_Confidence_Desc": "N\u00famero m\u00ednimo de fuentes necesarias para marcar un anime como doblado (mostrar el \u00edcono de doblaje)", "Dub_Icon_Style": "Estilo de icono", "Dub_Icon_Style_Desc": "Seleccione el estilo de icono para anime doblado y parcialmente doblado", "Dub_Report": "Informar sobre doblajes inexactos", @@ -1020,8 +1020,16 @@ "Add": "Agregar", "Private_Note": "Nota Privada", "Show_Private_Review": "Mostrar Notas Privadas", - "Show_Private_Review_Desc": "Mostrar el campo de notas privadas en la pantalla de edición", - "Private_Note_Desc": "Guardado localmente, nunca se envía a los servidores", - "Private_Note_Hint": "Escribe tu nota privada aquí...", - "Private_Note_Local_Only": "Esta nota es solo local y no se sincronizará." + "Show_Private_Review_Desc": "Mostrar el campo de notas privadas en la pantalla de edici\u00f3n", + "Private_Note_Desc": "Guardado localmente, nunca se env\u00eda a los servidores", + "Private_Note_Hint": "Escribe tu nota privada aqu\u00ed...", + "Private_Note_Local_Only": "Esta nota es solo local y no se sincronizar\u00e1.", + "Score_Stats": "Estad\u00edsticas de puntuaci\u00f3n", + "Show_dub_status_AnimeList_Desc": "Mostrar el estado de doblaje (ingl\u00e9s) de un anime en la lista", + "Download_ICS": "Descargar .ics", + "Share_ICS": "Compartir .ics", + "File_Saved": "\u00a1Archivo guardado en la carpeta de descargas!", + "Error_Saving_File": "\u00a1Error al guardar el archivo!", + "View_Related_Graph_Tooltip": "Ver gr\u00e1fico de anime/manga relacionado", + "Calendar": "Calendario" } \ No newline at end of file diff --git a/lib/l10n/intl_fr_FR.arb b/lib/l10n/intl_fr_FR.arb index 40d2b52..aa6dbc0 100644 --- a/lib/l10n/intl_fr_FR.arb +++ b/lib/l10n/intl_fr_FR.arb @@ -686,15 +686,15 @@ "Show_Airing_info_AnimeList": "Afficher le temps de diffusion sur la liste des anime", "Show_Airing_info_AnimeList_Desc": "Afficher les informations de diffusion de l'anime en cours avec le prochain nombre d'\u00e9pisodes", "Dub_Settings": "Signaler les doublages inexacts", - "Dub_Settings_Desc": "Personnalisez vos param\u00E8tres de doublage", - "Dub_Show_Icon": "Afficher l'ic\u00F4ne de doublage", - "Dub_Show_Icon_Desc": "Activer l'ic\u00F4ne de doublage \u00E0 c\u00F4t\u00E9 de l'anime doubl\u00E9", + "Dub_Settings_Desc": "Personnalisez vos param\u00e8tres de doublage", + "Dub_Show_Icon": "Afficher l'ic\u00f4ne de doublage", + "Dub_Show_Icon_Desc": "Activer l'ic\u00f4ne de doublage \u00e0 c\u00f4t\u00e9 de l'anime doubl\u00e9", "Dub_Language": "Langue dub", - "Dub_Language_Desc": "S\u00E9lectionnez la langue pour les doublages", + "Dub_Language_Desc": "S\u00e9lectionnez la langue pour les doublages", "Dub_Confidence": "Doublage de confiance", - "Dub_Confidence_Desc": "Nombre minimum de sources requises pour marquer un anime comme doubl\u00E9 (afficher l'ic\u00F4ne de doublage)", - "Dub_Icon_Style": "Style d'ic\u00F4ne", - "Dub_Icon_Style_Desc": "S\u00E9lectionnez le style d'ic\u00F4ne pour les animes doubl\u00E9s et partiellement doubl\u00E9s", + "Dub_Confidence_Desc": "Nombre minimum de sources requises pour marquer un anime comme doubl\u00e9 (afficher l'ic\u00f4ne de doublage)", + "Dub_Icon_Style": "Style d'ic\u00f4ne", + "Dub_Icon_Style_Desc": "S\u00e9lectionnez le style d'ic\u00f4ne pour les animes doubl\u00e9s et partiellement doubl\u00e9s", "Dub_Report": "Signaler les doublages inexacts", "Dub_Support": "Soutenez le projet MyDubList", "Made_With_Flutter": "Fabriqu\u00e9 avec", @@ -1016,5 +1016,19 @@ "Add_To_Calendar_Prompt": "Ajouter au calendrier", "Add_Recurring_Event": "Hebdomadaire r\u00e9current", "Add_Recurring_Event_Desc": "Ajouter les futurs \u00e9pisodes comme \u00e9v\u00e9nements hebdomadaires", - "Add": "Ajouter" + "Add": "Ajouter", + "Score_Stats": "Statistiques des scores", + "Show_dub_status_AnimeList_Desc": "Afficher le statut de doublage (anglais) d'un anime dans la liste", + "Download_ICS": "T\u00e9l\u00e9charger .ics", + "Share_ICS": "Partager .ics", + "File_Saved": "Fichier enregistr\u00e9 dans le dossier de t\u00e9l\u00e9chargement\u00a0!", + "Error_Saving_File": "Erreur lors de l'enregistrement du fichier\u00a0!", + "View_Related_Graph_Tooltip": "Voir le graphique anime/manga associ\u00e9", + "Calendar": "Calendrier", + "Private_Note": "Note priv\u00e9e", + "Show_Private_Review": "Afficher l'avis priv\u00e9", + "Show_Private_Review_Desc": "Afficher le champ de note priv\u00e9e dans l'\u00e9cran d'\u00e9dition", + "Private_Note_Desc": "Enregistr\u00e9 localement, jamais envoy\u00e9 aux serveurs", + "Private_Note_Hint": "\u00c9crivez votre note priv\u00e9e ici...", + "Private_Note_Local_Only": "Cette note est locale uniquement et ne sera pas synchronis\u00e9e." } \ No newline at end of file diff --git a/lib/l10n/intl_id_ID.arb b/lib/l10n/intl_id_ID.arb index 0306f92..a9fe399 100644 --- a/lib/l10n/intl_id_ID.arb +++ b/lib/l10n/intl_id_ID.arb @@ -1022,5 +1022,13 @@ "Show_Private_Review_Desc": "Tampilkan kolom catatan pribadi di layar edit", "Private_Note_Desc": "Disimpan secara lokal, tidak pernah dikirim ke server", "Private_Note_Hint": "Tulis catatan pribadi Anda di sini...", - "Private_Note_Local_Only": "Catatan ini hanya bersifat lokal dan tidak akan disinkronkan." + "Private_Note_Local_Only": "Catatan ini hanya bersifat lokal dan tidak akan disinkronkan.", + "Score_Stats": "Statistik Skor", + "Show_dub_status_AnimeList_Desc": "Tampilkan status dubbing (Bahasa Inggris) suatu anime dalam daftar", + "Download_ICS": "Unduh .ics", + "Share_ICS": "Bagikan .ics", + "File_Saved": "File disimpan ke folder unduhan!", + "Error_Saving_File": "Terjadi kesalahan saat menyimpan file!", + "View_Related_Graph_Tooltip": "Lihat grafik anime/manga terkait", + "Calendar": "Kalender" } \ No newline at end of file diff --git a/lib/l10n/intl_ja.arb b/lib/l10n/intl_ja.arb index 38ee2ae..03a3612 100644 --- a/lib/l10n/intl_ja.arb +++ b/lib/l10n/intl_ja.arb @@ -685,18 +685,18 @@ "Auto_Add_Start_End_Date_Desc": "\u30b9\u30c6\u30fc\u30bf\u30b9\u304c\u76e3\u8996/\u5b8c\u4e86\u306b\u79fb\u884c\u3059\u308b\u3068\u3001\u958b\u59cb\u65e5\u3068\u7d42\u4e86\u65e5\u304c\u81ea\u52d5\u7684\u306b\u8ffd\u52a0\u3055\u308c\u307e\u3059\u3002", "Show_Airing_info_AnimeList": "\u30a2\u30cb\u30e1\u30ea\u30b9\u30c8\u306b\u653e\u6620\u6642\u9593\u3092\u8868\u793a", "Show_Airing_info_AnimeList_Desc": "\u6b21\u306e\u30a8\u30d4\u30bd\u30fc\u30c9\u6570\u3067\u9032\u884c\u4e2d\u306e\u30a2\u30cb\u30e1\u306e\u653e\u9001\u60c5\u5831\u3092\u8868\u793a\u3059\u308b", - "Dub_Settings": "\u30C0\u30D6\u8A2D\u5B9A", - "Dub_Settings_Desc": "\u5439\u304D\u66FF\u3048\u8A2D\u5B9A\u3092\u30AB\u30B9\u30BF\u30DE\u30A4\u30BA\u3059\u308B", - "Dub_Show_Icon": "\u5439\u304D\u66FF\u3048\u30A2\u30A4\u30B3\u30F3\u3092\u8868\u793A", - "Dub_Show_Icon_Desc": "\u5439\u304D\u66FF\u3048\u30A2\u30CB\u30E1\u306E\u6A2A\u306B\u3042\u308B\u5439\u304D\u66FF\u3048\u30A2\u30A4\u30B3\u30F3\u3092\u6709\u52B9\u306B\u3059\u308B", - "Dub_Language": "\u5439\u304D\u66FF\u3048\u8A00\u8A9E", - "Dub_Language_Desc": "\u5439\u304D\u66FF\u3048\u306E\u8A00\u8A9E\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044", - "Dub_Confidence": "\u30C0\u30D6\u306E\u81EA\u4FE1", - "Dub_Confidence_Desc": "\u30A2\u30CB\u30E1\u3092\u5439\u304D\u66FF\u3048\u3068\u3057\u3066\u30DE\u30FC\u30AF\u3059\u308B\u305F\u3081\u306B\u5FC5\u8981\u306A\u30BD\u30FC\u30B9\u306E\u6700\u5C0F\u6570\uFF08\u5439\u304D\u66FF\u3048\u30A2\u30A4\u30B3\u30F3\u3092\u8868\u793A\uFF09", - "Dub_Icon_Style": "\u30A2\u30A4\u30B3\u30F3\u30B9\u30BF\u30A4\u30EB", - "Dub_Icon_Style_Desc": "\u5439\u304D\u66FF\u3048\u7248\u304A\u3088\u3073\u90E8\u5206\u5439\u304D\u66FF\u3048\u7248\u30A2\u30CB\u30E1\u306E\u30A2\u30A4\u30B3\u30F3\u30B9\u30BF\u30A4\u30EB\u3092\u9078\u629E\u3057\u307E\u3059", - "Dub_Report": "\u4E0D\u6B63\u78BA\u306A\u5439\u304D\u66FF\u3048\u3092\u5831\u544A\u3059\u308B", - "Dub_Support": "MyDubList\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u3092\u30B5\u30DD\u30FC\u30C8\u3059\u308B", + "Dub_Settings": "\u30c0\u30d6\u8a2d\u5b9a", + "Dub_Settings_Desc": "\u5439\u304d\u66ff\u3048\u8a2d\u5b9a\u3092\u30ab\u30b9\u30bf\u30de\u30a4\u30ba\u3059\u308b", + "Dub_Show_Icon": "\u5439\u304d\u66ff\u3048\u30a2\u30a4\u30b3\u30f3\u3092\u8868\u793a", + "Dub_Show_Icon_Desc": "\u5439\u304d\u66ff\u3048\u30a2\u30cb\u30e1\u306e\u6a2a\u306b\u3042\u308b\u5439\u304d\u66ff\u3048\u30a2\u30a4\u30b3\u30f3\u3092\u6709\u52b9\u306b\u3059\u308b", + "Dub_Language": "\u5439\u304d\u66ff\u3048\u8a00\u8a9e", + "Dub_Language_Desc": "\u5439\u304d\u66ff\u3048\u306e\u8a00\u8a9e\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044", + "Dub_Confidence": "\u30c0\u30d6\u306e\u81ea\u4fe1", + "Dub_Confidence_Desc": "\u30a2\u30cb\u30e1\u3092\u5439\u304d\u66ff\u3048\u3068\u3057\u3066\u30de\u30fc\u30af\u3059\u308b\u305f\u3081\u306b\u5fc5\u8981\u306a\u30bd\u30fc\u30b9\u306e\u6700\u5c0f\u6570\uff08\u5439\u304d\u66ff\u3048\u30a2\u30a4\u30b3\u30f3\u3092\u8868\u793a\uff09", + "Dub_Icon_Style": "\u30a2\u30a4\u30b3\u30f3\u30b9\u30bf\u30a4\u30eb", + "Dub_Icon_Style_Desc": "\u5439\u304d\u66ff\u3048\u7248\u304a\u3088\u3073\u90e8\u5206\u5439\u304d\u66ff\u3048\u7248\u30a2\u30cb\u30e1\u306e\u30a2\u30a4\u30b3\u30f3\u30b9\u30bf\u30a4\u30eb\u3092\u9078\u629e\u3057\u307e\u3059", + "Dub_Report": "\u4e0d\u6b63\u78ba\u306a\u5439\u304d\u66ff\u3048\u3092\u5831\u544a\u3059\u308b", + "Dub_Support": "MyDubList\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u3092\u30b5\u30dd\u30fc\u30c8\u3059\u308b", "Made_With_Flutter": "\u3067\u4f5c\u3063\u305f", "Cannot_launch": "\u8d77\u52d5\u3067\u304d\u307e\u305b\u3093", "Anime_Manga_BG": "\u30a2\u30cb\u30e1\u30fb\u30de\u30f3\u30ac\u306e\u80cc\u666f", @@ -1017,10 +1017,18 @@ "Add_Recurring_Event": "\u6bce\u9031\u7e70\u308a\u8fd4\u3057", "Add_Recurring_Event_Desc": "Add future episodes as weekly events", "Add": "\u8ffd\u52a0", - "Private_Note": "プライベートノート", - "Show_Private_Review": "プライベートレビューを表示", - "Show_Private_Review_Desc": "編集画面にプライベートノートフィールドを表示する", - "Private_Note_Desc": "ローカルに保存され、サーバーには送信されません", - "Private_Note_Hint": "ここにプライベートノートを書いてください...", - "Private_Note_Local_Only": "このノートはローカルのみであり、同期されません。" + "Private_Note": "\u30d7\u30e9\u30a4\u30d9\u30fc\u30c8\u30ce\u30fc\u30c8", + "Show_Private_Review": "\u30d7\u30e9\u30a4\u30d9\u30fc\u30c8\u30ec\u30d3\u30e5\u30fc\u3092\u8868\u793a", + "Show_Private_Review_Desc": "\u7de8\u96c6\u753b\u9762\u306b\u30d7\u30e9\u30a4\u30d9\u30fc\u30c8\u30ce\u30fc\u30c8\u30d5\u30a3\u30fc\u30eb\u30c9\u3092\u8868\u793a\u3059\u308b", + "Private_Note_Desc": "\u30ed\u30fc\u30ab\u30eb\u306b\u4fdd\u5b58\u3055\u308c\u3001\u30b5\u30fc\u30d0\u30fc\u306b\u306f\u9001\u4fe1\u3055\u308c\u307e\u305b\u3093", + "Private_Note_Hint": "\u3053\u3053\u306b\u30d7\u30e9\u30a4\u30d9\u30fc\u30c8\u30ce\u30fc\u30c8\u3092\u66f8\u3044\u3066\u304f\u3060\u3055\u3044...", + "Private_Note_Local_Only": "\u3053\u306e\u30ce\u30fc\u30c8\u306f\u30ed\u30fc\u30ab\u30eb\u306e\u307f\u3067\u3042\u308a\u3001\u540c\u671f\u3055\u308c\u307e\u305b\u3093\u3002", + "Score_Stats": "\u30b9\u30b3\u30a2\u7d71\u8a08", + "Show_dub_status_AnimeList_Desc": "\u30a2\u30cb\u30e1\u306e\u5439\u304d\u66ff\u3048\uff08\u82f1\u8a9e\uff09\u30b9\u30c6\u30fc\u30bf\u30b9\u3092\u30ea\u30b9\u30c8\u306b\u8868\u793a\u3057\u307e\u3059", + "Download_ICS": ".ics\u3092\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9", + "Share_ICS": ".ics\u3092\u5171\u6709\u3059\u308b", + "File_Saved": "\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u30d5\u30a9\u30eb\u30c0\u306b\u30d5\u30a1\u30a4\u30eb\u304c\u4fdd\u5b58\u3055\u308c\u307e\u3057\u305f\uff01", + "Error_Saving_File": "\u30d5\u30a1\u30a4\u30eb\u306e\u4fdd\u5b58\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f!", + "View_Related_Graph_Tooltip": "\u95a2\u9023\u3059\u308b\u30a2\u30cb\u30e1/\u30de\u30f3\u30ac\u306e\u30b0\u30e9\u30d5\u3092\u8868\u793a", + "Calendar": "\u30ab\u30ec\u30f3\u30c0\u30fc" } \ No newline at end of file diff --git a/lib/l10n/intl_ko_KR.arb b/lib/l10n/intl_ko_KR.arb index 5efa187..d564510 100644 --- a/lib/l10n/intl_ko_KR.arb +++ b/lib/l10n/intl_ko_KR.arb @@ -685,18 +685,18 @@ "Auto_Add_Start_End_Date_Desc": "\uc0c1\ud0dc\uac00 \uc2dc\uccad/\uc644\ub8cc\ub85c \uc804\ud658\ub418\uba74 \uc2dc\uc791 \ub0a0\uc9dc\uc640 \uc885\ub8cc \ub0a0\uc9dc\ub97c \uc790\ub3d9\uc73c\ub85c \ucd94\uac00\ud569\ub2c8\ub2e4.", "Show_Airing_info_AnimeList": "\uc560\ub2c8\uba54\uc774\uc158 \ubaa9\ub85d\uc5d0 \ubc29\uc601 \uc2dc\uac04 \ud45c\uc2dc", "Show_Airing_info_AnimeList_Desc": "\ub2e4\uc74c \uc5d0\ud53c\uc18c\ub4dc \uc218\uc640 \ud568\uaed8 \uc9c4\ud589 \uc911\uc778 \uc560\ub2c8\uba54\uc774\uc158\uc758 \ubc29\uc601 \uc815\ubcf4 \ud45c\uc2dc", - "Dub_Settings": "\uB354\uBE59 \uC124\uC815", - "Dub_Settings_Desc": "\uB354\uBE59 \uC124\uC815 \uC0AC\uC6A9\uC790 \uC9C0\uC815", - "Dub_Show_Icon": "\uB354\uBE59 \uC544\uC774\uCF58 \uD45C\uC2DC", - "Dub_Show_Icon_Desc": "\uB354\uBE59\uB41C \uC560\uB2C8\uBA54\uC774\uC158 \uC606\uC5D0 \uC788\uB294 \uB354\uBE59 \uC544\uC774\uCF58\uC744 \uD65C\uC131\uD654\uD558\uC138\uC694", - "Dub_Language": "\uB354\uBE0C \uC5B8\uC5B4", - "Dub_Language_Desc": "\uB354\uBE59 \uC5B8\uC5B4\uB97C \uC120\uD0DD\uD558\uC138\uC694", - "Dub_Confidence": "\uB354\uBE0C \uCEE8\uD53C\uB358\uC2A4", - "Dub_Confidence_Desc": "\uC560\uB2C8\uBA54\uC774\uC158\uC744 \uB354\uBE59\uC73C\uB85C \uD45C\uC2DC\uD558\uB294 \uB370 \uD544\uC694\uD55C \uCD5C\uC18C \uC18C\uC2A4 \uC218(\uB354\uBE59 \uC544\uC774\uCF58 \uD45C\uC2DC)", - "Dub_Icon_Style": "\uC544\uC774\uCF58 \uC2A4\uD0C0\uC77C", - "Dub_Icon_Style_Desc": "\uB354\uBE59 \uBC0F \uBD80\uBD84 \uB354\uBE59 \uC560\uB2C8\uBA54\uC774\uC158\uC758 \uC544\uC774\uCF58 \uC2A4\uD0C0\uC77C\uC744 \uC120\uD0DD\uD558\uC138\uC694", - "Dub_Report": "\uBD80\uC815\uD655\uD55C \uB354\uBE59 \uC2E0\uACE0", - "Dub_Support": "MyDubList \uD504\uB85C\uC81D\uD2B8\uB97C \uC9C0\uC6D0\uD558\uC138\uC694", + "Dub_Settings": "\ub354\ube59 \uc124\uc815", + "Dub_Settings_Desc": "\ub354\ube59 \uc124\uc815 \uc0ac\uc6a9\uc790 \uc9c0\uc815", + "Dub_Show_Icon": "\ub354\ube59 \uc544\uc774\ucf58 \ud45c\uc2dc", + "Dub_Show_Icon_Desc": "\ub354\ube59\ub41c \uc560\ub2c8\uba54\uc774\uc158 \uc606\uc5d0 \uc788\ub294 \ub354\ube59 \uc544\uc774\ucf58\uc744 \ud65c\uc131\ud654\ud558\uc138\uc694", + "Dub_Language": "\ub354\ube0c \uc5b8\uc5b4", + "Dub_Language_Desc": "\ub354\ube59 \uc5b8\uc5b4\ub97c \uc120\ud0dd\ud558\uc138\uc694", + "Dub_Confidence": "\ub354\ube0c \ucee8\ud53c\ub358\uc2a4", + "Dub_Confidence_Desc": "\uc560\ub2c8\uba54\uc774\uc158\uc744 \ub354\ube59\uc73c\ub85c \ud45c\uc2dc\ud558\ub294 \ub370 \ud544\uc694\ud55c \ucd5c\uc18c \uc18c\uc2a4 \uc218(\ub354\ube59 \uc544\uc774\ucf58 \ud45c\uc2dc)", + "Dub_Icon_Style": "\uc544\uc774\ucf58 \uc2a4\ud0c0\uc77c", + "Dub_Icon_Style_Desc": "\ub354\ube59 \ubc0f \ubd80\ubd84 \ub354\ube59 \uc560\ub2c8\uba54\uc774\uc158\uc758 \uc544\uc774\ucf58 \uc2a4\ud0c0\uc77c\uc744 \uc120\ud0dd\ud558\uc138\uc694", + "Dub_Report": "\ubd80\uc815\ud655\ud55c \ub354\ube59 \uc2e0\uace0", + "Dub_Support": "MyDubList \ud504\ub85c\uc81d\ud2b8\ub97c \uc9c0\uc6d0\ud558\uc138\uc694", "Made_With_Flutter": "\ub85c \ub9cc\ub4e0", "Cannot_launch": "\uc2e4\ud589\ud560 \uc218 \uc5c6\uc74c", "Anime_Manga_BG": "\uc560\ub2c8\uba54\uc774\uc158/\ub9cc\ud654\uc758 \ubc30\uacbd", @@ -1017,10 +1017,18 @@ "Add_Recurring_Event": "\ub9e4\uc8fc \ubc18\ubcf5", "Add_Recurring_Event_Desc": "\uc8fc\uac04 \uc774\ubca4\ud2b8\ub85c \ud5a5\ud6c4 \uc5d0\ud53c\uc18c\ub4dc\ub97c \ucd94\uac00\ud558\uc2ed\uc2dc\uc624", "Add": "\ucd94\uac00\ud558\ub2e4", - "Private_Note": "개인 메모", - "Show_Private_Review": "개인 메모 표시", - "Show_Private_Review_Desc": "편집 화면에서 개인 메모 필드를 표시합니다.", - "Private_Note_Desc": "로컬에 저장되며 서버로 전송되지 않습니다.", - "Private_Note_Hint": "여기에 개인 메모를 작성하세요...", - "Private_Note_Local_Only": "이 메모는 로컬 전용이며 동기화되지 않습니다." + "Private_Note": "\uac1c\uc778 \uba54\ubaa8", + "Show_Private_Review": "\uac1c\uc778 \uba54\ubaa8 \ud45c\uc2dc", + "Show_Private_Review_Desc": "\ud3b8\uc9d1 \ud654\uba74\uc5d0\uc11c \uac1c\uc778 \uba54\ubaa8 \ud544\ub4dc\ub97c \ud45c\uc2dc\ud569\ub2c8\ub2e4.", + "Private_Note_Desc": "\ub85c\uceec\uc5d0 \uc800\uc7a5\ub418\uba70 \uc11c\ubc84\ub85c \uc804\uc1a1\ub418\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.", + "Private_Note_Hint": "\uc5ec\uae30\uc5d0 \uac1c\uc778 \uba54\ubaa8\ub97c \uc791\uc131\ud558\uc138\uc694...", + "Private_Note_Local_Only": "\uc774 \uba54\ubaa8\ub294 \ub85c\uceec \uc804\uc6a9\uc774\uba70 \ub3d9\uae30\ud654\ub418\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.", + "Score_Stats": "\uc810\uc218 \ud1b5\uacc4", + "Show_dub_status_AnimeList_Desc": "\ubaa9\ub85d\uc5d0 \uc788\ub294 \uc560\ub2c8\uba54\uc774\uc158\uc758 \ub354\ube59(\uc601\uc5b4) \uc0c1\ud0dc \ud45c\uc2dc", + "Download_ICS": ".ics \ub2e4\uc6b4\ub85c\ub4dc", + "Share_ICS": ".ics \uacf5\uc720", + "File_Saved": "\ub2e4\uc6b4\ub85c\ub4dc \ud3f4\ub354\uc5d0 \ud30c\uc77c\uc774 \uc800\uc7a5\ub418\uc5c8\uc2b5\ub2c8\ub2e4!", + "Error_Saving_File": "\ud30c\uc77c\uc744 \uc800\uc7a5\ud558\ub294 \uc911\uc5d0 \uc624\ub958\uac00 \ubc1c\uc0dd\ud588\uc2b5\ub2c8\ub2e4.", + "View_Related_Graph_Tooltip": "\uad00\ub828 \uc560\ub2c8\uba54\uc774\uc158/\ub9cc\ud654 \uadf8\ub798\ud504 \ubcf4\uae30", + "Calendar": "\ub2ec\ub825" } \ No newline at end of file diff --git a/lib/l10n/intl_pt_BR.arb b/lib/l10n/intl_pt_BR.arb index 859397b..de6a62b 100644 --- a/lib/l10n/intl_pt_BR.arb +++ b/lib/l10n/intl_pt_BR.arb @@ -686,16 +686,16 @@ "Auto_Add_Start_End_Date_Desc": "Adiciona automaticamente a data de in\u00edcio e t\u00e9rmino quando o status \u00e9 movido para assistindo/conclu\u00eddo.", "Show_Airing_info_AnimeList": "Mostrar tempo de exibi\u00e7\u00e3o na lista de animes", "Show_Airing_info_AnimeList_Desc": "Mostrar informa\u00e7\u00f5es de exibi\u00e7\u00e3o do anime em andamento com a pr\u00f3xima contagem de epis\u00f3dios", - "Dub_Settings": "Configura\u00E7\u00F5es de dublagem", - "Dub_Settings_Desc": "Personalize suas configura\u00E7\u00F5es de dublagem", - "Dub_Show_Icon": "Mostrar \u00EDcone de dublagem", - "Dub_Show_Icon_Desc": "Habilitar o \u00EDcone de dublagem ao lado do anime dublado", + "Dub_Settings": "Configura\u00e7\u00f5es de dublagem", + "Dub_Settings_Desc": "Personalize suas configura\u00e7\u00f5es de dublagem", + "Dub_Show_Icon": "Mostrar \u00edcone de dublagem", + "Dub_Show_Icon_Desc": "Habilitar o \u00edcone de dublagem ao lado do anime dublado", "Dub_Language": "Linguagem de dublagem", "Dub_Language_Desc": "Selecione o idioma para dublagens", - "Dub_Confidence": "Confian\u00E7a Dub", - "Dub_Confidence_Desc": "N\u00FAmero m\u00EDnimo de fontes necess\u00E1rias para marcar um anime como dublado (mostrar o \u00EDcone de dublagem)", - "Dub_Icon_Style": "Estilo de \u00EDcone", - "Dub_Icon_Style_Desc": "Selecione o estilo do \u00EDcone para anime dublado e parcialmente dublado", + "Dub_Confidence": "Confian\u00e7a Dub", + "Dub_Confidence_Desc": "N\u00famero m\u00ednimo de fontes necess\u00e1rias para marcar um anime como dublado (mostrar o \u00edcone de dublagem)", + "Dub_Icon_Style": "Estilo de \u00edcone", + "Dub_Icon_Style_Desc": "Selecione o estilo do \u00edcone para anime dublado e parcialmente dublado", "Dub_Report": "Denunciar dublagens imprecisas", "Dub_Support": "Apoie o projeto MyDubList", "Made_With_Flutter": "Feito com", @@ -1020,8 +1020,16 @@ "Add": "Adicionar", "Private_Note": "Nota Privada", "Show_Private_Review": "Mostrar Nota Privada", - "Show_Private_Review_Desc": "Mostrar campo de nota privada na tela de edição", + "Show_Private_Review_Desc": "Mostrar campo de nota privada na tela de edi\u00e7\u00e3o", "Private_Note_Desc": "Salvo localmente, nunca enviado para servidores", "Private_Note_Hint": "Escreva sua nota privada aqui...", - "Private_Note_Local_Only": "Esta nota é apenas local e não será sincronizada." + "Private_Note_Local_Only": "Esta nota \u00e9 apenas local e n\u00e3o ser\u00e1 sincronizada.", + "Score_Stats": "Estat\u00edsticas de pontua\u00e7\u00e3o", + "Show_dub_status_AnimeList_Desc": "Mostrar status de dublagem (ingl\u00eas) de um anime na lista", + "Download_ICS": "Baixar .ics", + "Share_ICS": "Compartilhe .ics", + "File_Saved": "Arquivo salvo na pasta de download!", + "Error_Saving_File": "Erro ao salvar o arquivo!", + "View_Related_Graph_Tooltip": "Ver gr\u00e1fico de anime/mang\u00e1 relacionado", + "Calendar": "Calend\u00e1rio" } \ No newline at end of file diff --git a/lib/l10n/intl_ru_RU.arb b/lib/l10n/intl_ru_RU.arb index f74aa72..0f14279 100644 --- a/lib/l10n/intl_ru_RU.arb +++ b/lib/l10n/intl_ru_RU.arb @@ -686,18 +686,18 @@ "Auto_Add_Start_End_Date_Desc": "\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442 \u0434\u0430\u0442\u0443 \u043d\u0430\u0447\u0430\u043b\u0430 \u0438 \u043e\u043a\u043e\u043d\u0447\u0430\u043d\u0438\u044f, \u043a\u043e\u0433\u0434\u0430 \u0441\u0442\u0430\u0442\u0443\u0441 \u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u043d\u0430 \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440/\u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u043e.", "Show_Airing_info_AnimeList": "\u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0432\u0440\u0435\u043c\u044f \u0432\u044b\u0445\u043e\u0434\u0430 \u0432 \u044d\u0444\u0438\u0440 \u0432 \u0441\u043f\u0438\u0441\u043a\u0435 \u0430\u043d\u0438\u043c\u0435", "Show_Airing_info_AnimeList_Desc": "\u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u0432\u044b\u0445\u043e\u0434\u0435 \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u0430\u043d\u0438\u043c\u0435 \u0441 \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u0435\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u0441\u0435\u0440\u0438\u0439.", - "Dub_Settings": "\u041D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u0438 \u0434\u0443\u0431\u043B\u044F\u0436\u0430", - "Dub_Settings_Desc": "\u041D\u0430\u0441\u0442\u0440\u043E\u0439\u0442\u0435 \u043F\u0430\u0440\u0430\u043C\u0435\u0442\u0440\u044B \u0434\u0443\u0431\u043B\u044F\u0436\u0430", - "Dub_Show_Icon": "\u041F\u043E\u043A\u0430\u0437\u0430\u0442\u044C \u0437\u043D\u0430\u0447\u043E\u043A \u0434\u0443\u0431\u043B\u044F\u0436\u0430", - "Dub_Show_Icon_Desc": "\u0412\u043A\u043B\u044E\u0447\u0438\u0442\u044C \u0437\u043D\u0430\u0447\u043E\u043A \u0434\u0443\u0431\u043B\u044F\u0436\u0430 \u0440\u044F\u0434\u043E\u043C \u0441 \u0434\u0443\u0431\u043B\u0438\u0440\u043E\u0432\u0430\u043D\u043D\u044B\u043C \u0430\u043D\u0438\u043C\u0435", - "Dub_Language": "\u044F\u0437\u044B\u043A \u0434\u0443\u0431\u043B\u044F\u0436\u0430", - "Dub_Language_Desc": "\u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435 \u044F\u0437\u044B\u043A \u0434\u043B\u044F \u0434\u0443\u0431\u043B\u044F\u0436\u0430", - "Dub_Confidence": "\u0414\u0443\u0431\u043B\u0438\u0440\u043E\u0432\u0430\u043D\u043D\u0430\u044F \u0443\u0432\u0435\u0440\u0435\u043D\u043D\u043E\u0441\u0442\u044C", - "Dub_Confidence_Desc": "\u041C\u0438\u043D\u0438\u043C\u0430\u043B\u044C\u043D\u043E\u0435 \u043A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E \u0438\u0441\u0442\u043E\u0447\u043D\u0438\u043A\u043E\u0432, \u043D\u0435\u043E\u0431\u0445\u043E\u0434\u0438\u043C\u043E\u0435 \u0434\u043B\u044F \u0442\u043E\u0433\u043E, \u0447\u0442\u043E\u0431\u044B \u043E\u0442\u043C\u0435\u0442\u0438\u0442\u044C \u0430\u043D\u0438\u043C\u0435 \u043A\u0430\u043A \u0434\u0443\u0431\u043B\u0438\u0440\u043E\u0432\u0430\u043D\u043D\u043E\u0435 (\u043F\u043E\u043A\u0430\u0437\u0430\u0442\u044C \u0437\u043D\u0430\u0447\u043E\u043A \u0434\u0443\u0431\u043B\u044F\u0436\u0430)", - "Dub_Icon_Style": "\u0418\u043A\u043E\u043D\u0438\u0447\u0435\u0441\u043A\u0438\u0439 \u0441\u0442\u0438\u043B\u044C", - "Dub_Icon_Style_Desc": "\u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435 \u0441\u0442\u0438\u043B\u044C \u0437\u043D\u0430\u0447\u043A\u0430 \u0434\u043B\u044F \u0434\u0443\u0431\u043B\u0438\u0440\u043E\u0432\u0430\u043D\u043D\u043E\u0433\u043E \u0438 \u0447\u0430\u0441\u0442\u0438\u0447\u043D\u043E \u0434\u0443\u0431\u043B\u0438\u0440\u043E\u0432\u0430\u043D\u043D\u043E\u0433\u043E \u0430\u043D\u0438\u043C\u0435.", - "Dub_Report": "\u0421\u043E\u043E\u0431\u0449\u0438\u0442\u044C \u043E \u043D\u0435\u0442\u043E\u0447\u043D\u044B\u0445 \u0434\u0443\u0431\u043B\u044F\u0436\u0430\u0445", - "Dub_Support": "\u041F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0442\u0435 \u043F\u0440\u043E\u0435\u043A\u0442 MyDubList", + "Dub_Settings": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0434\u0443\u0431\u043b\u044f\u0436\u0430", + "Dub_Settings_Desc": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u0442\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0434\u0443\u0431\u043b\u044f\u0436\u0430", + "Dub_Show_Icon": "\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0437\u043d\u0430\u0447\u043e\u043a \u0434\u0443\u0431\u043b\u044f\u0436\u0430", + "Dub_Show_Icon_Desc": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0437\u043d\u0430\u0447\u043e\u043a \u0434\u0443\u0431\u043b\u044f\u0436\u0430 \u0440\u044f\u0434\u043e\u043c \u0441 \u0434\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u043c \u0430\u043d\u0438\u043c\u0435", + "Dub_Language": "\u044f\u0437\u044b\u043a \u0434\u0443\u0431\u043b\u044f\u0436\u0430", + "Dub_Language_Desc": "\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u044f\u0437\u044b\u043a \u0434\u043b\u044f \u0434\u0443\u0431\u043b\u044f\u0436\u0430", + "Dub_Confidence": "\u0414\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u0430\u044f \u0443\u0432\u0435\u0440\u0435\u043d\u043d\u043e\u0441\u0442\u044c", + "Dub_Confidence_Desc": "\u041c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u043e\u0432, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0435 \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c \u0430\u043d\u0438\u043c\u0435 \u043a\u0430\u043a \u0434\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0435 (\u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0437\u043d\u0430\u0447\u043e\u043a \u0434\u0443\u0431\u043b\u044f\u0436\u0430)", + "Dub_Icon_Style": "\u0418\u043a\u043e\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0441\u0442\u0438\u043b\u044c", + "Dub_Icon_Style_Desc": "\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0441\u0442\u0438\u043b\u044c \u0437\u043d\u0430\u0447\u043a\u0430 \u0434\u043b\u044f \u0434\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u0438 \u0447\u0430\u0441\u0442\u0438\u0447\u043d\u043e \u0434\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u0430\u043d\u0438\u043c\u0435.", + "Dub_Report": "\u0421\u043e\u043e\u0431\u0449\u0438\u0442\u044c \u043e \u043d\u0435\u0442\u043e\u0447\u043d\u044b\u0445 \u0434\u0443\u0431\u043b\u044f\u0436\u0430\u0445", + "Dub_Support": "\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0442\u0435 \u043f\u0440\u043e\u0435\u043a\u0442 MyDubList", "Made_With_Flutter": "\u0421\u0434\u0435\u043b\u0430\u043d\u043e \u0441", "Anime_Manga_BG": "\u0424\u043e\u043d \u0434\u043b\u044f \u0430\u043d\u0438\u043c\u0435/\u043c\u0430\u043d\u0433\u0438", "Anime_Manga_BG_Desc": "\u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0430\u043d\u0438\u043c\u0435/\u043c\u0430\u043d\u0433\u0438 \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0444\u043e\u043d\u0430", @@ -1015,10 +1015,18 @@ "Add_Recurring_Event": "\u041f\u043e\u0432\u0442\u043e\u0440\u044f\u044e\u0449\u0438\u0439\u0441\u044f \u0435\u0436\u0435\u043d\u0435\u0434\u0435\u043b\u044c\u043d\u044b\u0439", "Add_Recurring_Event_Desc": "\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0431\u0443\u0434\u0443\u0449\u0438\u0435 \u044d\u043f\u0438\u0437\u043e\u0434\u044b \u043a\u0430\u043a \u0435\u0436\u0435\u043d\u0435\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u043c\u0435\u0440\u043e\u043f\u0440\u0438\u044f\u0442\u0438\u044f", "Add": "\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c", - "Private_Note": "Личная заметка", - "Show_Private_Review": "Показать личную заметку", - "Show_Private_Review_Desc": "Показать поле личной заметки на экране редактирования", - "Private_Note_Desc": "Сохранено локально, никогда не отправляется на серверы", - "Private_Note_Hint": "Напишите здесь свою личную заметку...", - "Private_Note_Local_Only": "Эта заметка только локальная и не будет синхронизирована." + "Private_Note": "\u041b\u0438\u0447\u043d\u0430\u044f \u0437\u0430\u043c\u0435\u0442\u043a\u0430", + "Show_Private_Review": "\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u043b\u0438\u0447\u043d\u0443\u044e \u0437\u0430\u043c\u0435\u0442\u043a\u0443", + "Show_Private_Review_Desc": "\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u043e\u043b\u0435 \u043b\u0438\u0447\u043d\u043e\u0439 \u0437\u0430\u043c\u0435\u0442\u043a\u0438 \u043d\u0430 \u044d\u043a\u0440\u0430\u043d\u0435 \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f", + "Private_Note_Desc": "\u0421\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u043e \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e, \u043d\u0438\u043a\u043e\u0433\u0434\u0430 \u043d\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u044b", + "Private_Note_Hint": "\u041d\u0430\u043f\u0438\u0448\u0438\u0442\u0435 \u0437\u0434\u0435\u0441\u044c \u0441\u0432\u043e\u044e \u043b\u0438\u0447\u043d\u0443\u044e \u0437\u0430\u043c\u0435\u0442\u043a\u0443...", + "Private_Note_Local_Only": "\u042d\u0442\u0430 \u0437\u0430\u043c\u0435\u0442\u043a\u0430 \u0442\u043e\u043b\u044c\u043a\u043e \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u0430\u044f \u0438 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u0430.", + "Score_Stats": "\u0421\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0430 \u043e\u0447\u043a\u043e\u0432", + "Show_dub_status_AnimeList_Desc": "\u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0441\u0442\u0430\u0442\u0443\u0441 \u0434\u0443\u0431\u043b\u044f\u0436\u0430 (\u0430\u043d\u0433\u043b\u0438\u0439\u0441\u043a\u043e\u0433\u043e) \u0430\u043d\u0438\u043c\u0435 \u0432 \u0441\u043f\u0438\u0441\u043a\u0435", + "Download_ICS": "\u0421\u043a\u0430\u0447\u0430\u0442\u044c .ics", + "Share_ICS": "\u041f\u043e\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f .ics", + "File_Saved": "\u0424\u0430\u0439\u043b \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d \u0432 \u043f\u0430\u043f\u043a\u0435 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438!", + "Error_Saving_File": "\u041e\u0448\u0438\u0431\u043a\u0430 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0444\u0430\u0439\u043b\u0430!", + "View_Related_Graph_Tooltip": "\u041f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0439 \u0433\u0440\u0430\u0444\u0438\u043a \u0430\u043d\u0438\u043c\u0435/\u043c\u0430\u043d\u0433\u0438", + "Calendar": "\u041a\u0430\u043b\u0435\u043d\u0434\u0430\u0440\u044c" } \ No newline at end of file diff --git a/lib/l10n/intl_tr_TR.arb b/lib/l10n/intl_tr_TR.arb index 2ba8f51..588e37b 100644 --- a/lib/l10n/intl_tr_TR.arb +++ b/lib/l10n/intl_tr_TR.arb @@ -687,15 +687,15 @@ "Show_Airing_info_AnimeList": "Anime listesinde yay\u0131n saatini g\u00f6ster", "Show_Airing_info_AnimeList_Desc": "Bir sonraki b\u00f6l\u00fcm say\u0131s\u0131yla birlikte devam eden animenin yay\u0131n bilgilerini g\u00f6ster", "Dub_Settings": "Dublaj Ayarlar\u0131", - "Dub_Settings_Desc": "Dublaj ayarlar\u0131n\u0131z\u0131 \u00F6zelle\u015Ftirin", - "Dub_Show_Icon": "Dub simgesini g\u00F6ster", - "Dub_Show_Icon_Desc": "Dublajl\u0131 animenin yan\u0131ndaki dublaj simgesini etkinle\u015Ftirin", + "Dub_Settings_Desc": "Dublaj ayarlar\u0131n\u0131z\u0131 \u00f6zelle\u015ftirin", + "Dub_Show_Icon": "Dub simgesini g\u00f6ster", + "Dub_Show_Icon_Desc": "Dublajl\u0131 animenin yan\u0131ndaki dublaj simgesini etkinle\u015ftirin", "Dub_Language": "Dublaj dili", - "Dub_Language_Desc": "Dublaj i\u00E7in dili se\u00E7in", - "Dub_Confidence": "Lakapl\u0131 g\u00FCven", - "Dub_Confidence_Desc": "Bir animeyi dublajl\u0131 olarak i\u015Faretlemek i\u00E7in gereken minimum kaynak say\u0131s\u0131 (dub simgesini g\u00F6ster)", + "Dub_Language_Desc": "Dublaj i\u00e7in dili se\u00e7in", + "Dub_Confidence": "Lakapl\u0131 g\u00fcven", + "Dub_Confidence_Desc": "Bir animeyi dublajl\u0131 olarak i\u015faretlemek i\u00e7in gereken minimum kaynak say\u0131s\u0131 (dub simgesini g\u00f6ster)", "Dub_Icon_Style": "Simge stili", - "Dub_Icon_Style_Desc": "Dublajl\u0131 ve k\u0131smen dublajl\u0131 anime i\u00E7in simge stilini se\u00E7in", + "Dub_Icon_Style_Desc": "Dublajl\u0131 ve k\u0131smen dublajl\u0131 anime i\u00e7in simge stilini se\u00e7in", "Dub_Report": "Hatal\u0131 dublajlar\u0131 bildirin", "Dub_Support": "MyDubList projesini destekleyin", "Made_With_Flutter": "\u0130le yap\u0131lan", @@ -1020,5 +1020,13 @@ "Show_Private_Review_Desc": "D\u00fczenleme ekran\u0131nda \u00f6zel not alan\u0131n\u0131 g\u00f6ster", "Private_Note_Desc": "Yerel olarak kaydedilir, asla sunuculara g\u00f6nderilmez", "Private_Note_Hint": "\u00d6zel notunuzu buraya yaz\u0131n...", - "Private_Note_Local_Only": "Bu not yaln\u0131zca yereldir ve senkronize edilmeyecektir." + "Private_Note_Local_Only": "Bu not yaln\u0131zca yereldir ve senkronize edilmeyecektir.", + "Score_Stats": "Puan \u0130statistikleri", + "Show_dub_status_AnimeList_Desc": "Listede bir animenin dub (\u0130ngilizce) durumunu g\u00f6ster", + "Download_ICS": ".ics'i indirin", + "Share_ICS": ".ics'i payla\u015f\u0131n", + "File_Saved": "Dosya indirme klas\u00f6r\u00fcne kaydedildi!", + "Error_Saving_File": "Dosya kaydedilirken hata olu\u015ftu!", + "View_Related_Graph_Tooltip": "\u0130lgili anime/manga grafi\u011fini g\u00f6r\u00fcnt\u00fcleyin", + "Calendar": "Takvim" } \ No newline at end of file diff --git a/py-req.txt b/python/py-req.txt similarity index 100% rename from py-req.txt rename to python/py-req.txt From f599258f99f034acec668daf410f5ca2f17b676d Mon Sep 17 00:00:00 2001 From: Jishnu Raj Date: Sat, 14 Feb 2026 18:20:07 +0530 Subject: [PATCH 14/16] feat: Update flutter_local_notifications to v20.1.0, adapt notification service to its new API, and add Windows support. --- lib/notifservice.dart | 55 ++++++++++++------------- pubspec.lock | 24 +++++++---- pubspec.yaml | 4 +- windows/flutter/generated_plugins.cmake | 1 + 4 files changed, 46 insertions(+), 38 deletions(-) diff --git a/lib/notifservice.dart b/lib/notifservice.dart index 2490e92..590bdfa 100644 --- a/lib/notifservice.dart +++ b/lib/notifservice.dart @@ -85,7 +85,7 @@ class NotificationService { linux: LinuxInitializationSettings(defaultActionName: 'Open')); await flutterLocalNotificationsPlugin.initialize( - initializationSettings, + settings: initializationSettings, onDidReceiveBackgroundNotificationResponse: onDidReceiveBackgroundNotificationResponse, onDidReceiveNotificationResponse: onDidReceiveNotificationResponse, @@ -305,30 +305,29 @@ class NotificationService { } } else { await flutterLocalNotificationsPlugin.zonedSchedule( - serviceId * 100 + node.id!, - _replaceTags(title) ?? - "DailyAnimeList - ${S.current.Episode_Reminder}", - _replaceTags(body) ?? - "${node.title} - Episode $episode ${S.current.just_got_aired}!!", - exactDate != null - ? tz.TZDateTime.from(exactDate, tz.local) - : tz.TZDateTime.now(tz.local).add(addTime), - NotificationDetails( - android: AndroidNotificationDetails( - channel.channelId, - channel.channelName, - channelDescription: channel.channelDescription, - priority: Priority.high, - styleInformation: styleInfo, - icon: 'ic_stat_name', - largeIcon: largeIconBitmap, - category: AndroidNotificationCategory.reminder, - ), + id: serviceId * 100 + node.id!, + title: _replaceTags(title) ?? + "DailyAnimeList - ${S.current.Episode_Reminder}", + body: _replaceTags(body) ?? + "${node.title} - Episode $episode ${S.current.just_got_aired}!!", + scheduledDate: exactDate != null + ? tz.TZDateTime.from(exactDate, tz.local) + : tz.TZDateTime.now(tz.local).add(addTime), + notificationDetails: NotificationDetails( + android: AndroidNotificationDetails( + channel.channelId, + channel.channelName, + channelDescription: channel.channelDescription, + priority: Priority.high, + styleInformation: styleInfo, + icon: 'ic_stat_name', + largeIcon: largeIconBitmap, + category: AndroidNotificationCategory.reminder, ), - androidScheduleMode: AndroidScheduleMode.exactAllowWhileIdle, - payload: jsonEncode(node.toJson()), - uiLocalNotificationDateInterpretation: - UILocalNotificationDateInterpretation.absoluteTime); + ), + androidScheduleMode: AndroidScheduleMode.exactAllowWhileIdle, + payload: jsonEncode(node.toJson()), + ); } } catch (e) { logDal(e); @@ -349,10 +348,10 @@ class NotificationService { iconPath != null ? FilePathLinuxIcon(iconPath) : null; await flutterLocalNotificationsPlugin.show( - serviceId * 100 + node.id!, - cleanTitle, - cleanBody, - NotificationDetails( + id: serviceId * 100 + node.id!, + title: cleanTitle, + body: cleanBody, + notificationDetails: NotificationDetails( linux: LinuxNotificationDetails( urgency: LinuxNotificationUrgency.normal, icon: linuxIcon, diff --git a/pubspec.lock b/pubspec.lock index 1b95faa..a57b59a 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -537,26 +537,34 @@ packages: dependency: "direct main" description: name: flutter_local_notifications - sha256: "674173fd3c9eda9d4c8528da2ce0ea69f161577495a9cc835a2a4ecd7eadeb35" + sha256: "2b50e938a275e1ad77352d6a25e25770f4130baa61eaf02de7a9a884680954ad" url: "https://pub.dev" source: hosted - version: "17.2.4" + version: "20.1.0" flutter_local_notifications_linux: dependency: transitive description: name: flutter_local_notifications_linux - sha256: c49bd06165cad9beeb79090b18cd1eb0296f4bf4b23b84426e37dd7c027fc3af + sha256: dce0116868cedd2cdf768af0365fc37ff1cbef7c02c4f51d0587482e625868d0 url: "https://pub.dev" source: hosted - version: "4.0.1" + version: "7.0.0" flutter_local_notifications_platform_interface: dependency: transitive description: name: flutter_local_notifications_platform_interface - sha256: "85f8d07fe708c1bdcf45037f2c0109753b26ae077e9d9e899d55971711a4ea66" + sha256: "23de31678a48c084169d7ae95866df9de5c9d2a44be3e5915a2ff067aeeba899" url: "https://pub.dev" source: hosted - version: "7.2.0" + version: "10.0.0" + flutter_local_notifications_windows: + dependency: transitive + description: + name: flutter_local_notifications_windows + sha256: e97a1a3016512437d9c0b12fae7d1491c3c7b9aa7f03a69b974308840656b02a + url: "https://pub.dev" + source: hosted + version: "2.0.1" flutter_localizations: dependency: "direct main" description: flutter @@ -1541,10 +1549,10 @@ packages: dependency: "direct main" description: name: timezone - sha256: "2236ec079a174ce07434e89fcd3fcda430025eb7692244139a9cf54fdcf1fc7d" + sha256: dd14a3b83cfd7cb19e7888f1cbc20f258b8d71b54c06f79ac585f14093a287d1 url: "https://pub.dev" source: hosted - version: "0.9.4" + version: "0.10.1" translator_plus: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index e790da0..bbad3d9 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -47,8 +47,8 @@ dependencies: scroll_to_index: ^3.0.1 share_plus: ^10.0.2 built_collection: ^5.1.0 - flutter_local_notifications: ^17.2.2 - timezone: ^0.9.0 + flutter_local_notifications: ^20.1.0 + timezone: ^0.10.0 flutter_custom_tabs: ^2.1.0 flex_color_picker: ^3.5.1 translator_plus: ^1.0.1 diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index 152cb30..6ee232c 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -18,6 +18,7 @@ list(APPEND FLUTTER_PLUGIN_LIST ) list(APPEND FLUTTER_FFI_PLUGIN_LIST + flutter_local_notifications_windows ) set(PLUGIN_BUNDLED_LIBRARIES) From dfbaedf016ec54642abff416e72e547d16640add Mon Sep 17 00:00:00 2001 From: Jishnu Raj Date: Sat, 14 Feb 2026 18:48:10 +0530 Subject: [PATCH 15/16] refactor: separate MSIX from Windows build archive and generate individual SHA1 checksums for both. --- .github/workflows/release.yml | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e71c914..36061fe 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -97,22 +97,25 @@ jobs: - name: Create MSIX run: dart run msix:create --install-certificate false - - name: Compress Windows Build + - name: Separate MSIX and Compress Windows Build run: | - Compress-Archive -Path build/windows/x64/runner/Release/* -DestinationPath DailyAL-Windows.zip + Move-Item -Path build/windows/x64/runner/Release/*.msix -Destination DailyAL-Windows-x64.msix + Compress-Archive -Path build/windows/x64/runner/Release/* -DestinationPath DailyAL-Windows-x64.zip - - name: Generate SHA1 Checksum + - name: Generate SHA1 Checksums run: | - Get-FileHash DailyAL-Windows.zip -Algorithm SHA1 | Select-Object -ExpandProperty Hash > DailyAL-Windows.zip.sha1 + Get-FileHash DailyAL-Windows-x64.zip -Algorithm SHA1 | Select-Object -ExpandProperty Hash > DailyAL-Windows-x64.zip.sha1 + Get-FileHash DailyAL-Windows-x64.msix -Algorithm SHA1 | Select-Object -ExpandProperty Hash > DailyAL-Windows-x64.msix.sha1 - name: Upload Artifacts uses: actions/upload-artifact@v4 with: name: release-artifacts-windows path: | - build/windows/runner/Release/*.msix - DailyAL-Windows.zip - DailyAL-Windows.zip.sha1 + DailyAL-Windows-x64.msix + DailyAL-Windows-x64.msix.sha1 + DailyAL-Windows-x64.zip + DailyAL-Windows-x64.zip.sha1 release: needs: [build-linux-android, build-windows] @@ -140,6 +143,7 @@ jobs: release-artifacts/app-release.apk.sha1 release-artifacts/DailyAL-x86_64.AppImage release-artifacts/DailyAL-x86_64.AppImage.sha1 - release-artifacts/*.msix - release-artifacts/DailyAL-Windows.zip - release-artifacts/DailyAL-Windows.zip.sha1 + release-artifacts/DailyAL-Windows-x64.msix + release-artifacts/DailyAL-Windows-x64.msix.sha1 + release-artifacts/DailyAL-Windows-x64.zip + release-artifacts/DailyAL-Windows-x64.zip.sha1 From 3d583af006a1c9398c6198d01faee44be5e1f4bb Mon Sep 17 00:00:00 2001 From: Jishnu Raj Date: Sat, 14 Feb 2026 18:51:16 +0530 Subject: [PATCH 16/16] feat: Add workflow_dispatch inputs for selective platform builds and correct a localization typo. --- .github/workflows/release.yml | 16 +++++++++++++++- lib/l10n/intl_en.arb | 2 +- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 36061fe..981b355 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -5,6 +5,16 @@ on: tags: - '20*' workflow_dispatch: + inputs: + platform: + description: 'Platform to build' + required: true + default: 'all' + type: choice + options: + - all + - linux-android + - windows permissions: contents: write @@ -12,6 +22,7 @@ permissions: jobs: build-linux-android: runs-on: ubuntu-latest + if: ${{ github.event_name == 'push' || inputs.platform == 'all' || inputs.platform == 'linux-android' }} steps: - uses: actions/checkout@v4 @@ -76,6 +87,7 @@ jobs: build-windows: runs-on: windows-latest + if: ${{ github.event_name == 'push' || inputs.platform == 'all' || inputs.platform == 'windows' }} steps: - uses: actions/checkout@v4 @@ -120,16 +132,18 @@ jobs: release: needs: [build-linux-android, build-windows] runs-on: ubuntu-latest - if: startsWith(github.ref, 'refs/tags/20') + if: ${{ always() && startsWith(github.ref, 'refs/tags/20') }} steps: - name: Download Linux/Android Artifacts + if: ${{ needs.build-linux-android.result == 'success' }} uses: actions/download-artifact@v4 with: name: release-artifacts-linux-android path: release-artifacts - name: Download Windows Artifacts + if: ${{ needs.build-windows.result == 'success' }} uses: actions/download-artifact@v4 with: name: release-artifacts-windows diff --git a/lib/l10n/intl_en.arb b/lib/l10n/intl_en.arb index 29d16d7..a994feb 100644 --- a/lib/l10n/intl_en.arb +++ b/lib/l10n/intl_en.arb @@ -923,7 +923,7 @@ "Grid_Height": "Grid Height", "My_List2": "My List", "showAnimeMangaCard": "Show content card", - "showAnimeMangaCardDesc": "Show card around the content in list view (comfirtable) wherever possible", + "showAnimeMangaCardDesc": "Show card around the content in list view (Comfortable) wherever possible", "moreLinks": "More Links", "Resources": "Resources", "Available_At": "Available At",