From 71a635845209a3ace21def08ce021094ca340474 Mon Sep 17 00:00:00 2001 From: Enbiya Olgun <78034913+NBA2K1@users.noreply.github.com> Date: Sat, 26 Apr 2025 05:03:06 +0200 Subject: [PATCH] Fix #349 Added a checkbox "ignoreFiltersOnSearch" to the library search, so when checked, the whole library will be searched, not just the filtered library (Downloaded, Unwatched/Unread, Started, Bookmarked) + added some comments --- lib/l10n/app_ar.arb | 1 + lib/l10n/app_de.arb | 1 + lib/l10n/app_en.arb | 1 + lib/l10n/app_es.arb | 1 + lib/l10n/app_es_419.arb | 1 + lib/l10n/app_fr.arb | 1 + lib/l10n/app_id.arb | 1 + lib/l10n/app_it.arb | 1 + lib/l10n/app_pt.arb | 1 + lib/l10n/app_pt_BR.arb | 1 + lib/l10n/app_ru.arb | 1 + lib/l10n/app_th.arb | 1 + lib/l10n/app_tr.arb | 1 + lib/l10n/app_zh.arb | 1 + lib/l10n/generated/app_localizations.dart | 6 + lib/l10n/generated/app_localizations_ar.dart | 3 + lib/l10n/generated/app_localizations_de.dart | 3 + lib/l10n/generated/app_localizations_en.dart | 3 + lib/l10n/generated/app_localizations_es.dart | 6 + lib/l10n/generated/app_localizations_fr.dart | 3 + lib/l10n/generated/app_localizations_id.dart | 3 + lib/l10n/generated/app_localizations_it.dart | 3 + lib/l10n/generated/app_localizations_pt.dart | 6 + lib/l10n/generated/app_localizations_ru.dart | 3 + lib/l10n/generated/app_localizations_th.dart | 3 + lib/l10n/generated/app_localizations_tr.dart | 3 + lib/l10n/generated/app_localizations_zh.dart | 3 + lib/modules/library/library_screen.dart | 276 ++++++++++--------- 28 files changed, 213 insertions(+), 125 deletions(-) diff --git a/lib/l10n/app_ar.arb b/lib/l10n/app_ar.arb index a630ff43..c374f0a4 100644 --- a/lib/l10n/app_ar.arb +++ b/lib/l10n/app_ar.arb @@ -8,6 +8,7 @@ "open_random_entry": "فتح مدخل عشوائي", "import": "استيراد", "filter": "مرشح", + "ignore_filters": "تجاهل مرشح", "downloaded": "تم التحميل", "unread": "غير مقروء", "started": "بدأ", diff --git a/lib/l10n/app_de.arb b/lib/l10n/app_de.arb index 098606a0..75d47dfa 100644 --- a/lib/l10n/app_de.arb +++ b/lib/l10n/app_de.arb @@ -8,6 +8,7 @@ "open_random_entry": "Zufälligen Eintrag öffnen", "import": "Importieren", "filter": "Filter", + "ignore_filters": "Filter ignorieren", "downloaded": "Heruntergeladen", "unread": "Ungelesen", "unwatched": "Nicht angeschaut", diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index b822e002..ebb4d9de 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -8,6 +8,7 @@ "open_random_entry": "Open random entry", "import": "Import", "filter": "Filter", + "ignore_filters": "Ignore Filters", "downloaded": "Downloaded", "unread": "Unread", "unwatched": "Unwatched", diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index ddd28692..b0a926ae 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -8,6 +8,7 @@ "open_random_entry": "Abrir entrada aleatoria", "import": "Importar", "filter": "Filtrar", + "ignore_filters": "Ignorar filtros", "downloaded": "Descargado", "unread": "Sin leer", "started": "Comenzado", diff --git a/lib/l10n/app_es_419.arb b/lib/l10n/app_es_419.arb index 9abdeebc..fee5cbdc 100644 --- a/lib/l10n/app_es_419.arb +++ b/lib/l10n/app_es_419.arb @@ -8,6 +8,7 @@ "open_random_entry": "Abrir entrada aleatoria", "import": "Importar", "filter": "Filtrar", + "ignore_filters": "Ignorar filtros", "downloaded": "Descargado", "unread": "Sin leer", "started": "Comenzado", diff --git a/lib/l10n/app_fr.arb b/lib/l10n/app_fr.arb index a52fb769..a8fbbff9 100644 --- a/lib/l10n/app_fr.arb +++ b/lib/l10n/app_fr.arb @@ -8,6 +8,7 @@ "open_random_entry": "Ouvrir une entrée au hasard", "import": "Importer", "filter": "Filtre", + "ignore_filters": "Ignorer les filtres", "downloaded": "Téléchargé", "unread": "Non lus", "started": "Commencé", diff --git a/lib/l10n/app_id.arb b/lib/l10n/app_id.arb index 889bbde9..ee08b4ae 100644 --- a/lib/l10n/app_id.arb +++ b/lib/l10n/app_id.arb @@ -8,6 +8,7 @@ "open_random_entry": "Buka Entri Acak", "import": "Impor", "filter": "Filter", + "ignore_filters": "Abaikan filter", "downloaded": "Telah Diunduh", "unread": "Belum Dibaca", "started": "Dimulai", diff --git a/lib/l10n/app_it.arb b/lib/l10n/app_it.arb index 8b9c66b4..9bac94f5 100644 --- a/lib/l10n/app_it.arb +++ b/lib/l10n/app_it.arb @@ -8,6 +8,7 @@ "open_random_entry": "Apri voce casuale", "import": "Importa", "filter": "Filtro", + "ignore_filters": "Ignora filtri", "downloaded": "Scaricato", "unread": "Non letto", "started": "Iniziato", diff --git a/lib/l10n/app_pt.arb b/lib/l10n/app_pt.arb index 899eeec1..d33a827e 100644 --- a/lib/l10n/app_pt.arb +++ b/lib/l10n/app_pt.arb @@ -8,6 +8,7 @@ "open_random_entry": "Abrir entrada aleatória", "import": "Importar", "filter": "Filtro", + "ignore_filters": "Ignorar filtros", "downloaded": "Baixados", "unread": "Não lidos", "started": "Iniciados", diff --git a/lib/l10n/app_pt_BR.arb b/lib/l10n/app_pt_BR.arb index 075476ca..26acb106 100644 --- a/lib/l10n/app_pt_BR.arb +++ b/lib/l10n/app_pt_BR.arb @@ -8,6 +8,7 @@ "open_random_entry": "Abrir entrada aleatória", "import": "Importar", "filter": "Filtro", + "ignore_filters": "Ignorar filtros", "downloaded": "Baixado", "unread": "Não lido", "started": "Iniciado", diff --git a/lib/l10n/app_ru.arb b/lib/l10n/app_ru.arb index 3f64a81a..5a17bbbc 100644 --- a/lib/l10n/app_ru.arb +++ b/lib/l10n/app_ru.arb @@ -8,6 +8,7 @@ "open_random_entry": "Открыть случайную запись", "import": "Импорт", "filter": "Фильтр", + "ignore_filters": "Игнорировать фильтры", "downloaded": "Загружено", "unread": "Непрочитанное", "started": "Начато", diff --git a/lib/l10n/app_th.arb b/lib/l10n/app_th.arb index b90322a5..eff6bfe5 100644 --- a/lib/l10n/app_th.arb +++ b/lib/l10n/app_th.arb @@ -8,6 +8,7 @@ "open_random_entry": "สุ่มอ่าน", "import": "นำเข้า", "filter": "ตัวกรอง", + "ignore_filters": "ไม่สนใจตัวกรอง", "downloaded": "ดาวน์โหลดแล้ว", "unread": "ยังไม่อ่าน", "started": "เริ่มแล้ว", diff --git a/lib/l10n/app_tr.arb b/lib/l10n/app_tr.arb index 51eac19f..e4126779 100644 --- a/lib/l10n/app_tr.arb +++ b/lib/l10n/app_tr.arb @@ -8,6 +8,7 @@ "open_random_entry": "Rastgele Giriş Aç", "import": "İçe Aktar", "filter": "Filtre", + "ignore_filters": "Filtreleri yok say", "downloaded": "İndirildi", "unread": "Okunmamış", "started": "Başladı", diff --git a/lib/l10n/app_zh.arb b/lib/l10n/app_zh.arb index 150e36c0..7689fbcd 100644 --- a/lib/l10n/app_zh.arb +++ b/lib/l10n/app_zh.arb @@ -8,6 +8,7 @@ "open_random_entry": "随机打开条目", "import": "导入", "filter": "筛选", + "ignore_filters": "忽略筛选", "downloaded": "已下载", "unread": "未读", "started": "已开始", diff --git a/lib/l10n/generated/app_localizations.dart b/lib/l10n/generated/app_localizations.dart index c797853a..7fc73f5b 100644 --- a/lib/l10n/generated/app_localizations.dart +++ b/lib/l10n/generated/app_localizations.dart @@ -165,6 +165,12 @@ abstract class AppLocalizations { /// **'Filter'** String get filter; + /// No description provided for @ignore_filters. + /// + /// In en, this message translates to: + /// **'Ignore Filters'** + String get ignore_filters; + /// No description provided for @downloaded. /// /// In en, this message translates to: diff --git a/lib/l10n/generated/app_localizations_ar.dart b/lib/l10n/generated/app_localizations_ar.dart index c55146f4..a0a15008 100644 --- a/lib/l10n/generated/app_localizations_ar.dart +++ b/lib/l10n/generated/app_localizations_ar.dart @@ -32,6 +32,9 @@ class AppLocalizationsAr extends AppLocalizations { @override String get filter => 'مرشح'; + @override + String get ignore_filters => 'تجاهل مرشح'; + @override String get downloaded => 'تم التحميل'; diff --git a/lib/l10n/generated/app_localizations_de.dart b/lib/l10n/generated/app_localizations_de.dart index 773501cc..3e1d37ac 100644 --- a/lib/l10n/generated/app_localizations_de.dart +++ b/lib/l10n/generated/app_localizations_de.dart @@ -32,6 +32,9 @@ class AppLocalizationsDe extends AppLocalizations { @override String get filter => 'Filter'; + @override + String get ignore_filters => 'Filter ignorieren'; + @override String get downloaded => 'Heruntergeladen'; diff --git a/lib/l10n/generated/app_localizations_en.dart b/lib/l10n/generated/app_localizations_en.dart index 042d7207..5dce637c 100644 --- a/lib/l10n/generated/app_localizations_en.dart +++ b/lib/l10n/generated/app_localizations_en.dart @@ -32,6 +32,9 @@ class AppLocalizationsEn extends AppLocalizations { @override String get filter => 'Filter'; + @override + String get ignore_filters => 'Ignore Filters'; + @override String get downloaded => 'Downloaded'; diff --git a/lib/l10n/generated/app_localizations_es.dart b/lib/l10n/generated/app_localizations_es.dart index be255a68..dd113bcb 100644 --- a/lib/l10n/generated/app_localizations_es.dart +++ b/lib/l10n/generated/app_localizations_es.dart @@ -32,6 +32,9 @@ class AppLocalizationsEs extends AppLocalizations { @override String get filter => 'Filtrar'; + @override + String get ignore_filters => 'Ignorar filtros'; + @override String get downloaded => 'Descargado'; @@ -1466,6 +1469,9 @@ class AppLocalizationsEs419 extends AppLocalizationsEs { @override String get filter => 'Filtrar'; + @override + String get ignore_filters => 'Ignorar filtros'; + @override String get downloaded => 'Descargado'; diff --git a/lib/l10n/generated/app_localizations_fr.dart b/lib/l10n/generated/app_localizations_fr.dart index e15554b3..ea61c66c 100644 --- a/lib/l10n/generated/app_localizations_fr.dart +++ b/lib/l10n/generated/app_localizations_fr.dart @@ -32,6 +32,9 @@ class AppLocalizationsFr extends AppLocalizations { @override String get filter => 'Filtre'; + @override + String get ignore_filters => 'Ignorer les filtres'; + @override String get downloaded => 'Téléchargé'; diff --git a/lib/l10n/generated/app_localizations_id.dart b/lib/l10n/generated/app_localizations_id.dart index 306d7af3..d9e03e66 100644 --- a/lib/l10n/generated/app_localizations_id.dart +++ b/lib/l10n/generated/app_localizations_id.dart @@ -32,6 +32,9 @@ class AppLocalizationsId extends AppLocalizations { @override String get filter => 'Filter'; + @override + String get ignore_filters => 'Abaikan filter'; + @override String get downloaded => 'Telah Diunduh'; diff --git a/lib/l10n/generated/app_localizations_it.dart b/lib/l10n/generated/app_localizations_it.dart index 4a922ee4..e828e9cf 100644 --- a/lib/l10n/generated/app_localizations_it.dart +++ b/lib/l10n/generated/app_localizations_it.dart @@ -32,6 +32,9 @@ class AppLocalizationsIt extends AppLocalizations { @override String get filter => 'Filtro'; + @override + String get ignore_filters => 'Ignora filtri'; + @override String get downloaded => 'Scaricato'; diff --git a/lib/l10n/generated/app_localizations_pt.dart b/lib/l10n/generated/app_localizations_pt.dart index 2ef76a7b..686e2f54 100644 --- a/lib/l10n/generated/app_localizations_pt.dart +++ b/lib/l10n/generated/app_localizations_pt.dart @@ -32,6 +32,9 @@ class AppLocalizationsPt extends AppLocalizations { @override String get filter => 'Filtro'; + @override + String get ignore_filters => 'Ignorar filtros'; + @override String get downloaded => 'Baixados'; @@ -1466,6 +1469,9 @@ class AppLocalizationsPtBr extends AppLocalizationsPt { @override String get filter => 'Filtro'; + @override + String get ignore_filters => 'Ignorar filtros'; + @override String get downloaded => 'Baixado'; diff --git a/lib/l10n/generated/app_localizations_ru.dart b/lib/l10n/generated/app_localizations_ru.dart index 27665197..eff605d0 100644 --- a/lib/l10n/generated/app_localizations_ru.dart +++ b/lib/l10n/generated/app_localizations_ru.dart @@ -32,6 +32,9 @@ class AppLocalizationsRu extends AppLocalizations { @override String get filter => 'Фильтр'; + @override + String get ignore_filters => 'Игнорировать фильтры'; + @override String get downloaded => 'Загружено'; diff --git a/lib/l10n/generated/app_localizations_th.dart b/lib/l10n/generated/app_localizations_th.dart index 16bee309..651730f8 100644 --- a/lib/l10n/generated/app_localizations_th.dart +++ b/lib/l10n/generated/app_localizations_th.dart @@ -32,6 +32,9 @@ class AppLocalizationsTh extends AppLocalizations { @override String get filter => 'ตัวกรอง'; + @override + String get ignore_filters => 'ไม่สนใจตัวกรอง'; + @override String get downloaded => 'ดาวน์โหลดแล้ว'; diff --git a/lib/l10n/generated/app_localizations_tr.dart b/lib/l10n/generated/app_localizations_tr.dart index 021a73e0..d7f9bf9d 100644 --- a/lib/l10n/generated/app_localizations_tr.dart +++ b/lib/l10n/generated/app_localizations_tr.dart @@ -32,6 +32,9 @@ class AppLocalizationsTr extends AppLocalizations { @override String get filter => 'Filtre'; + @override + String get ignore_filters => 'Filtreleri yok say'; + @override String get downloaded => 'İndirildi'; diff --git a/lib/l10n/generated/app_localizations_zh.dart b/lib/l10n/generated/app_localizations_zh.dart index 801d70df..fd7b6ce4 100644 --- a/lib/l10n/generated/app_localizations_zh.dart +++ b/lib/l10n/generated/app_localizations_zh.dart @@ -32,6 +32,9 @@ class AppLocalizationsZh extends AppLocalizations { @override String get filter => '筛选'; + @override + String get ignore_filters => '忽略筛选'; + @override String get downloaded => '已下载'; diff --git a/lib/modules/library/library_screen.dart b/lib/modules/library/library_screen.dart index 807f9a8b..c8e36f43 100644 --- a/lib/modules/library/library_screen.dart +++ b/lib/modules/library/library_screen.dart @@ -1013,6 +1013,21 @@ class _LibraryScreenState extends ConsumerState ); } + bool matchesSearchQuery(Manga manga, String query) { + final keywords = query + .toLowerCase() + .split(',') + .map((k) => k.trim()) + .where((k) => k.isNotEmpty); + + return keywords.any( + (keyword) => + (manga.name?.toLowerCase().contains(keyword) ?? false) || + (manga.source?.toLowerCase().contains(keyword) ?? false) || + (manga.genre?.any((g) => g.toLowerCase().contains(keyword)) ?? false), + ); + } + List _filterAndSortManga({ required List data, required int downloadFilterType, @@ -1022,133 +1037,126 @@ class _LibraryScreenState extends ConsumerState required int sortType, }) { List? mangas; - mangas = - data - .where((element) { - List list = []; - if (downloadFilterType == 1) { - for (var chap in element.chapters) { - final modelChapDownload = - isar.downloads.filter().idEqualTo(chap.id).findAllSync(); - - if (modelChapDownload.isNotEmpty && - modelChapDownload.first.isDownload == true) { - list.add(true); - } - } - return list.isNotEmpty; - } else if (downloadFilterType == 2) { - for (var chap in element.chapters) { - final modelChapDownload = - isar.downloads.filter().idEqualTo(chap.id).findAllSync(); - if (!(modelChapDownload.isNotEmpty && - modelChapDownload.first.isDownload == true)) { - list.add(true); - } - } - return list.length == element.chapters.length; - } - return true; - }) - .where((element) { - List list = []; - if (unreadFilterType == 1 || startedFilterType == 1) { - for (var chap in element.chapters) { - if (!chap.isRead!) { - list.add(true); - } - } - return list.isNotEmpty; - } else if (unreadFilterType == 2 || startedFilterType == 2) { + final searchQuery = _textEditingController.text; + // Skip all filters, just do search + if (searchQuery.isNotEmpty && ignoreFiltersOnSearch) { + mangas = + data + .where((element) => matchesSearchQuery(element, searchQuery)) + .toList(); + } else { + // Apply filters + search + mangas = + data + .where((element) { + // Filter by download List list = []; - for (var chap in element.chapters) { - if (chap.isRead!) { - list.add(true); - } - } - return list.length == element.chapters.length; - } - return true; - }) - .where((element) { - List list = []; - if (bookmarkedFilterType == 1) { - for (var chap in element.chapters) { - if (chap.isBookmarked!) { - list.add(true); - } - } - return list.isNotEmpty; - } else if (bookmarkedFilterType == 2) { - List list = []; - for (var chap in element.chapters) { - if (!chap.isBookmarked!) { - list.add(true); - } - } - return list.length == element.chapters.length; - } - return true; - }) - .where( - (element) => - _textEditingController.text.isNotEmpty - ? _textEditingController.text - .split(",") - .any( - (keyword) => - element.name!.toLowerCase().contains( - _textEditingController.text.toLowerCase(), - ) || - (element.source != null && - element.source!.toLowerCase().contains( - _textEditingController.text.toLowerCase(), - )) || - element.genre!.contains(keyword), - ) - : true, - ) - .toList(); + if (downloadFilterType == 1) { + for (var chap in element.chapters) { + final modelChapDownload = + isar.downloads + .filter() + .idEqualTo(chap.id) + .findAllSync(); - if (sortType == 0) { - mangas.sort((a, b) { - return a.name!.compareTo(b.name!); - }); - } else if (sortType == 1) { - mangas.sort((a, b) { - return a.lastRead!.compareTo(b.lastRead!); - }); - } else if (sortType == 2) { - mangas.sort((a, b) { - return a.lastUpdate?.compareTo(b.lastUpdate ?? 0) ?? 0; - }); - } else if (sortType == 3) { - mangas.sort((a, b) { - return a.chapters - .where((element) => !element.isRead!) - .toList() - .length - .compareTo( - b.chapters.where((element) => !element.isRead!).toList().length, - ); - }); - } else if (sortType == 4) { - mangas.sort((a, b) { - return a.chapters.length.compareTo(b.chapters.length); - }); - } else if (sortType == 5) { - mangas.sort((a, b) { - final aChaps = a.chapters; - final bChaps = b.chapters; - return (aChaps.lastOrNull?.dateUpload ?? "").compareTo( - bChaps.lastOrNull?.dateUpload ?? "", - ); - }); - } else if (sortType == 6) { - mangas.sort((a, b) { - return a.dateAdded?.compareTo(b.dateAdded ?? 0) ?? 0; - }); + if (modelChapDownload.isNotEmpty && + modelChapDownload.first.isDownload == true) { + list.add(true); + } + } + return list.isNotEmpty; + } else if (downloadFilterType == 2) { + for (var chap in element.chapters) { + final modelChapDownload = + isar.downloads + .filter() + .idEqualTo(chap.id) + .findAllSync(); + if (!(modelChapDownload.isNotEmpty && + modelChapDownload.first.isDownload == true)) { + list.add(true); + } + } + return list.length == element.chapters.length; + } + return true; + }) + .where((element) { + // Filter by unread or started + List list = []; + if (unreadFilterType == 1 || startedFilterType == 1) { + for (var chap in element.chapters) { + if (!chap.isRead!) { + list.add(true); + } + } + return list.isNotEmpty; + } else if (unreadFilterType == 2 || startedFilterType == 2) { + List list = []; + for (var chap in element.chapters) { + if (chap.isRead!) { + list.add(true); + } + } + return list.length == element.chapters.length; + } + return true; + }) + .where((element) { + // Filter by bookmarked + List list = []; + if (bookmarkedFilterType == 1) { + for (var chap in element.chapters) { + if (chap.isBookmarked!) { + list.add(true); + } + } + return list.isNotEmpty; + } else if (bookmarkedFilterType == 2) { + List list = []; + for (var chap in element.chapters) { + if (!chap.isBookmarked!) { + list.add(true); + } + } + return list.length == element.chapters.length; + } + return true; + }) + .where( + (element) => + searchQuery.isNotEmpty + ? matchesSearchQuery(element, searchQuery) + : true, + ) + .toList(); } + // Sorting the data based on selected sort type + mangas.sort((a, b) { + switch (sortType) { + case 0: + return a.name!.compareTo(b.name!); + case 1: + return a.lastRead!.compareTo(b.lastRead!); + case 2: + return a.lastUpdate?.compareTo(b.lastUpdate ?? 0) ?? 0; + case 3: + return a.chapters + .where((e) => !e.isRead!) + .length + .compareTo(b.chapters.where((e) => !e.isRead!).length); + case 4: + return a.chapters.length.compareTo(b.chapters.length); + case 5: + return (a.chapters.lastOrNull?.dateUpload ?? "").compareTo( + b.chapters.lastOrNull?.dateUpload ?? "", + ); + case 6: + return a.dateAdded?.compareTo(b.dateAdded ?? 0) ?? 0; + default: + return 0; + } + }); return mangas; } @@ -1188,7 +1196,9 @@ class _LibraryScreenState extends ConsumerState ); final entries = - data.where((e) => !(e.hide ?? false)).toList(); + data + .where((e) => !(e.hide ?? false)) + .toList(); if (entries.isEmpty) { return Text(l10n.library_no_category_exist); } @@ -2043,6 +2053,7 @@ class _LibraryScreenState extends ConsumerState return l10n.date_added; } + bool ignoreFiltersOnSearch = false; PreferredSize _appBar( bool isNotFiltering, bool showNumbersOfItems, @@ -2202,6 +2213,21 @@ class _LibraryScreenState extends ConsumerState }, icon: const Icon(Icons.search), ), + if (_isSearch) + Row( + mainAxisSize: MainAxisSize.min, + children: [ + Text(l10n.ignore_filters), + Checkbox( + value: ignoreFiltersOnSearch, + onChanged: (val) { + setState(() { + ignoreFiltersOnSearch = val ?? false; + }); + }, + ), + ], + ), IconButton( splashRadius: 20, onPressed: () {