From dfd19c0ab02893ce984f8518967bbba241c9e938 Mon Sep 17 00:00:00 2001 From: Sivan Ratson <89018301+Sivan22@users.noreply.github.com> Date: Sun, 1 Sep 2024 22:35:56 +0300 Subject: [PATCH] feat: Tantivy_search_engine (#222) * create refs database * splitted data layer * split data layer * fix find ref screen * comment helper * added mimir integration * moved ref find to isolate * added refs indexing screen * fixed keyboard shortcuts * added book filtering for full text search and isar Line model * fixed filter_list package * filter books fotr seearch by category * legacy FT search option * ability to stop indexing * save indexed books * adjustments to searchEngine package * using searcStream * fixy * hiding create index button while indexing * fixed * tested and working * switched to stream * added listener * few improvements * fixed a bug * sort entities in book tree and reorgenised some code files. * Merge branch 'main' into tantivy_search_engine --- lib/data/data.dart | 50 - .../{ => data_providers}/cache_provider.dart | 0 .../file_system_data_provider.dart | 20 +- .../hive_data_provider.dart | 0 .../data_providers/isar_data_provider.dart | 210 +++ .../data_providers/tantivy_data_provider.dart | 145 ++ lib/data/repository/data_repository.dart | 52 + lib/main.dart | 30 +- lib/models/app_model.dart | 21 +- lib/models/books.dart | 7 +- lib/models/isar_collections/line.dart | 19 + lib/models/isar_collections/line.g.dart | 1200 +++++++++++++++ lib/models/isar_collections/ref.dart | 21 + lib/models/isar_collections/ref.g.dart | 1296 +++++++++++++++++ lib/models/library.dart | 2 +- lib/models/links.dart | 8 +- lib/models/tabs.dart | 12 +- .../{ => favorites}/bookmark_screen.dart | 0 lib/screens/{ => favorites}/favoriets.dart | 6 +- .../{ => favorites}/history_screen.dart | 0 .../{ => favorites}/workspaces_screen.dart | 0 lib/screens/find_book_screen.dart | 122 -- lib/screens/find_ref_screen.dart | 121 ++ .../book_tree_checklist.dart | 0 .../full_text_search/full_text_book_list.dart | 164 +++ .../full_text_search/full_text_book_tree.dart | 115 ++ .../full_text_search/full_text_left_pane.dart | 74 + .../full_text_search_screen.dart | 28 + .../full_text_settings_screen.dart | 150 ++ .../legacy_full_text_search_screen.dart} | 6 +- .../tantivy_full_text_search.dart | 270 ++++ lib/screens/library_browser.dart | 5 +- lib/screens/main_window_screen.dart | 23 +- .../{ => reading/pdf}/pdf_book_screen.dart | 2 +- .../pdf}/pdf_outlines_screen.dart | 0 .../{ => reading/pdf}/pdf_search_screen.dart | 0 .../pdf}/pdf_thumbnails_screen.dart | 0 lib/screens/{ => reading}/reading_screen.dart | 16 +- .../text}/combined_book_screen.dart | 6 +- .../text}/commentators_list_screen.dart | 3 +- .../{ => reading/text}/links_screen.dart | 0 .../{ => reading/text}/simple_book_view.dart | 4 +- .../text}/splited_view_screen.dart | 4 +- .../{ => reading/text}/text_book_screen.dart | 8 +- .../text}/text_book_search_screen.dart | 57 +- .../text}/toc_navigator_screen.dart | 0 lib/screens/ref_indexing_screen.dart | 99 ++ lib/screens/settings_screen.dart | 23 +- lib/screens/temp.dart | 329 ----- lib/utils/ref_helper.dart | 72 + lib/utils/text_manipulation.dart | 25 +- .../src/filter_list_delegate.dart | 8 +- .../filter_list}/src/filter_list_dialog.dart | 11 +- .../filter_list}/src/filter_list_widget.dart | 0 .../filter_list}/src/state/filter_state.dart | 2 +- .../filter_list}/src/state/provider.dart | 0 .../src/theme/choice_chip_theme.dart | 2 +- .../src/theme/contol_button_theme.dart | 2 +- .../src/theme/control_button_bar_theme.dart | 2 +- .../src/theme/filter_list_delegate_theme.dart | 0 .../src/theme/filter_list_theme.dart | 6 +- .../filter_list}/src/theme/header_theme.dart | 2 +- .../widgets/filter_list}/src/theme/theme.dart | 0 .../src/widget/choice_chip_widget.dart | 4 +- .../filter_list}/src/widget/choice_list.dart | 10 +- .../src/widget/control_button.dart | 2 +- .../src/widget/control_button_bar.dart | 11 +- .../filter_list}/src/widget/header.dart | 5 +- .../src/widget/search_field_widget.dart | 2 +- lib/widgets/keyboard_shortcuts.dart | 38 +- linux/flutter/generated_plugins.cmake | 1 + packages/filter_list-1.0.3/CHANGELOG.md | 139 -- packages/filter_list-1.0.3/LICENSE | 25 - packages/filter_list-1.0.3/README.md | 270 ---- .../filter_list-1.0.3/analysis_options.yaml | 909 ------------ .../filter_list-1.0.3/lib/filter_list.dart | 6 - packages/filter_list-1.0.3/pubspec.lock | 205 --- packages/filter_list-1.0.3/pubspec.yaml | 54 - .../test/filter_list_test.dart | 11 - pubspec.lock | 148 +- pubspec.yaml | 16 +- windows/flutter/generated_plugins.cmake | 1 + 82 files changed, 4434 insertions(+), 2283 deletions(-) delete mode 100644 lib/data/data.dart rename lib/data/{ => data_providers}/cache_provider.dart (100%) rename lib/data/{ => data_providers}/file_system_data_provider.dart (97%) rename lib/data/{ => data_providers}/hive_data_provider.dart (100%) create mode 100644 lib/data/data_providers/isar_data_provider.dart create mode 100644 lib/data/data_providers/tantivy_data_provider.dart create mode 100644 lib/data/repository/data_repository.dart create mode 100644 lib/models/isar_collections/line.dart create mode 100644 lib/models/isar_collections/line.g.dart create mode 100644 lib/models/isar_collections/ref.dart create mode 100644 lib/models/isar_collections/ref.g.dart rename lib/screens/{ => favorites}/bookmark_screen.dart (100%) rename lib/screens/{ => favorites}/favoriets.dart (84%) rename lib/screens/{ => favorites}/history_screen.dart (100%) rename lib/screens/{ => favorites}/workspaces_screen.dart (100%) delete mode 100644 lib/screens/find_book_screen.dart create mode 100644 lib/screens/find_ref_screen.dart rename lib/screens/{ => full_text_search}/book_tree_checklist.dart (100%) create mode 100644 lib/screens/full_text_search/full_text_book_list.dart create mode 100644 lib/screens/full_text_search/full_text_book_tree.dart create mode 100644 lib/screens/full_text_search/full_text_left_pane.dart create mode 100644 lib/screens/full_text_search/full_text_search_screen.dart create mode 100644 lib/screens/full_text_search/full_text_settings_screen.dart rename lib/screens/{full_text_search_screen.dart => full_text_search/legacy_full_text_search_screen.dart} (98%) create mode 100644 lib/screens/full_text_search/tantivy_full_text_search.dart rename lib/screens/{ => reading/pdf}/pdf_book_screen.dart (99%) rename lib/screens/{ => reading/pdf}/pdf_outlines_screen.dart (100%) rename lib/screens/{ => reading/pdf}/pdf_search_screen.dart (100%) rename lib/screens/{ => reading/pdf}/pdf_thumbnails_screen.dart (100%) rename lib/screens/{ => reading}/reading_screen.dart (96%) rename lib/screens/{ => reading/text}/combined_book_screen.dart (94%) rename lib/screens/{ => reading/text}/commentators_list_screen.dart (97%) rename lib/screens/{ => reading/text}/links_screen.dart (100%) rename lib/screens/{ => reading/text}/simple_book_view.dart (94%) rename lib/screens/{ => reading/text}/splited_view_screen.dart (93%) rename lib/screens/{ => reading/text}/text_book_screen.dart (98%) rename lib/screens/{ => reading/text}/text_book_search_screen.dart (68%) rename lib/screens/{ => reading/text}/toc_navigator_screen.dart (100%) create mode 100644 lib/screens/ref_indexing_screen.dart delete mode 100644 lib/screens/temp.dart create mode 100644 lib/utils/ref_helper.dart rename {packages/filter_list-1.0.3/lib => lib/widgets/filter_list}/src/filter_list_delegate.dart (98%) rename {packages/filter_list-1.0.3/lib => lib/widgets/filter_list}/src/filter_list_dialog.dart (96%) rename {packages/filter_list-1.0.3/lib => lib/widgets/filter_list}/src/filter_list_widget.dart (100%) rename {packages/filter_list-1.0.3/lib => lib/widgets/filter_list}/src/state/filter_state.dart (97%) rename {packages/filter_list-1.0.3/lib => lib/widgets/filter_list}/src/state/provider.dart (100%) rename {packages/filter_list-1.0.3/lib => lib/widgets/filter_list}/src/theme/choice_chip_theme.dart (99%) rename {packages/filter_list-1.0.3/lib => lib/widgets/filter_list}/src/theme/contol_button_theme.dart (99%) rename {packages/filter_list-1.0.3/lib => lib/widgets/filter_list}/src/theme/control_button_bar_theme.dart (99%) rename {packages/filter_list-1.0.3/lib => lib/widgets/filter_list}/src/theme/filter_list_delegate_theme.dart (100%) rename {packages/filter_list-1.0.3/lib => lib/widgets/filter_list}/src/theme/filter_list_theme.dart (97%) rename {packages/filter_list-1.0.3/lib => lib/widgets/filter_list}/src/theme/header_theme.dart (99%) rename {packages/filter_list-1.0.3/lib => lib/widgets/filter_list}/src/theme/theme.dart (100%) rename {packages/filter_list-1.0.3/lib => lib/widgets/filter_list}/src/widget/choice_chip_widget.dart (94%) rename {packages/filter_list-1.0.3/lib => lib/widgets/filter_list}/src/widget/choice_list.dart (92%) rename {packages/filter_list-1.0.3/lib => lib/widgets/filter_list}/src/widget/control_button.dart (96%) rename {packages/filter_list-1.0.3/lib => lib/widgets/filter_list}/src/widget/control_button_bar.dart (91%) rename {packages/filter_list-1.0.3/lib => lib/widgets/filter_list}/src/widget/header.dart (96%) rename {packages/filter_list-1.0.3/lib => lib/widgets/filter_list}/src/widget/search_field_widget.dart (94%) delete mode 100644 packages/filter_list-1.0.3/CHANGELOG.md delete mode 100644 packages/filter_list-1.0.3/LICENSE delete mode 100644 packages/filter_list-1.0.3/README.md delete mode 100644 packages/filter_list-1.0.3/analysis_options.yaml delete mode 100644 packages/filter_list-1.0.3/lib/filter_list.dart delete mode 100644 packages/filter_list-1.0.3/pubspec.lock delete mode 100644 packages/filter_list-1.0.3/pubspec.yaml delete mode 100644 packages/filter_list-1.0.3/test/filter_list_test.dart diff --git a/lib/data/data.dart b/lib/data/data.dart deleted file mode 100644 index 91bfe2772..000000000 --- a/lib/data/data.dart +++ /dev/null @@ -1,50 +0,0 @@ -/* this is an abstract class of the data layer, - providing all the data access methods needed for the app model. */ - -import 'package:otzaria/models/library.dart'; -import 'package:otzaria/models/books.dart'; -import 'package:otzaria/models/links.dart'; - -/// Abstract class of the data layer. -/// -/// Provides all the data access methods needed for the app model. -/// -/// The `Data` class represents an abstract layer for handling the app's data. -/// It declares the methods for accessing the library, book text, book table of contents, -/// and links for a book. -/// -/// The `metadata` field is a map, where the keys are book titles and the values are maps, -/// where the keys are metadata fields and the values are their corresponding values. -/// -/// The `getLibrary` method returns a [Library] object, which represents the library. -/// The `getBookText` method returns a [Future] that resolves to a [String], -/// which contains the text of the book with the given title. -/// The `getBookToc` method returns a [Future] that resolves to a [List] of [TocEntry] objects, -/// which represent the table of contents of the book with the given title. -/// The `getAllLinksForBook` method returns a [Future] that resolves to a [List] of [Link] objects, -/// which represent the links for the book with the given title. -/// The `getLinkContent` method returns a [Future] that resolves to a [String], -/// which contains the content of the link. -abstract class Data { - Map> metadata = {}; - - /// Returns the library. - Future getLibrary(); - - ///returns the list of otzar books - Future> getOtzarBooks(); - - Future> getHebrewBooks(); - - /// Returns the text of the book with the given title. - Future getBookText(String title); - - /// Returns the table of contents of the book with the given title. - Future> getBookToc(String title); - - /// Returns the links for the book with the given title. - Future> getAllLinksForBook(String title); - - /// Returns the content of the link. - Future getLinkContent(Link link); -} diff --git a/lib/data/cache_provider.dart b/lib/data/data_providers/cache_provider.dart similarity index 100% rename from lib/data/cache_provider.dart rename to lib/data/data_providers/cache_provider.dart diff --git a/lib/data/file_system_data_provider.dart b/lib/data/data_providers/file_system_data_provider.dart similarity index 97% rename from lib/data/file_system_data_provider.dart rename to lib/data/data_providers/file_system_data_provider.dart index 00850433e..73ba1696e 100644 --- a/lib/data/file_system_data_provider.dart +++ b/lib/data/data_providers/file_system_data_provider.dart @@ -7,12 +7,11 @@ import 'dart:isolate'; import 'dart:convert'; import 'package:csv/csv.dart'; import 'package:flutter/services.dart'; -import 'package:otzaria/data/cache_provider.dart'; +import 'package:otzaria/data/data_providers/cache_provider.dart'; import 'package:otzaria/utils/docx_to_otzaria.dart'; import 'package:flutter_settings_screens/flutter_settings_screens.dart'; import 'package:otzaria/utils/text_manipulation.dart'; import 'package:otzaria/models/books.dart'; -import 'package:otzaria/data/data.dart'; import 'package:otzaria/models/library.dart'; import 'package:otzaria/models/links.dart'; @@ -24,9 +23,10 @@ import 'package:otzaria/models/links.dart'; /// The inner representation of the library is a tree of directories and files, /// which every book is stored in a file, and every directory is represents a category. /// The metadata is stored in a JSON file. -class FileSystemData extends Data { +class FileSystemData { late String libraryPath; Map titleToPath = {}; + Map metadata = {}; FileSystemData() { _initialize(); @@ -42,8 +42,6 @@ class FileSystemData extends Data { _updateTitleToPath(); } - @override - /// Returns the library Future getLibrary() async { return _getLibraryFromDirectory( @@ -101,6 +99,8 @@ class FileSystemData extends Data { } } } + category.subCategories.sort((a, b) => a.order.compareTo(b.order)); + category.books.sort((a, b) => a.order.compareTo(b.order)); return category; } @@ -114,15 +114,14 @@ class FileSystemData extends Data { Directory(entity.path), library)); } } + library.subCategories.sort((a, b) => a.order.compareTo(b.order)); return library; } - @override Future> getOtzarBooks() { return _getOtzarBooks(); } - @override Future> getHebrewBooks() { return _getHebrewBooks(); } @@ -214,7 +213,6 @@ class FileSystemData extends Data { ///the implementation of the links from app's model, based on the filesystem. ///the links are in the folder 'links' with the name '_links.json' - @override Future> getAllLinksForBook(String title) async { try { File file = File(_getLinksPath(title)); @@ -227,8 +225,6 @@ class FileSystemData extends Data { } } - @override - /// Retrieves the text for a book with the given title asynchronously (using Isolate). /// supports docx files Future getBookText(String title) { @@ -244,8 +240,6 @@ class FileSystemData extends Data { }); } - @override - /// an file system approach to get the content of a link. /// we read the file line by line and return the content of the line with the given index. Future getLinkContent(Link link) async { @@ -266,7 +260,7 @@ class FileSystemData extends Data { /// Returns the title of the book with the given path. // Retrieves the table of contents for a book with the given title. - @override + Future> getBookToc(String title) async { return _parseToc(getBookText(title)); } diff --git a/lib/data/hive_data_provider.dart b/lib/data/data_providers/hive_data_provider.dart similarity index 100% rename from lib/data/hive_data_provider.dart rename to lib/data/data_providers/hive_data_provider.dart diff --git a/lib/data/data_providers/isar_data_provider.dart b/lib/data/data_providers/isar_data_provider.dart new file mode 100644 index 000000000..94e3e0296 --- /dev/null +++ b/lib/data/data_providers/isar_data_provider.dart @@ -0,0 +1,210 @@ +import 'dart:isolate'; + +import 'package:flutter/foundation.dart'; +import 'package:flutter_settings_screens/flutter_settings_screens.dart'; +import 'package:isar/isar.dart'; +import 'package:otzaria/models/books.dart'; +import 'package:otzaria/models/isar_collections/line.dart'; +import 'package:otzaria/models/isar_collections/ref.dart'; +import 'package:fuzzywuzzy/fuzzywuzzy.dart'; +import 'package:otzaria/models/library.dart'; +import 'package:pdfrx/pdfrx.dart'; + +class IsarDataProvider { + static final IsarDataProvider _singleton = IsarDataProvider(); + static IsarDataProvider get instance => _singleton; + + IsarDataProvider(); + + final isar = Isar.open( + directory: Settings.getValue('key-library-path') ?? 'C:\\אוצריא', + maxSizeMiB: 100000, + schemas: [ + RefSchema, + LineSchema, + ], + ); + ValueNotifier refsNumOfbooksDone = ValueNotifier(null); + ValueNotifier refsNumOfbooksTotal = ValueNotifier(null); + ValueNotifier linesNumOfbooksDone = ValueNotifier(null); + ValueNotifier linesNumOfbooksTotal = ValueNotifier(null); + + Future createRefsFromLibrary(Library library, int startIndex) async { + isar.write((isar) => isar.refs.clear()); + int i = 0; + final allBooks = + library.getAllBooks().whereType().skip(startIndex); + refsNumOfbooksTotal.value = allBooks.length; + for (TextBook book in allBooks) { + try { + print('Creating refs for ${book.title} (${i++}/${allBooks.length})'); + refsNumOfbooksDone.value = i - 1; + List refs = []; + final List toc = await book.tableOfContents; + //get all TocEntries recursively + List alltocs = []; + + void searchToc(List entries) { + for (final TocEntry entry in entries) { + alltocs.add(entry); + for (final child in entry.children) { + child.text = '${entry.text},${child.text}'; + } + searchToc(entry.children); + } + } + + searchToc(toc); + for (final TocEntry entry in alltocs) { + final ref = Ref( + id: isar.refs.autoIncrement(), + ref: entry.text + .replaceAll('"', '') + .replaceAll("'", '') + .replaceAll('״', ''), + bookTitle: book.title, + index: entry.index, + pdfBook: false); + refs.add(ref); + } + isar.write((isar) => isar.refs.putAll(refs)); + print('Done creating refs for ${book.title} '); + } catch (e) { + print(' Failed creating refs for ${book.title} $e'); + } + } + final pdfBooks = + library.getAllBooks().whereType().skip(startIndex).toList(); + refsNumOfbooksTotal.value = pdfBooks.length; + for (int i = 0; i < pdfBooks.length; i++) { + refsNumOfbooksDone.value = i; + final List outlines = + await PdfDocument.openFile(pdfBooks[i].path) + .then((value) => value.loadOutline()); + + //get all TocEntries recursively + List alloutlines = []; + + void searchOutline(List entries) { + for (final PdfOutlineNode entry in entries) { + alloutlines.add(entry); + searchOutline(entry.children); + } + } + + searchOutline(outlines); + + for (final PdfOutlineNode entry in alloutlines) { + final ref = Ref( + id: isar.refs.autoIncrement(), + ref: "${pdfBooks[i].title} ${entry.title}", + bookTitle: pdfBooks[i].title, + index: entry.dest?.pageNumber ?? 0, + pdfBook: true, + pdfPath: pdfBooks[i].path, + ); + print('Adding Pdf ref: ${ref.ref}'); + isar.write((isar) => isar.refs.put(ref)); + } + } + refsNumOfbooksDone.value = null; + refsNumOfbooksTotal.value = null; + } + + List getRefsForBook(TextBook book) { + return isar.refs.where().bookTitleEqualTo(book.title).findAll(); + } + + List getAllRefs() { + return isar.refs.where().findAll(); + } + + Future> findRefs(String ref) { + final parts = ref.split(' '); + return isar.refs + .where() + .allOf( + parts, + (q, element) => q.refContains(element), + ) + .findAllAsync(); + } + + Future> findRefsByRelevance(String ref, {int limit = 10}) async { + var refs = await findRefs(ref); + // reduce the number of refs by taking the top N of each book + refs = await Isolate.run(() { + List takenRefs = []; + final gruops = refs.groupBy((ref) => ref.bookTitle); + for (final gruop in gruops.keys) { + takenRefs += (gruops[gruop]!.take(limit)).toList(); + } + takenRefs.sort((a, b) { + final scoreA = ratio(ref, a.ref); + final scoreB = ratio(ref, b.ref); + return scoreB.compareTo(scoreA); + }); + return takenRefs; + }); + + // sort by ratio + + return refs; + } + + Future getNumberOfBooksWithRefs() async { + final allRefs = isar.refs.where().findAll(); + final books = allRefs.groupBy((ref) => ref.bookTitle); + return books.length; + } + + Future addAllLines(Library library) async { + final books = library.getAllBooks().whereType().toList(); + linesNumOfbooksTotal.value = books.length; + linesNumOfbooksDone.value = 0; + + for (TextBook book in books) { + print('Adding lines for ${book.title}'); + await addLinesForBook(book); + linesNumOfbooksDone.value = books.indexOf(book) + 1; + } + } + + Future addLinesForBook(TextBook book) async { + final texts = (await book.text).split('\n'); + final List lines = []; + + for (int i = 0; i < texts.length; i++) { + final line = Line( + id: isar.lines.autoIncrement(), + text: texts[i], + bookTitle: book.title, + topics: book.topics, + index: i, + ); + + lines.add(line); + } + + isar.write((isar) => isar.lines.putAll(lines)); + } + + Future> getLinesForBook(TextBook book) async { + return isar.lines.where().bookTitleEqualTo(book.title).findAll(); + } + + Future> getAllLines() async { + return isar.lines.where().findAll(); + } + + Future> findLines(String text) async { + return isar.lines.where().textContains(text).findAllAsync(); + } +} + +extension Iterables on Iterable { + Map> groupBy(K Function(E) keyFunction) => fold( + >{}, + (Map> map, E element) => + map..putIfAbsent(keyFunction(element), () => []).add(element)); +} diff --git a/lib/data/data_providers/tantivy_data_provider.dart b/lib/data/data_providers/tantivy_data_provider.dart new file mode 100644 index 000000000..f225c6c54 --- /dev/null +++ b/lib/data/data_providers/tantivy_data_provider.dart @@ -0,0 +1,145 @@ +import 'dart:convert'; +import 'dart:io'; +import 'dart:math'; +import 'package:crypto/crypto.dart'; +import 'package:flutter/foundation.dart'; +import 'package:otzaria/utils/text_manipulation.dart'; +import 'package:search_engine/search_engine.dart'; +import 'package:flutter_settings_screens/flutter_settings_screens.dart'; +import 'package:otzaria/models/books.dart'; +import 'package:otzaria/models/library.dart'; +import 'package:pdfrx/pdfrx.dart'; + +class TantivyDataProvider { + static final TantivyDataProvider _singleton = TantivyDataProvider(); + static TantivyDataProvider instance = _singleton; + + ValueNotifier numOfbooksDone = ValueNotifier(null); + ValueNotifier numOfbooksTotal = ValueNotifier(null); + ValueNotifier isIndexing = ValueNotifier(false); + late List booksDone; + + TantivyDataProvider() { + booksDone = Settings.getValue( + 'key-books-done', + ) ?? + []; + } + + saveBooksDoneToDisk() { + Settings.setValue('key-books-done', booksDone); + } + + final engine = SearchEngine.newInstance( + path: (Settings.getValue('key-library-path') ?? 'C:/אוצריא') + + Platform.pathSeparator + + 'index'); + + Future> searchTexts( + String query, List books, int limit) async { + final index = await engine; + return await index.search(query: query, books: books, limit: limit); + } + + Stream> searchTextsStream( + String query, List books, int limit) async* { + final index = await engine; + yield* index.searchStream(query: query, books: books, limit: limit); + } + + addAllTBooksToTantivy(Library library, + {int start = 0, int end = 100000}) async { + isIndexing.value = true; + var allBooks = library.getAllBooks(); + allBooks = allBooks.getRange(start, min(end, allBooks.length)).toList(); + + numOfbooksTotal.value = allBooks.length; + numOfbooksDone.value = 0; + + for (Book book in allBooks) { + if (!isIndexing.value) { + return; + } + print('Adding ${book.title} to index'); + try { + if (book is TextBook) { + await addTextsToTantivy(book); + } else if (book is PdfBook) { + await addPdfTextsToMimir(book); + } + } catch (e) { + print('Error adding ${book.title} to index: $e'); + } + } + numOfbooksDone.value = null; + numOfbooksTotal.value = null; + isIndexing.value = false; + } + + addTextsToTantivy(TextBook book) async { + final index = await engine; + var text = await book.text; + final title = book.title; + + final hash = sha1.convert(utf8.encode(text)).toString(); + if (booksDone.contains(hash)) { + print('${book.title} already in index'); + numOfbooksDone.value = numOfbooksDone.value! + 1; + return; + } + + text = stripHtmlIfNeeded(text); + text = removeVolwels(text); + final texts = text.split('\n'); + for (int i = 0; i < texts.length; i++) { + if (!isIndexing.value) { + return; + } + index.addDocument( + id: BigInt.from(hashCode + i), + title: title, + text: texts[i], + segment: BigInt.from(i), + isPdf: false, + filePath: ''); + } + await index.commit(); + booksDone.add(hash); + saveBooksDoneToDisk(); + print('Added ${book.title} to index'); + numOfbooksDone.value = numOfbooksDone.value! + 1; + } + + addPdfTextsToMimir(PdfBook book) async { + final index = await engine; + final data = await File(book.path).readAsBytes(); + final hash = sha1.convert(data).toString(); + if (booksDone.contains(hash)) { + print('${book.title} already in index'); + numOfbooksDone.value = numOfbooksDone.value! + 1; + return; + } + final pages = await PdfDocument.openData(data).then((value) => value.pages); + final title = book.title; + for (int i = 0; i < pages.length; i++) { + final texts = (await pages[i].loadText()).fullText.split('\n'); + for (int j = 0; j < texts.length; j++) { + if (!isIndexing.value) { + return; + } + index.addDocument( + id: BigInt.from(hashCode + i + j), + title: title, + text: texts[j], + segment: BigInt.from(i), + isPdf: true, + filePath: book.path); + } + } + await index.commit(); + booksDone.add(hash); + saveBooksDoneToDisk(); + print('Added ${book.title} to index'); + numOfbooksDone.value = numOfbooksDone.value! + 1; + } +} diff --git a/lib/data/repository/data_repository.dart b/lib/data/repository/data_repository.dart new file mode 100644 index 000000000..76449ce67 --- /dev/null +++ b/lib/data/repository/data_repository.dart @@ -0,0 +1,52 @@ +import 'package:otzaria/data/data_providers/file_system_data_provider.dart'; +import 'package:otzaria/data/data_providers/isar_data_provider.dart'; +import 'package:otzaria/data/data_providers/tantivy_data_provider.dart'; +import 'package:otzaria/models/books.dart'; +import 'package:otzaria/models/isar_collections/ref.dart'; +import 'package:otzaria/models/library.dart'; + +class DataRepository { + final FileSystemData _fileSystemData = FileSystemData.instance; + final IsarDataProvider _isarDataProvider = IsarDataProvider.instance; + final TantivyDataProvider _mimirDataProvider = TantivyDataProvider.instance; + + static final DataRepository _singleton = DataRepository(); + static DataRepository get instance => _singleton; + + Future getLibrary() async { + return _fileSystemData.getLibrary(); + } + + ///returns the list of otzar books + Future> getOtzarBooks() { + return _fileSystemData.getOtzarBooks(); + } + + Future> getHebrewBooks() { + return _fileSystemData.getHebrewBooks(); + } + + Future getBookText(String title) async { + return _fileSystemData.getBookText(title); + } + + Future> getBookToc(String title) async { + return _fileSystemData.getBookToc(title); + } + + Future createRefsFromLibrary(Library library, int startIndex) async { + _isarDataProvider.createRefsFromLibrary(library, startIndex); + } + + List getRefsForBook(TextBook book) { + return _isarDataProvider.getRefsForBook(book); + } + + Future> findRefsByRelevance(String ref, {int limit = 10}) { + return _isarDataProvider.findRefsByRelevance(ref, limit: limit); + } + + addAllTextsToMimir(Library library, {int start = 0, int end = 100000}) async { + _mimirDataProvider.addAllTBooksToTantivy(library, start: start, end: end); + } +} diff --git a/lib/main.dart b/lib/main.dart index 6b5201172..27b297e5e 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -2,10 +2,11 @@ import 'package:flutter/material.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:otzaria/models/app_model.dart'; import 'package:provider/provider.dart'; +import 'package:search_engine/search_engine.dart'; import 'screens/main_window_screen.dart'; import 'package:flutter_settings_screens/flutter_settings_screens.dart'; -import 'package:otzaria/data/cache_provider.dart'; -import 'package:otzaria/data/hive_data_provider.dart'; +import 'package:otzaria/data/data_providers/cache_provider.dart'; +import 'package:otzaria/data/data_providers/hive_data_provider.dart'; import 'package:file_picker/file_picker.dart'; import 'package:permission_handler/permission_handler.dart'; import 'dart:io'; @@ -22,7 +23,19 @@ import 'dart:io'; /// void main() async { + void createDirectoryIfNotExists(String path) { + Directory directory = Directory(path); + if (!directory.existsSync()) { + directory.createSync(recursive: true); + print('Directory created: $path'); + } else { + print('Directory already exists: $path'); + } + } + + await RustLib.init(); await Settings.init(cacheProvider: HiveCache()); + await initHiveBoxes(); WidgetsFlutterBinding.ensureInitialized(); // requesting external storage permission on android @@ -49,6 +62,9 @@ void main() async { Settings.setValue('key-library-path', libraryPath); } }(); + createDirectoryIfNotExists( + '${Settings.getValue('key-library-path')}${Platform.pathSeparator}index'); + runApp(const OtzariaApp()); } @@ -93,3 +109,13 @@ class OtzariaApp extends StatelessWidget { ); } } + +void createDirectoryIfNotExists(String path) { + Directory directory = Directory(path); + if (!directory.existsSync()) { + directory.createSync(recursive: true); + print('Directory created: $path'); + } else { + print('Directory already exists: $path'); + } +} diff --git a/lib/models/app_model.dart b/lib/models/app_model.dart index 301c885b1..e90ca2fcc 100644 --- a/lib/models/app_model.dart +++ b/lib/models/app_model.dart @@ -8,8 +8,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_settings_screens/flutter_settings_screens.dart'; import 'package:fuzzywuzzy/fuzzywuzzy.dart'; import 'package:hive/hive.dart'; -import 'package:otzaria/data/data.dart'; -import 'package:otzaria/data/file_system_data_provider.dart'; +import 'package:otzaria/data/repository/data_repository.dart'; import 'package:otzaria/models/bookmark.dart'; import 'package:otzaria/models/books.dart'; import 'package:otzaria/models/library.dart'; @@ -25,7 +24,7 @@ import 'package:otzaria/utils/text_manipulation.dart' as utils; /// the seed color. class AppModel with ChangeNotifier { /// The data provider for the application. - Data data = FileSystemData.instance; + DataRepository data = DataRepository.instance; /// The library of books. late Future library; @@ -84,8 +83,14 @@ class AppModel with ChangeNotifier { Settings.getValue('key-show-external-books') ?? false, ); + /// if you should show hebrewbooks books + final ValueNotifier useFastSearch = ValueNotifier( + Settings.getValue('key-use-fast-search') ?? true, + ); + /// a focus node for the search field in libraryBrowser FocusNode bookLocatorFocusNode = FocusNode(); + FocusNode findReferenceFocusNode = FocusNode(); /// Constructs a new AppModel instance. /// @@ -442,7 +447,15 @@ class AppModel with ChangeNotifier { return filteredBooks; }); } + + Future createRefsFromLibrary(int startIndex) async { + data.createRefsFromLibrary(await library, startIndex); + } + + addAllTextsToMimir({int start = 0, int end = 100000}) async { + data.addAllTextsToMimir(await library, start: start, end: end); + } } /// An enum that represents the different screens in the application. -enum Screens { library, reading, search, favorites, settings } +enum Screens { library, find, reading, search, favorites, settings } diff --git a/lib/models/books.dart b/lib/models/books.dart index b97d55cf1..32164e568 100644 --- a/lib/models/books.dart +++ b/lib/models/books.dart @@ -1,5 +1,4 @@ -import 'package:otzaria/data/data.dart'; -import 'package:otzaria/data/file_system_data_provider.dart'; +import 'package:otzaria/data/data_providers/file_system_data_provider.dart'; import 'package:otzaria/models/links.dart'; import 'dart:isolate'; //import 'package:pdfrx/pdfrx.dart'; @@ -14,7 +13,7 @@ abstract class Book { final String title; /// an access to the data layer - final Data data = FileSystemData.instance; + final FileSystemData data = FileSystemData.instance; /// The author of the book, if available. String? author; @@ -115,7 +114,7 @@ class TextBook extends Book { ///represents an entry in table of content , which is a node in a hirarchial tree of topics. ///every entry has its 'level' in the tree, and an index of the line in the book that it is refers to class TocEntry { - final String text; + String text; final int index; final int level; List children = []; diff --git a/lib/models/isar_collections/line.dart b/lib/models/isar_collections/line.dart new file mode 100644 index 000000000..121629609 --- /dev/null +++ b/lib/models/isar_collections/line.dart @@ -0,0 +1,19 @@ +import 'package:isar/isar.dart'; + +part 'line.g.dart'; + +@Collection() +class Line { + final int id; + final String text; + final String bookTitle; + final String topics; + final int index; + + Line( + {required this.id, + required this.text, + required this.bookTitle, + required this.topics, + required this.index}); +} diff --git a/lib/models/isar_collections/line.g.dart b/lib/models/isar_collections/line.g.dart new file mode 100644 index 000000000..051f1c1f2 --- /dev/null +++ b/lib/models/isar_collections/line.g.dart @@ -0,0 +1,1200 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'line.dart'; + +// ************************************************************************** +// _IsarCollectionGenerator +// ************************************************************************** + +// coverage:ignore-file +// ignore_for_file: duplicate_ignore, invalid_use_of_protected_member, lines_longer_than_80_chars, constant_identifier_names, avoid_js_rounded_ints, no_leading_underscores_for_local_identifiers, require_trailing_commas, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_in_if_null_operators, library_private_types_in_public_api, prefer_const_constructors +// ignore_for_file: type=lint + +extension GetLineCollection on Isar { + IsarCollection get lines => this.collection(); +} + +const LineSchema = IsarGeneratedSchema( + schema: IsarSchema( + name: 'Line', + idName: 'id', + embedded: false, + properties: [ + IsarPropertySchema( + name: 'text', + type: IsarType.string, + ), + IsarPropertySchema( + name: 'bookTitle', + type: IsarType.string, + ), + IsarPropertySchema( + name: 'topics', + type: IsarType.string, + ), + IsarPropertySchema( + name: 'index', + type: IsarType.long, + ), + ], + indexes: [], + ), + converter: IsarObjectConverter( + serialize: serializeLine, + deserialize: deserializeLine, + deserializeProperty: deserializeLineProp, + ), + embeddedSchemas: [], +); + +@isarProtected +int serializeLine(IsarWriter writer, Line object) { + IsarCore.writeString(writer, 1, object.text); + IsarCore.writeString(writer, 2, object.bookTitle); + IsarCore.writeString(writer, 3, object.topics); + IsarCore.writeLong(writer, 4, object.index); + return object.id; +} + +@isarProtected +Line deserializeLine(IsarReader reader) { + final int _id; + _id = IsarCore.readId(reader); + final String _text; + _text = IsarCore.readString(reader, 1) ?? ''; + final String _bookTitle; + _bookTitle = IsarCore.readString(reader, 2) ?? ''; + final String _topics; + _topics = IsarCore.readString(reader, 3) ?? ''; + final int _index; + _index = IsarCore.readLong(reader, 4); + final object = Line( + id: _id, + text: _text, + bookTitle: _bookTitle, + topics: _topics, + index: _index, + ); + return object; +} + +@isarProtected +dynamic deserializeLineProp(IsarReader reader, int property) { + switch (property) { + case 0: + return IsarCore.readId(reader); + case 1: + return IsarCore.readString(reader, 1) ?? ''; + case 2: + return IsarCore.readString(reader, 2) ?? ''; + case 3: + return IsarCore.readString(reader, 3) ?? ''; + case 4: + return IsarCore.readLong(reader, 4); + default: + throw ArgumentError('Unknown property: $property'); + } +} + +sealed class _LineUpdate { + bool call({ + required int id, + String? text, + String? bookTitle, + String? topics, + int? index, + }); +} + +class _LineUpdateImpl implements _LineUpdate { + const _LineUpdateImpl(this.collection); + + final IsarCollection collection; + + @override + bool call({ + required int id, + Object? text = ignore, + Object? bookTitle = ignore, + Object? topics = ignore, + Object? index = ignore, + }) { + return collection.updateProperties([ + id + ], { + if (text != ignore) 1: text as String?, + if (bookTitle != ignore) 2: bookTitle as String?, + if (topics != ignore) 3: topics as String?, + if (index != ignore) 4: index as int?, + }) > + 0; + } +} + +sealed class _LineUpdateAll { + int call({ + required List id, + String? text, + String? bookTitle, + String? topics, + int? index, + }); +} + +class _LineUpdateAllImpl implements _LineUpdateAll { + const _LineUpdateAllImpl(this.collection); + + final IsarCollection collection; + + @override + int call({ + required List id, + Object? text = ignore, + Object? bookTitle = ignore, + Object? topics = ignore, + Object? index = ignore, + }) { + return collection.updateProperties(id, { + if (text != ignore) 1: text as String?, + if (bookTitle != ignore) 2: bookTitle as String?, + if (topics != ignore) 3: topics as String?, + if (index != ignore) 4: index as int?, + }); + } +} + +extension LineUpdate on IsarCollection { + _LineUpdate get update => _LineUpdateImpl(this); + + _LineUpdateAll get updateAll => _LineUpdateAllImpl(this); +} + +sealed class _LineQueryUpdate { + int call({ + String? text, + String? bookTitle, + String? topics, + int? index, + }); +} + +class _LineQueryUpdateImpl implements _LineQueryUpdate { + const _LineQueryUpdateImpl(this.query, {this.limit}); + + final IsarQuery query; + final int? limit; + + @override + int call({ + Object? text = ignore, + Object? bookTitle = ignore, + Object? topics = ignore, + Object? index = ignore, + }) { + return query.updateProperties(limit: limit, { + if (text != ignore) 1: text as String?, + if (bookTitle != ignore) 2: bookTitle as String?, + if (topics != ignore) 3: topics as String?, + if (index != ignore) 4: index as int?, + }); + } +} + +extension LineQueryUpdate on IsarQuery { + _LineQueryUpdate get updateFirst => _LineQueryUpdateImpl(this, limit: 1); + + _LineQueryUpdate get updateAll => _LineQueryUpdateImpl(this); +} + +class _LineQueryBuilderUpdateImpl implements _LineQueryUpdate { + const _LineQueryBuilderUpdateImpl(this.query, {this.limit}); + + final QueryBuilder query; + final int? limit; + + @override + int call({ + Object? text = ignore, + Object? bookTitle = ignore, + Object? topics = ignore, + Object? index = ignore, + }) { + final q = query.build(); + try { + return q.updateProperties(limit: limit, { + if (text != ignore) 1: text as String?, + if (bookTitle != ignore) 2: bookTitle as String?, + if (topics != ignore) 3: topics as String?, + if (index != ignore) 4: index as int?, + }); + } finally { + q.close(); + } + } +} + +extension LineQueryBuilderUpdate on QueryBuilder { + _LineQueryUpdate get updateFirst => + _LineQueryBuilderUpdateImpl(this, limit: 1); + + _LineQueryUpdate get updateAll => _LineQueryBuilderUpdateImpl(this); +} + +extension LineQueryFilter on QueryBuilder { + QueryBuilder idEqualTo( + int value, + ) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + EqualCondition( + property: 0, + value: value, + ), + ); + }); + } + + QueryBuilder idGreaterThan( + int value, + ) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + GreaterCondition( + property: 0, + value: value, + ), + ); + }); + } + + QueryBuilder idGreaterThanOrEqualTo( + int value, + ) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + GreaterOrEqualCondition( + property: 0, + value: value, + ), + ); + }); + } + + QueryBuilder idLessThan( + int value, + ) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + LessCondition( + property: 0, + value: value, + ), + ); + }); + } + + QueryBuilder idLessThanOrEqualTo( + int value, + ) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + LessOrEqualCondition( + property: 0, + value: value, + ), + ); + }); + } + + QueryBuilder idBetween( + int lower, + int upper, + ) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + BetweenCondition( + property: 0, + lower: lower, + upper: upper, + ), + ); + }); + } + + QueryBuilder textEqualTo( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + EqualCondition( + property: 1, + value: value, + caseSensitive: caseSensitive, + ), + ); + }); + } + + QueryBuilder textGreaterThan( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + GreaterCondition( + property: 1, + value: value, + caseSensitive: caseSensitive, + ), + ); + }); + } + + QueryBuilder textGreaterThanOrEqualTo( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + GreaterOrEqualCondition( + property: 1, + value: value, + caseSensitive: caseSensitive, + ), + ); + }); + } + + QueryBuilder textLessThan( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + LessCondition( + property: 1, + value: value, + caseSensitive: caseSensitive, + ), + ); + }); + } + + QueryBuilder textLessThanOrEqualTo( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + LessOrEqualCondition( + property: 1, + value: value, + caseSensitive: caseSensitive, + ), + ); + }); + } + + QueryBuilder textBetween( + String lower, + String upper, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + BetweenCondition( + property: 1, + lower: lower, + upper: upper, + caseSensitive: caseSensitive, + ), + ); + }); + } + + QueryBuilder textStartsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + StartsWithCondition( + property: 1, + value: value, + caseSensitive: caseSensitive, + ), + ); + }); + } + + QueryBuilder textEndsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + EndsWithCondition( + property: 1, + value: value, + caseSensitive: caseSensitive, + ), + ); + }); + } + + QueryBuilder textContains(String value, + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + ContainsCondition( + property: 1, + value: value, + caseSensitive: caseSensitive, + ), + ); + }); + } + + QueryBuilder textMatches(String pattern, + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + MatchesCondition( + property: 1, + wildcard: pattern, + caseSensitive: caseSensitive, + ), + ); + }); + } + + QueryBuilder textIsEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + const EqualCondition( + property: 1, + value: '', + ), + ); + }); + } + + QueryBuilder textIsNotEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + const GreaterCondition( + property: 1, + value: '', + ), + ); + }); + } + + QueryBuilder bookTitleEqualTo( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + EqualCondition( + property: 2, + value: value, + caseSensitive: caseSensitive, + ), + ); + }); + } + + QueryBuilder bookTitleGreaterThan( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + GreaterCondition( + property: 2, + value: value, + caseSensitive: caseSensitive, + ), + ); + }); + } + + QueryBuilder bookTitleGreaterThanOrEqualTo( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + GreaterOrEqualCondition( + property: 2, + value: value, + caseSensitive: caseSensitive, + ), + ); + }); + } + + QueryBuilder bookTitleLessThan( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + LessCondition( + property: 2, + value: value, + caseSensitive: caseSensitive, + ), + ); + }); + } + + QueryBuilder bookTitleLessThanOrEqualTo( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + LessOrEqualCondition( + property: 2, + value: value, + caseSensitive: caseSensitive, + ), + ); + }); + } + + QueryBuilder bookTitleBetween( + String lower, + String upper, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + BetweenCondition( + property: 2, + lower: lower, + upper: upper, + caseSensitive: caseSensitive, + ), + ); + }); + } + + QueryBuilder bookTitleStartsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + StartsWithCondition( + property: 2, + value: value, + caseSensitive: caseSensitive, + ), + ); + }); + } + + QueryBuilder bookTitleEndsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + EndsWithCondition( + property: 2, + value: value, + caseSensitive: caseSensitive, + ), + ); + }); + } + + QueryBuilder bookTitleContains( + String value, + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + ContainsCondition( + property: 2, + value: value, + caseSensitive: caseSensitive, + ), + ); + }); + } + + QueryBuilder bookTitleMatches( + String pattern, + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + MatchesCondition( + property: 2, + wildcard: pattern, + caseSensitive: caseSensitive, + ), + ); + }); + } + + QueryBuilder bookTitleIsEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + const EqualCondition( + property: 2, + value: '', + ), + ); + }); + } + + QueryBuilder bookTitleIsNotEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + const GreaterCondition( + property: 2, + value: '', + ), + ); + }); + } + + QueryBuilder topicsEqualTo( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + EqualCondition( + property: 3, + value: value, + caseSensitive: caseSensitive, + ), + ); + }); + } + + QueryBuilder topicsGreaterThan( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + GreaterCondition( + property: 3, + value: value, + caseSensitive: caseSensitive, + ), + ); + }); + } + + QueryBuilder topicsGreaterThanOrEqualTo( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + GreaterOrEqualCondition( + property: 3, + value: value, + caseSensitive: caseSensitive, + ), + ); + }); + } + + QueryBuilder topicsLessThan( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + LessCondition( + property: 3, + value: value, + caseSensitive: caseSensitive, + ), + ); + }); + } + + QueryBuilder topicsLessThanOrEqualTo( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + LessOrEqualCondition( + property: 3, + value: value, + caseSensitive: caseSensitive, + ), + ); + }); + } + + QueryBuilder topicsBetween( + String lower, + String upper, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + BetweenCondition( + property: 3, + lower: lower, + upper: upper, + caseSensitive: caseSensitive, + ), + ); + }); + } + + QueryBuilder topicsStartsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + StartsWithCondition( + property: 3, + value: value, + caseSensitive: caseSensitive, + ), + ); + }); + } + + QueryBuilder topicsEndsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + EndsWithCondition( + property: 3, + value: value, + caseSensitive: caseSensitive, + ), + ); + }); + } + + QueryBuilder topicsContains(String value, + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + ContainsCondition( + property: 3, + value: value, + caseSensitive: caseSensitive, + ), + ); + }); + } + + QueryBuilder topicsMatches(String pattern, + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + MatchesCondition( + property: 3, + wildcard: pattern, + caseSensitive: caseSensitive, + ), + ); + }); + } + + QueryBuilder topicsIsEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + const EqualCondition( + property: 3, + value: '', + ), + ); + }); + } + + QueryBuilder topicsIsNotEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + const GreaterCondition( + property: 3, + value: '', + ), + ); + }); + } + + QueryBuilder indexEqualTo( + int value, + ) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + EqualCondition( + property: 4, + value: value, + ), + ); + }); + } + + QueryBuilder indexGreaterThan( + int value, + ) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + GreaterCondition( + property: 4, + value: value, + ), + ); + }); + } + + QueryBuilder indexGreaterThanOrEqualTo( + int value, + ) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + GreaterOrEqualCondition( + property: 4, + value: value, + ), + ); + }); + } + + QueryBuilder indexLessThan( + int value, + ) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + LessCondition( + property: 4, + value: value, + ), + ); + }); + } + + QueryBuilder indexLessThanOrEqualTo( + int value, + ) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + LessOrEqualCondition( + property: 4, + value: value, + ), + ); + }); + } + + QueryBuilder indexBetween( + int lower, + int upper, + ) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + BetweenCondition( + property: 4, + lower: lower, + upper: upper, + ), + ); + }); + } +} + +extension LineQueryObject on QueryBuilder {} + +extension LineQuerySortBy on QueryBuilder { + QueryBuilder sortById() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(0); + }); + } + + QueryBuilder sortByIdDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(0, sort: Sort.desc); + }); + } + + QueryBuilder sortByText( + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addSortBy( + 1, + caseSensitive: caseSensitive, + ); + }); + } + + QueryBuilder sortByTextDesc( + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addSortBy( + 1, + sort: Sort.desc, + caseSensitive: caseSensitive, + ); + }); + } + + QueryBuilder sortByBookTitle( + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addSortBy( + 2, + caseSensitive: caseSensitive, + ); + }); + } + + QueryBuilder sortByBookTitleDesc( + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addSortBy( + 2, + sort: Sort.desc, + caseSensitive: caseSensitive, + ); + }); + } + + QueryBuilder sortByTopics( + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addSortBy( + 3, + caseSensitive: caseSensitive, + ); + }); + } + + QueryBuilder sortByTopicsDesc( + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addSortBy( + 3, + sort: Sort.desc, + caseSensitive: caseSensitive, + ); + }); + } + + QueryBuilder sortByIndex() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(4); + }); + } + + QueryBuilder sortByIndexDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(4, sort: Sort.desc); + }); + } +} + +extension LineQuerySortThenBy on QueryBuilder { + QueryBuilder thenById() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(0); + }); + } + + QueryBuilder thenByIdDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(0, sort: Sort.desc); + }); + } + + QueryBuilder thenByText( + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(1, caseSensitive: caseSensitive); + }); + } + + QueryBuilder thenByTextDesc( + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(1, sort: Sort.desc, caseSensitive: caseSensitive); + }); + } + + QueryBuilder thenByBookTitle( + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(2, caseSensitive: caseSensitive); + }); + } + + QueryBuilder thenByBookTitleDesc( + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(2, sort: Sort.desc, caseSensitive: caseSensitive); + }); + } + + QueryBuilder thenByTopics( + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(3, caseSensitive: caseSensitive); + }); + } + + QueryBuilder thenByTopicsDesc( + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(3, sort: Sort.desc, caseSensitive: caseSensitive); + }); + } + + QueryBuilder thenByIndex() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(4); + }); + } + + QueryBuilder thenByIndexDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(4, sort: Sort.desc); + }); + } +} + +extension LineQueryWhereDistinct on QueryBuilder { + QueryBuilder distinctByText( + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(1, caseSensitive: caseSensitive); + }); + } + + QueryBuilder distinctByBookTitle( + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(2, caseSensitive: caseSensitive); + }); + } + + QueryBuilder distinctByTopics( + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(3, caseSensitive: caseSensitive); + }); + } + + QueryBuilder distinctByIndex() { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(4); + }); + } +} + +extension LineQueryProperty1 on QueryBuilder { + QueryBuilder idProperty() { + return QueryBuilder.apply(this, (query) { + return query.addProperty(0); + }); + } + + QueryBuilder textProperty() { + return QueryBuilder.apply(this, (query) { + return query.addProperty(1); + }); + } + + QueryBuilder bookTitleProperty() { + return QueryBuilder.apply(this, (query) { + return query.addProperty(2); + }); + } + + QueryBuilder topicsProperty() { + return QueryBuilder.apply(this, (query) { + return query.addProperty(3); + }); + } + + QueryBuilder indexProperty() { + return QueryBuilder.apply(this, (query) { + return query.addProperty(4); + }); + } +} + +extension LineQueryProperty2 on QueryBuilder { + QueryBuilder idProperty() { + return QueryBuilder.apply(this, (query) { + return query.addProperty(0); + }); + } + + QueryBuilder textProperty() { + return QueryBuilder.apply(this, (query) { + return query.addProperty(1); + }); + } + + QueryBuilder bookTitleProperty() { + return QueryBuilder.apply(this, (query) { + return query.addProperty(2); + }); + } + + QueryBuilder topicsProperty() { + return QueryBuilder.apply(this, (query) { + return query.addProperty(3); + }); + } + + QueryBuilder indexProperty() { + return QueryBuilder.apply(this, (query) { + return query.addProperty(4); + }); + } +} + +extension LineQueryProperty3 + on QueryBuilder { + QueryBuilder idProperty() { + return QueryBuilder.apply(this, (query) { + return query.addProperty(0); + }); + } + + QueryBuilder textProperty() { + return QueryBuilder.apply(this, (query) { + return query.addProperty(1); + }); + } + + QueryBuilder bookTitleProperty() { + return QueryBuilder.apply(this, (query) { + return query.addProperty(2); + }); + } + + QueryBuilder topicsProperty() { + return QueryBuilder.apply(this, (query) { + return query.addProperty(3); + }); + } + + QueryBuilder indexProperty() { + return QueryBuilder.apply(this, (query) { + return query.addProperty(4); + }); + } +} diff --git a/lib/models/isar_collections/ref.dart b/lib/models/isar_collections/ref.dart new file mode 100644 index 000000000..008b2f2c7 --- /dev/null +++ b/lib/models/isar_collections/ref.dart @@ -0,0 +1,21 @@ +import 'package:isar/isar.dart'; + +part 'ref.g.dart'; + +@Collection() +class Ref { + @Id() + final int id; + final String ref; + final String bookTitle; + final int index; + final bool pdfBook; + final String? pdfPath; + Ref( + {required this.id, + required this.ref, + required this.bookTitle, + required this.index, + required this.pdfBook, + this.pdfPath}); +} diff --git a/lib/models/isar_collections/ref.g.dart b/lib/models/isar_collections/ref.g.dart new file mode 100644 index 000000000..ad7ba0f9e --- /dev/null +++ b/lib/models/isar_collections/ref.g.dart @@ -0,0 +1,1296 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'ref.dart'; + +// ************************************************************************** +// _IsarCollectionGenerator +// ************************************************************************** + +// coverage:ignore-file +// ignore_for_file: duplicate_ignore, invalid_use_of_protected_member, lines_longer_than_80_chars, constant_identifier_names, avoid_js_rounded_ints, no_leading_underscores_for_local_identifiers, require_trailing_commas, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_in_if_null_operators, library_private_types_in_public_api, prefer_const_constructors +// ignore_for_file: type=lint + +extension GetRefCollection on Isar { + IsarCollection get refs => this.collection(); +} + +const RefSchema = IsarGeneratedSchema( + schema: IsarSchema( + name: 'Ref', + idName: 'id', + embedded: false, + properties: [ + IsarPropertySchema( + name: 'ref', + type: IsarType.string, + ), + IsarPropertySchema( + name: 'bookTitle', + type: IsarType.string, + ), + IsarPropertySchema( + name: 'index', + type: IsarType.long, + ), + IsarPropertySchema( + name: 'pdfBook', + type: IsarType.bool, + ), + IsarPropertySchema( + name: 'pdfPath', + type: IsarType.string, + ), + ], + indexes: [], + ), + converter: IsarObjectConverter( + serialize: serializeRef, + deserialize: deserializeRef, + deserializeProperty: deserializeRefProp, + ), + embeddedSchemas: [], +); + +@isarProtected +int serializeRef(IsarWriter writer, Ref object) { + IsarCore.writeString(writer, 1, object.ref); + IsarCore.writeString(writer, 2, object.bookTitle); + IsarCore.writeLong(writer, 3, object.index); + IsarCore.writeBool(writer, 4, object.pdfBook); + { + final value = object.pdfPath; + if (value == null) { + IsarCore.writeNull(writer, 5); + } else { + IsarCore.writeString(writer, 5, value); + } + } + return object.id; +} + +@isarProtected +Ref deserializeRef(IsarReader reader) { + final int _id; + _id = IsarCore.readId(reader); + final String _ref; + _ref = IsarCore.readString(reader, 1) ?? ''; + final String _bookTitle; + _bookTitle = IsarCore.readString(reader, 2) ?? ''; + final int _index; + _index = IsarCore.readLong(reader, 3); + final bool _pdfBook; + _pdfBook = IsarCore.readBool(reader, 4); + final String? _pdfPath; + _pdfPath = IsarCore.readString(reader, 5); + final object = Ref( + id: _id, + ref: _ref, + bookTitle: _bookTitle, + index: _index, + pdfBook: _pdfBook, + pdfPath: _pdfPath, + ); + return object; +} + +@isarProtected +dynamic deserializeRefProp(IsarReader reader, int property) { + switch (property) { + case 0: + return IsarCore.readId(reader); + case 1: + return IsarCore.readString(reader, 1) ?? ''; + case 2: + return IsarCore.readString(reader, 2) ?? ''; + case 3: + return IsarCore.readLong(reader, 3); + case 4: + return IsarCore.readBool(reader, 4); + case 5: + return IsarCore.readString(reader, 5); + default: + throw ArgumentError('Unknown property: $property'); + } +} + +sealed class _RefUpdate { + bool call({ + required int id, + String? ref, + String? bookTitle, + int? index, + bool? pdfBook, + String? pdfPath, + }); +} + +class _RefUpdateImpl implements _RefUpdate { + const _RefUpdateImpl(this.collection); + + final IsarCollection collection; + + @override + bool call({ + required int id, + Object? ref = ignore, + Object? bookTitle = ignore, + Object? index = ignore, + Object? pdfBook = ignore, + Object? pdfPath = ignore, + }) { + return collection.updateProperties([ + id + ], { + if (ref != ignore) 1: ref as String?, + if (bookTitle != ignore) 2: bookTitle as String?, + if (index != ignore) 3: index as int?, + if (pdfBook != ignore) 4: pdfBook as bool?, + if (pdfPath != ignore) 5: pdfPath as String?, + }) > + 0; + } +} + +sealed class _RefUpdateAll { + int call({ + required List id, + String? ref, + String? bookTitle, + int? index, + bool? pdfBook, + String? pdfPath, + }); +} + +class _RefUpdateAllImpl implements _RefUpdateAll { + const _RefUpdateAllImpl(this.collection); + + final IsarCollection collection; + + @override + int call({ + required List id, + Object? ref = ignore, + Object? bookTitle = ignore, + Object? index = ignore, + Object? pdfBook = ignore, + Object? pdfPath = ignore, + }) { + return collection.updateProperties(id, { + if (ref != ignore) 1: ref as String?, + if (bookTitle != ignore) 2: bookTitle as String?, + if (index != ignore) 3: index as int?, + if (pdfBook != ignore) 4: pdfBook as bool?, + if (pdfPath != ignore) 5: pdfPath as String?, + }); + } +} + +extension RefUpdate on IsarCollection { + _RefUpdate get update => _RefUpdateImpl(this); + + _RefUpdateAll get updateAll => _RefUpdateAllImpl(this); +} + +sealed class _RefQueryUpdate { + int call({ + String? ref, + String? bookTitle, + int? index, + bool? pdfBook, + String? pdfPath, + }); +} + +class _RefQueryUpdateImpl implements _RefQueryUpdate { + const _RefQueryUpdateImpl(this.query, {this.limit}); + + final IsarQuery query; + final int? limit; + + @override + int call({ + Object? ref = ignore, + Object? bookTitle = ignore, + Object? index = ignore, + Object? pdfBook = ignore, + Object? pdfPath = ignore, + }) { + return query.updateProperties(limit: limit, { + if (ref != ignore) 1: ref as String?, + if (bookTitle != ignore) 2: bookTitle as String?, + if (index != ignore) 3: index as int?, + if (pdfBook != ignore) 4: pdfBook as bool?, + if (pdfPath != ignore) 5: pdfPath as String?, + }); + } +} + +extension RefQueryUpdate on IsarQuery { + _RefQueryUpdate get updateFirst => _RefQueryUpdateImpl(this, limit: 1); + + _RefQueryUpdate get updateAll => _RefQueryUpdateImpl(this); +} + +class _RefQueryBuilderUpdateImpl implements _RefQueryUpdate { + const _RefQueryBuilderUpdateImpl(this.query, {this.limit}); + + final QueryBuilder query; + final int? limit; + + @override + int call({ + Object? ref = ignore, + Object? bookTitle = ignore, + Object? index = ignore, + Object? pdfBook = ignore, + Object? pdfPath = ignore, + }) { + final q = query.build(); + try { + return q.updateProperties(limit: limit, { + if (ref != ignore) 1: ref as String?, + if (bookTitle != ignore) 2: bookTitle as String?, + if (index != ignore) 3: index as int?, + if (pdfBook != ignore) 4: pdfBook as bool?, + if (pdfPath != ignore) 5: pdfPath as String?, + }); + } finally { + q.close(); + } + } +} + +extension RefQueryBuilderUpdate on QueryBuilder { + _RefQueryUpdate get updateFirst => _RefQueryBuilderUpdateImpl(this, limit: 1); + + _RefQueryUpdate get updateAll => _RefQueryBuilderUpdateImpl(this); +} + +extension RefQueryFilter on QueryBuilder { + QueryBuilder idEqualTo( + int value, + ) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + EqualCondition( + property: 0, + value: value, + ), + ); + }); + } + + QueryBuilder idGreaterThan( + int value, + ) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + GreaterCondition( + property: 0, + value: value, + ), + ); + }); + } + + QueryBuilder idGreaterThanOrEqualTo( + int value, + ) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + GreaterOrEqualCondition( + property: 0, + value: value, + ), + ); + }); + } + + QueryBuilder idLessThan( + int value, + ) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + LessCondition( + property: 0, + value: value, + ), + ); + }); + } + + QueryBuilder idLessThanOrEqualTo( + int value, + ) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + LessOrEqualCondition( + property: 0, + value: value, + ), + ); + }); + } + + QueryBuilder idBetween( + int lower, + int upper, + ) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + BetweenCondition( + property: 0, + lower: lower, + upper: upper, + ), + ); + }); + } + + QueryBuilder refEqualTo( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + EqualCondition( + property: 1, + value: value, + caseSensitive: caseSensitive, + ), + ); + }); + } + + QueryBuilder refGreaterThan( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + GreaterCondition( + property: 1, + value: value, + caseSensitive: caseSensitive, + ), + ); + }); + } + + QueryBuilder refGreaterThanOrEqualTo( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + GreaterOrEqualCondition( + property: 1, + value: value, + caseSensitive: caseSensitive, + ), + ); + }); + } + + QueryBuilder refLessThan( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + LessCondition( + property: 1, + value: value, + caseSensitive: caseSensitive, + ), + ); + }); + } + + QueryBuilder refLessThanOrEqualTo( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + LessOrEqualCondition( + property: 1, + value: value, + caseSensitive: caseSensitive, + ), + ); + }); + } + + QueryBuilder refBetween( + String lower, + String upper, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + BetweenCondition( + property: 1, + lower: lower, + upper: upper, + caseSensitive: caseSensitive, + ), + ); + }); + } + + QueryBuilder refStartsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + StartsWithCondition( + property: 1, + value: value, + caseSensitive: caseSensitive, + ), + ); + }); + } + + QueryBuilder refEndsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + EndsWithCondition( + property: 1, + value: value, + caseSensitive: caseSensitive, + ), + ); + }); + } + + QueryBuilder refContains(String value, + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + ContainsCondition( + property: 1, + value: value, + caseSensitive: caseSensitive, + ), + ); + }); + } + + QueryBuilder refMatches(String pattern, + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + MatchesCondition( + property: 1, + wildcard: pattern, + caseSensitive: caseSensitive, + ), + ); + }); + } + + QueryBuilder refIsEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + const EqualCondition( + property: 1, + value: '', + ), + ); + }); + } + + QueryBuilder refIsNotEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + const GreaterCondition( + property: 1, + value: '', + ), + ); + }); + } + + QueryBuilder bookTitleEqualTo( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + EqualCondition( + property: 2, + value: value, + caseSensitive: caseSensitive, + ), + ); + }); + } + + QueryBuilder bookTitleGreaterThan( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + GreaterCondition( + property: 2, + value: value, + caseSensitive: caseSensitive, + ), + ); + }); + } + + QueryBuilder bookTitleGreaterThanOrEqualTo( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + GreaterOrEqualCondition( + property: 2, + value: value, + caseSensitive: caseSensitive, + ), + ); + }); + } + + QueryBuilder bookTitleLessThan( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + LessCondition( + property: 2, + value: value, + caseSensitive: caseSensitive, + ), + ); + }); + } + + QueryBuilder bookTitleLessThanOrEqualTo( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + LessOrEqualCondition( + property: 2, + value: value, + caseSensitive: caseSensitive, + ), + ); + }); + } + + QueryBuilder bookTitleBetween( + String lower, + String upper, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + BetweenCondition( + property: 2, + lower: lower, + upper: upper, + caseSensitive: caseSensitive, + ), + ); + }); + } + + QueryBuilder bookTitleStartsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + StartsWithCondition( + property: 2, + value: value, + caseSensitive: caseSensitive, + ), + ); + }); + } + + QueryBuilder bookTitleEndsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + EndsWithCondition( + property: 2, + value: value, + caseSensitive: caseSensitive, + ), + ); + }); + } + + QueryBuilder bookTitleContains(String value, + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + ContainsCondition( + property: 2, + value: value, + caseSensitive: caseSensitive, + ), + ); + }); + } + + QueryBuilder bookTitleMatches(String pattern, + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + MatchesCondition( + property: 2, + wildcard: pattern, + caseSensitive: caseSensitive, + ), + ); + }); + } + + QueryBuilder bookTitleIsEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + const EqualCondition( + property: 2, + value: '', + ), + ); + }); + } + + QueryBuilder bookTitleIsNotEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + const GreaterCondition( + property: 2, + value: '', + ), + ); + }); + } + + QueryBuilder indexEqualTo( + int value, + ) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + EqualCondition( + property: 3, + value: value, + ), + ); + }); + } + + QueryBuilder indexGreaterThan( + int value, + ) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + GreaterCondition( + property: 3, + value: value, + ), + ); + }); + } + + QueryBuilder indexGreaterThanOrEqualTo( + int value, + ) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + GreaterOrEqualCondition( + property: 3, + value: value, + ), + ); + }); + } + + QueryBuilder indexLessThan( + int value, + ) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + LessCondition( + property: 3, + value: value, + ), + ); + }); + } + + QueryBuilder indexLessThanOrEqualTo( + int value, + ) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + LessOrEqualCondition( + property: 3, + value: value, + ), + ); + }); + } + + QueryBuilder indexBetween( + int lower, + int upper, + ) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + BetweenCondition( + property: 3, + lower: lower, + upper: upper, + ), + ); + }); + } + + QueryBuilder pdfBookEqualTo( + bool value, + ) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + EqualCondition( + property: 4, + value: value, + ), + ); + }); + } + + QueryBuilder pdfPathIsNull() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(const IsNullCondition(property: 5)); + }); + } + + QueryBuilder pdfPathIsNotNull() { + return QueryBuilder.apply(not(), (query) { + return query.addFilterCondition(const IsNullCondition(property: 5)); + }); + } + + QueryBuilder pdfPathEqualTo( + String? value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + EqualCondition( + property: 5, + value: value, + caseSensitive: caseSensitive, + ), + ); + }); + } + + QueryBuilder pdfPathGreaterThan( + String? value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + GreaterCondition( + property: 5, + value: value, + caseSensitive: caseSensitive, + ), + ); + }); + } + + QueryBuilder pdfPathGreaterThanOrEqualTo( + String? value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + GreaterOrEqualCondition( + property: 5, + value: value, + caseSensitive: caseSensitive, + ), + ); + }); + } + + QueryBuilder pdfPathLessThan( + String? value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + LessCondition( + property: 5, + value: value, + caseSensitive: caseSensitive, + ), + ); + }); + } + + QueryBuilder pdfPathLessThanOrEqualTo( + String? value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + LessOrEqualCondition( + property: 5, + value: value, + caseSensitive: caseSensitive, + ), + ); + }); + } + + QueryBuilder pdfPathBetween( + String? lower, + String? upper, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + BetweenCondition( + property: 5, + lower: lower, + upper: upper, + caseSensitive: caseSensitive, + ), + ); + }); + } + + QueryBuilder pdfPathStartsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + StartsWithCondition( + property: 5, + value: value, + caseSensitive: caseSensitive, + ), + ); + }); + } + + QueryBuilder pdfPathEndsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + EndsWithCondition( + property: 5, + value: value, + caseSensitive: caseSensitive, + ), + ); + }); + } + + QueryBuilder pdfPathContains(String value, + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + ContainsCondition( + property: 5, + value: value, + caseSensitive: caseSensitive, + ), + ); + }); + } + + QueryBuilder pdfPathMatches(String pattern, + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + MatchesCondition( + property: 5, + wildcard: pattern, + caseSensitive: caseSensitive, + ), + ); + }); + } + + QueryBuilder pdfPathIsEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + const EqualCondition( + property: 5, + value: '', + ), + ); + }); + } + + QueryBuilder pdfPathIsNotEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition( + const GreaterCondition( + property: 5, + value: '', + ), + ); + }); + } +} + +extension RefQueryObject on QueryBuilder {} + +extension RefQuerySortBy on QueryBuilder { + QueryBuilder sortById() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(0); + }); + } + + QueryBuilder sortByIdDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(0, sort: Sort.desc); + }); + } + + QueryBuilder sortByRef({bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addSortBy( + 1, + caseSensitive: caseSensitive, + ); + }); + } + + QueryBuilder sortByRefDesc( + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addSortBy( + 1, + sort: Sort.desc, + caseSensitive: caseSensitive, + ); + }); + } + + QueryBuilder sortByBookTitle( + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addSortBy( + 2, + caseSensitive: caseSensitive, + ); + }); + } + + QueryBuilder sortByBookTitleDesc( + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addSortBy( + 2, + sort: Sort.desc, + caseSensitive: caseSensitive, + ); + }); + } + + QueryBuilder sortByIndex() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(3); + }); + } + + QueryBuilder sortByIndexDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(3, sort: Sort.desc); + }); + } + + QueryBuilder sortByPdfBook() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(4); + }); + } + + QueryBuilder sortByPdfBookDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(4, sort: Sort.desc); + }); + } + + QueryBuilder sortByPdfPath( + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addSortBy( + 5, + caseSensitive: caseSensitive, + ); + }); + } + + QueryBuilder sortByPdfPathDesc( + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addSortBy( + 5, + sort: Sort.desc, + caseSensitive: caseSensitive, + ); + }); + } +} + +extension RefQuerySortThenBy on QueryBuilder { + QueryBuilder thenById() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(0); + }); + } + + QueryBuilder thenByIdDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(0, sort: Sort.desc); + }); + } + + QueryBuilder thenByRef({bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(1, caseSensitive: caseSensitive); + }); + } + + QueryBuilder thenByRefDesc( + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(1, sort: Sort.desc, caseSensitive: caseSensitive); + }); + } + + QueryBuilder thenByBookTitle( + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(2, caseSensitive: caseSensitive); + }); + } + + QueryBuilder thenByBookTitleDesc( + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(2, sort: Sort.desc, caseSensitive: caseSensitive); + }); + } + + QueryBuilder thenByIndex() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(3); + }); + } + + QueryBuilder thenByIndexDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(3, sort: Sort.desc); + }); + } + + QueryBuilder thenByPdfBook() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(4); + }); + } + + QueryBuilder thenByPdfBookDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(4, sort: Sort.desc); + }); + } + + QueryBuilder thenByPdfPath( + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(5, caseSensitive: caseSensitive); + }); + } + + QueryBuilder thenByPdfPathDesc( + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(5, sort: Sort.desc, caseSensitive: caseSensitive); + }); + } +} + +extension RefQueryWhereDistinct on QueryBuilder { + QueryBuilder distinctByRef( + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(1, caseSensitive: caseSensitive); + }); + } + + QueryBuilder distinctByBookTitle( + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(2, caseSensitive: caseSensitive); + }); + } + + QueryBuilder distinctByIndex() { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(3); + }); + } + + QueryBuilder distinctByPdfBook() { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(4); + }); + } + + QueryBuilder distinctByPdfPath( + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(5, caseSensitive: caseSensitive); + }); + } +} + +extension RefQueryProperty1 on QueryBuilder { + QueryBuilder idProperty() { + return QueryBuilder.apply(this, (query) { + return query.addProperty(0); + }); + } + + QueryBuilder refProperty() { + return QueryBuilder.apply(this, (query) { + return query.addProperty(1); + }); + } + + QueryBuilder bookTitleProperty() { + return QueryBuilder.apply(this, (query) { + return query.addProperty(2); + }); + } + + QueryBuilder indexProperty() { + return QueryBuilder.apply(this, (query) { + return query.addProperty(3); + }); + } + + QueryBuilder pdfBookProperty() { + return QueryBuilder.apply(this, (query) { + return query.addProperty(4); + }); + } + + QueryBuilder pdfPathProperty() { + return QueryBuilder.apply(this, (query) { + return query.addProperty(5); + }); + } +} + +extension RefQueryProperty2 on QueryBuilder { + QueryBuilder idProperty() { + return QueryBuilder.apply(this, (query) { + return query.addProperty(0); + }); + } + + QueryBuilder refProperty() { + return QueryBuilder.apply(this, (query) { + return query.addProperty(1); + }); + } + + QueryBuilder bookTitleProperty() { + return QueryBuilder.apply(this, (query) { + return query.addProperty(2); + }); + } + + QueryBuilder indexProperty() { + return QueryBuilder.apply(this, (query) { + return query.addProperty(3); + }); + } + + QueryBuilder pdfBookProperty() { + return QueryBuilder.apply(this, (query) { + return query.addProperty(4); + }); + } + + QueryBuilder pdfPathProperty() { + return QueryBuilder.apply(this, (query) { + return query.addProperty(5); + }); + } +} + +extension RefQueryProperty3 + on QueryBuilder { + QueryBuilder idProperty() { + return QueryBuilder.apply(this, (query) { + return query.addProperty(0); + }); + } + + QueryBuilder refProperty() { + return QueryBuilder.apply(this, (query) { + return query.addProperty(1); + }); + } + + QueryBuilder bookTitleProperty() { + return QueryBuilder.apply(this, (query) { + return query.addProperty(2); + }); + } + + QueryBuilder indexProperty() { + return QueryBuilder.apply(this, (query) { + return query.addProperty(3); + }); + } + + QueryBuilder pdfBookProperty() { + return QueryBuilder.apply(this, (query) { + return query.addProperty(4); + }); + } + + QueryBuilder pdfPathProperty() { + return QueryBuilder.apply(this, (query) { + return query.addProperty(5); + }); + } +} diff --git a/lib/models/library.dart b/lib/models/library.dart index f91df5571..52c6de7cb 100644 --- a/lib/models/library.dart +++ b/lib/models/library.dart @@ -2,7 +2,7 @@ contain other categories and books */ import 'package:otzaria/models/books.dart'; -import 'package:otzaria/data/file_system_data_provider.dart'; +import 'package:otzaria/data/data_providers/file_system_data_provider.dart'; /// Represents a category in the library. /// diff --git a/lib/models/links.dart b/lib/models/links.dart index 6f6de0611..ec9cc409a 100644 --- a/lib/models/links.dart +++ b/lib/models/links.dart @@ -1,15 +1,15 @@ /* represents links between two books in the library*/ -import 'package:otzaria/data/file_system_data_provider.dart'; +import 'package:otzaria/data/data_providers/file_system_data_provider.dart'; +import 'package:otzaria/data/repository/data_repository.dart'; import 'package:otzaria/models/books.dart'; import 'dart:isolate'; -import 'package:otzaria/data/data.dart'; import 'package:otzaria/utils/text_manipulation.dart' as utils; /// Represents a link between two books in the library. class Link { /// The [Data] object used for file system operations. - final Data data = FileSystemData.instance; + final DataRepository data = DataRepository.instance; /// The Hebrew reference of the link. final String heRef; @@ -36,7 +36,7 @@ class Link { }); /// Returns the content of the link as a [Future] of [String]. - Future get content => data.getLinkContent(this); + Future get content => FileSystemData.instance.getLinkContent(this); /// Constructs a [Link] object from a JSON object. /// diff --git a/lib/models/tabs.dart b/lib/models/tabs.dart index 305248400..24970dec5 100644 --- a/lib/models/tabs.dart +++ b/lib/models/tabs.dart @@ -4,7 +4,7 @@ a tab is either a pdf book or a text book, or a full text search window*/ import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; import 'package:multi_split_view/multi_split_view.dart'; -import 'package:otzaria/data/file_system_data_provider.dart'; +import 'package:otzaria/data/data_providers/file_system_data_provider.dart'; import 'package:otzaria/utils/text_manipulation.dart'; import 'package:scrollable_positioned_list/scrollable_positioned_list.dart'; import 'package:pdfrx/pdfrx.dart'; @@ -12,6 +12,7 @@ import 'package:otzaria/models/links.dart'; import 'package:otzaria/models/full_text_search.dart'; import 'package:otzaria/models/books.dart'; import 'package:flutter_settings_screens/flutter_settings_screens.dart'; +import 'package:search_engine/search_engine.dart'; abstract class OpenedTab { String title; @@ -270,6 +271,11 @@ class TextBookTab extends OpenedTab { } class SearchingTab extends OpenedTab { + ValueNotifier aproximateSearch = ValueNotifier(false); + final queryController = TextEditingController(); + ValueNotifier> booksToSearch = ValueNotifier({}); + Future> results = Future.value([]); + ValueNotifier numResults = ValueNotifier(100); FullTextSearcher searcher = FullTextSearcher( [], TextEditingController(), @@ -279,7 +285,9 @@ class SearchingTab extends OpenedTab { SearchingTab( super.title, - ); + ) { + () async {}(); + } @override factory SearchingTab.fromJson(Map json) { diff --git a/lib/screens/bookmark_screen.dart b/lib/screens/favorites/bookmark_screen.dart similarity index 100% rename from lib/screens/bookmark_screen.dart rename to lib/screens/favorites/bookmark_screen.dart diff --git a/lib/screens/favoriets.dart b/lib/screens/favorites/favoriets.dart similarity index 84% rename from lib/screens/favoriets.dart rename to lib/screens/favorites/favoriets.dart index 4361d2862..e5976bc40 100644 --- a/lib/screens/favoriets.dart +++ b/lib/screens/favorites/favoriets.dart @@ -1,9 +1,9 @@ /// a widget that contains two tabs: history and bookmarks. /// The bookmarks tab is BookmarkView and the history is HistoryView. import 'package:flutter/material.dart'; -import 'package:otzaria/screens/history_screen.dart'; -import 'package:otzaria/screens/bookmark_screen.dart'; -import 'package:otzaria/screens/workspaces_screen.dart'; +import 'package:otzaria/screens/favorites/history_screen.dart'; +import 'package:otzaria/screens/favorites/bookmark_screen.dart'; +import 'package:otzaria/screens/favorites/workspaces_screen.dart'; class FavouritesScreen extends StatelessWidget { const FavouritesScreen({Key? key}) : super(key: key); diff --git a/lib/screens/history_screen.dart b/lib/screens/favorites/history_screen.dart similarity index 100% rename from lib/screens/history_screen.dart rename to lib/screens/favorites/history_screen.dart diff --git a/lib/screens/workspaces_screen.dart b/lib/screens/favorites/workspaces_screen.dart similarity index 100% rename from lib/screens/workspaces_screen.dart rename to lib/screens/favorites/workspaces_screen.dart diff --git a/lib/screens/find_book_screen.dart b/lib/screens/find_book_screen.dart deleted file mode 100644 index 8344d7982..000000000 --- a/lib/screens/find_book_screen.dart +++ /dev/null @@ -1,122 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:fuzzywuzzy/fuzzywuzzy.dart'; -import 'dart:io'; - -class BookSearchScreen extends StatefulWidget { - final void Function(String, int) openBookCallback; - final void Function() closeLeftPaneCallback; - final FocusNode focusNode; - final String libraryRootPath; - - const BookSearchScreen( - {Key? key, - required this.openBookCallback, - required this.closeLeftPaneCallback, - required this.focusNode, - required this.libraryRootPath}) - : super(key: key); - - @override - BookSearchScreenState createState() => BookSearchScreenState(); -} - -class BookSearchScreenState extends State { - TextEditingController searchController = TextEditingController(); - - late final List books; - - @override - initState() { - super.initState(); - books = - Directory('${widget.libraryRootPath}${Platform.pathSeparator}אוצריא') - .listSync(recursive: true) - .whereType() - .map((e) => e.path) - .toList(); - - searchController.addListener(() => _searchBooks(searchController.text)); - } - - List _searchResults = []; - - void _searchBooks(String query) async { - final results = books.where((book) { - final bookName = book.split(Platform.pathSeparator).last; - // if all the words seperated by spaces exist in the book name, even not in order, return true - bool result = true; - for (final word in query.split(' ')) { - result = result && bookName.contains(word); - } - return result; - }).toList(); - //sort the results by their levenstien distance - if (query.isNotEmpty) { - results.sort( - (a, b) => ratio(query, b.split(Platform.pathSeparator).last.trim()) - .compareTo( - ratio(query, a.split(Platform.pathSeparator).last.trim())), - ); - } - // sort alphabetic - else { - results.sort((a, b) => a - .split(Platform.pathSeparator) - .last - .trim() - .compareTo(b.split(Platform.pathSeparator).last.trim())); - } - - setState(() { - _searchResults = results; - }); - } - - @override - void dispose() { - searchController.dispose(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: const Text('חיפוש ספר'), - ), - body: Center( - child: Column( - children: [ - TextField( - focusNode: widget.focusNode, - autofocus: true, - controller: searchController, - decoration: const InputDecoration( - labelText: 'הקלד שם ספר: ', - ), - ), - Expanded( - child: ListView.builder( - itemCount: _searchResults.length, - itemBuilder: (context, index) { - final book = _searchResults[index]; - return ListTile( - title: Text(book.split(Platform.pathSeparator).last), - onTap: () { - //close the sidebar - widget.closeLeftPaneCallback(); - Future.microtask(() { - //open the book - widget.openBookCallback(book, 0); - //clear textField - searchController.clear(); - }); - }); - }, - ), - ), - ], - ), - )); - } -} diff --git a/lib/screens/find_ref_screen.dart b/lib/screens/find_ref_screen.dart new file mode 100644 index 000000000..5a4a40489 --- /dev/null +++ b/lib/screens/find_ref_screen.dart @@ -0,0 +1,121 @@ +import 'package:flutter/material.dart'; +import 'package:otzaria/data/repository/data_repository.dart'; +import 'package:otzaria/models/app_model.dart'; +import 'package:otzaria/models/books.dart'; +import 'package:otzaria/models/isar_collections/ref.dart'; +import 'package:otzaria/screens/ref_indexing_screen.dart'; +import 'package:otzaria/utils/text_manipulation.dart'; +import 'package:provider/provider.dart'; + +class FindRefScreen extends StatefulWidget { + const FindRefScreen({super.key}); + + @override + State createState() => _FindRefScreenState(); +} + +class _FindRefScreenState extends State { + final TextEditingController _searchController = TextEditingController(); + late Future> _refs; + + @override + void initState() { + super.initState(); + _refs = findRefs(_searchController.text); + } + + Future> findRefs(String ref) async { + if (ref.length < 3) { + return []; + } + //ref = paraphrase(ref); + return DataRepository.instance.findRefsByRelevance( + ref, + ); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + drawer: const Drawer( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.zero)), + semanticLabel: 'הגדרות אינדקס', + child: RefIndexingScreen()), + appBar: AppBar( + title: const Center(child: Text('איתור מקורות')), + ), + body: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + children: [ + TextField( + autofocus: true, + focusNode: context.read().findReferenceFocusNode, + decoration: InputDecoration( + hintText: + 'הקלד מקור מדוייק, לדוגמה: בראשית פרק א או שוע אוח יב ', + suffixIcon: Row( + mainAxisSize: MainAxisSize.min, + children: [ + IconButton( + icon: const Icon(Icons.clear), + onPressed: () { + setState(() { + _searchController.clear(); + }); + }, + ), + ], + ), + ), + controller: _searchController, + onChanged: (ref) { + setState(() { + _refs = findRefs(ref); + }); + }, + ), + Expanded( + child: FutureBuilder>( + future: _refs, + builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.waiting) { + return const Center(child: CircularProgressIndicator()); + } else if (snapshot.hasError) { + return Text('Error: ${snapshot.error}'); + } else { + return ListView.builder( + itemCount: snapshot.data!.length, + itemBuilder: (context, index) { + return ListTile( + title: Text(snapshot.data![index].ref), + onTap: () { + final appModel = + Provider.of(context, listen: false); + if (snapshot.data![index].pdfBook) { + appModel.openBook( + PdfBook( + title: snapshot.data![index].bookTitle, + path: snapshot.data![index].pdfPath!), + snapshot.data![index].index); + } else { + appModel.openBook( + TextBook( + title: snapshot.data![index].bookTitle, + ), + snapshot.data![index].index); + } + }); + }, + ); + } + }, + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/screens/book_tree_checklist.dart b/lib/screens/full_text_search/book_tree_checklist.dart similarity index 100% rename from lib/screens/book_tree_checklist.dart rename to lib/screens/full_text_search/book_tree_checklist.dart diff --git a/lib/screens/full_text_search/full_text_book_list.dart b/lib/screens/full_text_search/full_text_book_list.dart new file mode 100644 index 000000000..cb97b185d --- /dev/null +++ b/lib/screens/full_text_search/full_text_book_list.dart @@ -0,0 +1,164 @@ +import 'package:flutter/material.dart'; +import 'package:filter_list/filter_list.dart'; +import 'package:otzaria/models/books.dart'; +import 'package:otzaria/models/tabs.dart'; + +class FullTextBookList extends StatefulWidget { + final SearchingTab tab; + final List books; + const FullTextBookList({Key? key, required this.books, required this.tab}) + : super(key: key); + @override + State createState() => _FullTextBookListState(); +} + +class _FullTextBookListState extends State { + List books = []; + List allTopics = []; + List selectedTopics = []; + String _filterQuery = ''; + + void update() { + var filteredList = + widget.books.where((book) => book.title.contains(_filterQuery)); + if (selectedTopics.isNotEmpty) { + filteredList = filteredList.where((book) => + book.topics.split(', ').any((t) => selectedTopics.contains(t))); + } + setState(() { + books = filteredList.toList(); + }); + } + + @override + void initState() { + books = widget.books; + super.initState(); + Set allTopicsSet = {}; + for (Book book in widget.books) { + allTopicsSet.addAll(book.topics.split(', ')); + } + allTopics = allTopicsSet.toList(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Column( + children: [ + Padding( + padding: const EdgeInsets.fromLTRB(5, 20, 5, 5.0), + child: ElevatedButton( + child: const Text('בחר קטגוריות'), + onPressed: () async { + await openFilterDialog(); + update(); + }, //openFilterDialog, + ), + ), + selectedTopics.isEmpty + ? const SizedBox.shrink() + : Text( + '${selectedTopics.length} קטגוריות נבחרו: (${selectedTopics.join(', ')})', + style: const TextStyle(fontSize: 13), + ), + TextField( + decoration: const InputDecoration( + hintText: "סינון", + ), + onChanged: (query) { + setState(() { + _filterQuery = query; + update(); + }); + }, + ), + CheckboxListTile( + title: const Text("הכל"), + value: books + .every((test) => widget.tab.booksToSearch.value.contains(test)), + onChanged: (value) { + setState(() { + if (value!) { + widget.tab.booksToSearch.value.addAll(books); + } else { + widget.tab.booksToSearch.value + .removeWhere((e) => books.contains(e)); + } + widget.tab.booksToSearch.notifyListeners(); + }); + }, + ), + Expanded( + child: ListView.builder( + itemCount: books.length, + itemBuilder: (context, index) => CheckboxListTile( + title: Text(books[index].title), + value: widget.tab.booksToSearch.value.contains(books[index]), + onChanged: (value) { + if (value!) { + widget.tab.booksToSearch.value.add(books[index]); + } else { + widget.tab.booksToSearch.value + .removeWhere((s) => s == books[index]); + } + widget.tab.booksToSearch.notifyListeners(); + setState(() {}); + }, + ), + ), + ), + ], + ), + ); + } + + Future openFilterDialog() async { + await FilterListDialog.display( + context, + listData: allTopics, + hideCloseIcon: true, + controlButtons: [ControlButtonType.Reset], + selectedListData: selectedTopics, + allButtonText: 'הכל', + applyButtonText: 'סיום', + headlineText: 'בחר קטגוריות', + resetButtonText: 'איפוס', + selectedItemsText: 'קטגוריות נבחרו', + themeData: FilterListThemeData( + context, + wrapAlignment: WrapAlignment.center, + ), + choiceChipBuilder: (context, item, isSelected) => Padding( + padding: const EdgeInsets.symmetric( + horizontal: 3, + vertical: 2, + ), + child: Chip( + label: Text(item), + backgroundColor: + isSelected! ? Theme.of(context).colorScheme.secondary : null, + labelStyle: TextStyle( + color: + isSelected! ? Theme.of(context).colorScheme.onSecondary : null, + fontSize: 11, + ), + labelPadding: const EdgeInsets.all(0), + ), + ), + choiceChipLabel: (topic) => topic, + validateSelectedItem: (list, val) => list!.contains(val), + onItemSearch: (topic, query) { + return topic.contains(query); + }, + onApplyButtonClick: (list) { + setState(() { + selectedTopics = List.from(list!); + update(); + }); + + Navigator.pop(context); + }, + ); + } +} diff --git a/lib/screens/full_text_search/full_text_book_tree.dart b/lib/screens/full_text_search/full_text_book_tree.dart new file mode 100644 index 000000000..28e76f1c4 --- /dev/null +++ b/lib/screens/full_text_search/full_text_book_tree.dart @@ -0,0 +1,115 @@ +import 'package:flutter/material.dart'; +import 'package:otzaria/models/app_model.dart'; +import 'package:otzaria/models/books.dart'; +import 'package:otzaria/models/library.dart'; +import 'package:otzaria/models/tabs.dart'; +import 'package:provider/provider.dart'; + +class FullTextBookTree extends StatefulWidget { + final SearchingTab tab; + const FullTextBookTree({Key? key, required this.tab}) : super(key: key); + + @override + State createState() => _FullTextBookTreeState(); +} + +class _FullTextBookTreeState extends State { + @override + Widget build(BuildContext context) { + return ValueListenableBuilder( + valueListenable: widget.tab.booksToSearch, + builder: (context, value, child) { + return FutureBuilder( + future: Provider.of(context, listen: false).library, + builder: (context, snapshot) { + if (!snapshot.hasData) { + return const Center(child: CircularProgressIndicator()); + } + if (snapshot.hasError) { + return Center(child: Text('Error: ${snapshot.error}')); + } + return SingleChildScrollView(child: _buildTree(snapshot.data!)); + }); + }); + } + + Widget _buildTree(Category category, {int level = 0}) { + return ExpansionTile( + key: PageStorageKey(category), // Ensure unique keys for ExpansionTiles + title: Text(category.title), + + tilePadding: EdgeInsets.symmetric(horizontal: 6 + (level) * 6), + leading: SizedBox.fromSize( + size: const Size.fromWidth(60.0), + child: Row( + children: [ + Checkbox( + value: isCategoryChecked(category), + onChanged: (value) { + if (value != null && value) { + addCategory(category); + } else { + removeCategory(category); + } + }), + const Icon(Icons.folder), + ], // Icon(Icons.folder, + ), + ), + + children: ([] + category.subCategories + category.books).map((entity) { + if (entity is Category) { + return _buildTree(entity, level: level + 1); + } else if (entity is Book) { + return CheckboxListTile( + title: Row(children: [ + Text( + entity.title, + ), + ]), + value: widget.tab.booksToSearch.value.contains(entity), + onChanged: (value) { + widget.tab.booksToSearch.value.contains(entity) + ? widget.tab.booksToSearch.value.remove(entity) + : widget.tab.booksToSearch.value.add(entity); + widget.tab.booksToSearch.notifyListeners(); + }, //TODO: fix + controlAffinity: ListTileControlAffinity.leading, + contentPadding: EdgeInsets.symmetric(horizontal: 16 + level * 16), + ); + } else { + return ListTile( + title: Text('Unknown: ${entity.path}'), + ); + } + }).toList(), + ); + } + + void addCategory(Category category) { + for (Book book in category.books) { + widget.tab.booksToSearch.value.add(book); + } + for (Category subCategory in category.subCategories) { + addCategory(subCategory); + } + widget.tab.booksToSearch.notifyListeners(); + } + + void removeCategory(Category category) { + for (Book book in category.books) { + widget.tab.booksToSearch.value.remove(book); + } + for (Category subCategory in category.subCategories) { + removeCategory(subCategory); + } + + widget.tab.booksToSearch.notifyListeners(); + } + + bool isCategoryChecked(Category category) { + return category.books + .every((test) => widget.tab.booksToSearch.value.contains(test)) && + category.subCategories.every((test) => isCategoryChecked(test)); + } +} diff --git a/lib/screens/full_text_search/full_text_left_pane.dart b/lib/screens/full_text_search/full_text_left_pane.dart new file mode 100644 index 000000000..bd8fb89f1 --- /dev/null +++ b/lib/screens/full_text_search/full_text_left_pane.dart @@ -0,0 +1,74 @@ +import 'package:flutter/material.dart'; +import 'package:otzaria/models/app_model.dart'; +import 'package:otzaria/models/books.dart'; +import 'package:otzaria/models/tabs.dart'; +import 'package:otzaria/screens/full_text_search/full_text_book_list.dart'; +import 'package:otzaria/screens/full_text_search/full_text_book_tree.dart'; +import 'package:otzaria/screens/full_text_search/full_text_settings_screen.dart'; +import 'package:provider/provider.dart'; + +class FullTextLeftPane extends StatefulWidget { + final SearchingTab tab; + const FullTextLeftPane({Key? key, required this.tab}) : super(key: key); + @override + _FullTextLeftPaneState createState() => _FullTextLeftPaneState(); +} + +class _FullTextLeftPaneState extends State + with SingleTickerProviderStateMixin { + late TabController tabController; + @override + void initState() { + tabController = TabController(length: 3, vsync: this); + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Column(children: [ + TabBar( + controller: tabController, + tabs: const [ + Tab( + text: "הגדרות", + ), + Tab( + text: " סינון", + ), + Tab( + text: " עץ ספרים", + ), + ], + ), + Expanded( + child: TabBarView( + controller: tabController, + children: [ + FullTextSettingsScreen(tab: widget.tab), + FutureBuilder( + future: getBooks(), + builder: (context, snapshot) { + if (!snapshot.hasData) { + return const Center(child: CircularProgressIndicator()); + } + return FullTextBookList( + tab: widget.tab, + books: snapshot.data!, + ); + }), + FullTextBookTree(tab: widget.tab), + ], + ), + ), + ]); + } + + Future> getBooks() async { + final books = (await Provider.of(context, listen: false).library) + .getAllBooks(); + books.sort( + (a, b) => a.title.trim().compareTo(b.title.trim()), + ); + return books; + } +} diff --git a/lib/screens/full_text_search/full_text_search_screen.dart b/lib/screens/full_text_search/full_text_search_screen.dart new file mode 100644 index 000000000..f3c7947ed --- /dev/null +++ b/lib/screens/full_text_search/full_text_search_screen.dart @@ -0,0 +1,28 @@ +import 'package:flutter/material.dart'; +import 'package:otzaria/models/app_model.dart'; +import 'package:otzaria/models/tabs.dart'; +import 'package:otzaria/screens/full_text_search/tantivy_full_text_search.dart'; +import 'package:otzaria/screens/full_text_search/legacy_full_text_search_screen.dart'; +import 'package:provider/provider.dart'; + +class FullTextSearchScreen extends StatelessWidget { + final void Function(OpenedTab) openBookCallback; + final SearchingTab tab; + const FullTextSearchScreen( + {Key? key, required this.tab, required this.openBookCallback}) + : super(key: key); + @override + Widget build(BuildContext context) { + return ValueListenableBuilder( + valueListenable: context.read().useFastSearch, + builder: (context, value, child) => value + ? TantivyFullTextSearch( + tab: tab, + ) + : TextFileSearchScreen( + searcher: tab.searcher, + openBookCallback: openBookCallback, + ), + ); + } +} diff --git a/lib/screens/full_text_search/full_text_settings_screen.dart b/lib/screens/full_text_search/full_text_settings_screen.dart new file mode 100644 index 000000000..856e1d99c --- /dev/null +++ b/lib/screens/full_text_search/full_text_settings_screen.dart @@ -0,0 +1,150 @@ +import 'package:flutter/material.dart'; +import 'package:otzaria/data/data_providers/tantivy_data_provider.dart'; +import 'package:otzaria/models/app_model.dart'; +import 'package:otzaria/models/tabs.dart'; +import 'package:provider/provider.dart'; + +class FullTextSettingsScreen extends StatelessWidget { + const FullTextSettingsScreen({ + Key? key, + required this.tab, + }) : super(key: key); + final SearchingTab tab; + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Column( + children: [ + Expanded( + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(16.0), + child: Row( + children: [ + Expanded(child: Text('חיפוש מקורב')), + ValueListenableBuilder( + valueListenable: tab.aproximateSearch, + builder: (context, aproximateSearch, child) { + return Switch( + value: aproximateSearch, + onChanged: (value) => + tab.aproximateSearch.value = value); + }), + ], + ), + ), + Center( + child: Text(' מספר תוצאות להצגה'), + ), + ValueListenableBuilder( + valueListenable: tab.numResults, + builder: (context, numResults, child) { + return Padding( + padding: const EdgeInsets.all(8.0), + child: Slider( + value: numResults.toDouble(), + onChanged: (value) => + tab.numResults.value = (value.toInt()), + label: tab.numResults.value.toString(), + min: 10, + max: 10000, + divisions: 9990, + ), + ); + }), + Center( + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 30), + child: ValueListenableBuilder( + valueListenable: TantivyDataProvider.instance.isIndexing, + builder: (context, isIndexing, child) { + if (isIndexing) { + return const SizedBox.shrink(); + } + return ElevatedButton( + onPressed: () async { + final result = showDialog( + context: context, + builder: (context) => AlertDialog( + content: const Text( + 'עדכון האינדקס עלול לקחת זמן ומשאבים רבים. להמשיך?'), + actions: [ + TextButton( + child: const Text('ביטול'), + onPressed: () { + Navigator.pop(context, false); + }, + ), + TextButton( + child: const Text('אישור'), + onPressed: () { + Navigator.pop(context, true); + }, + ), + ], + )); + if (await result == true) { + context.read().addAllTextsToMimir(); + } + }, + child: const Text( + 'עדכון אינדקס', + ), + ); + }), + ), + ), + ValueListenableBuilder( + valueListenable: TantivyDataProvider.instance.isIndexing, + builder: (context, isIndexing, child) { + if (!isIndexing) { + return const SizedBox.shrink(); + } + return ValueListenableBuilder( + valueListenable: + TantivyDataProvider.instance.numOfbooksDone, + builder: (context, numOfbooksDone, child) => Column( + children: [ + ValueListenableBuilder( + valueListenable: + TantivyDataProvider.instance.numOfbooksTotal, + builder: (context, valueTotal, child) { + if (valueTotal == null) { + return const SizedBox.shrink(); + } + return Padding( + padding: const EdgeInsets.symmetric( + horizontal: 20, vertical: 50), + child: Column( + children: [ + LinearProgressIndicator( + borderRadius: BorderRadius.circular(20), + value: numOfbooksDone! / valueTotal, + ), + Text(' $valueTotal / $numOfbooksDone'), + ], + ), + ); + }), + isIndexing + ? Padding( + padding: const EdgeInsets.all(8.0), + child: ElevatedButton( + onPressed: () => TantivyDataProvider + .instance.isIndexing.value = false, + child: Text('עצור')), + ) + : SizedBox.shrink() + ], + ), + ); + }), + ], + ), + ) + ], + )); + } +} diff --git a/lib/screens/full_text_search_screen.dart b/lib/screens/full_text_search/legacy_full_text_search_screen.dart similarity index 98% rename from lib/screens/full_text_search_screen.dart rename to lib/screens/full_text_search/legacy_full_text_search_screen.dart index f9cc922cb..d70b56331 100644 --- a/lib/screens/full_text_search_screen.dart +++ b/lib/screens/full_text_search/legacy_full_text_search_screen.dart @@ -4,9 +4,9 @@ import 'package:flutter_settings_screens/flutter_settings_screens.dart'; import 'package:otzaria/models/books.dart'; import 'package:search_highlight_text/search_highlight_text.dart'; import 'book_tree_checklist.dart'; -import '../models/full_text_search.dart'; -import '../models/tabs.dart'; -import '../models/search_results.dart'; +import '../../models/full_text_search.dart'; +import '../../models/tabs.dart'; +import '../../models/search_results.dart'; import 'package:otzaria/utils/text_manipulation.dart' as utils; class TextFileSearchScreen extends StatefulWidget { diff --git a/lib/screens/full_text_search/tantivy_full_text_search.dart b/lib/screens/full_text_search/tantivy_full_text_search.dart new file mode 100644 index 000000000..fb3e8e448 --- /dev/null +++ b/lib/screens/full_text_search/tantivy_full_text_search.dart @@ -0,0 +1,270 @@ +import 'dart:async'; +import 'package:flutter/material.dart'; +import 'package:flutter_html/flutter_html.dart'; +import 'package:otzaria/data/data_providers/tantivy_data_provider.dart'; +import 'package:otzaria/models/app_model.dart'; +import 'package:otzaria/models/books.dart'; +import 'package:otzaria/models/tabs.dart'; +import 'package:otzaria/utils/text_manipulation.dart'; +import 'package:otzaria/screens/full_text_search/full_text_left_pane.dart'; +import 'package:provider/provider.dart'; + +class TantivyFullTextSearch extends StatefulWidget { + final SearchingTab tab; + const TantivyFullTextSearch({Key? key, required this.tab}) : super(key: key); + @override + State createState() => _TantivyFullTextSearchState(); +} + +class _TantivyFullTextSearchState extends State { + ValueNotifier isLeftPaneOpen = ValueNotifier(false); + + @override + void initState() { + super.initState(); + () async { + widget.tab.booksToSearch.value = + (await context.read().library).getAllBooks().toSet(); + }(); + widget.tab.aproximateSearch.addListener(() => updateResults()); + widget.tab.booksToSearch.addListener(() => updateResults()); + widget.tab.numResults.addListener(() => updateResults()); + widget.tab.queryController.addListener(() => updateResults()); + } + + @override + void dispose() { + widget.tab.aproximateSearch.removeListener(() => updateResults()); + widget.tab.booksToSearch.removeListener(() => updateResults()); + widget.tab.numResults.removeListener(() => updateResults()); + widget.tab.queryController.removeListener(() => updateResults()); + super.dispose(); + } + + void updateResults() { + setState(() { + if (widget.tab.queryController.text.isEmpty) { + widget.tab.results = Future.value([]); + } else { + final booksToSearch = + widget.tab.booksToSearch.value.map((e) => e.title).toList(); + if (!widget.tab.aproximateSearch.value) { + widget.tab.results = TantivyDataProvider.instance.searchTexts( + '"${widget.tab.queryController.text.replaceAll('"', '\\"')}"', + booksToSearch, + widget.tab.numResults.value); + } else { + widget.tab.results = TantivyDataProvider.instance.searchTexts( + widget.tab.queryController.text, + booksToSearch, + widget.tab.numResults.value); + } + } + }); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + body: ValueListenableBuilder( + valueListenable: isLeftPaneOpen, + builder: (context, value, child) { + return Row( + children: [ + !isLeftPaneOpen.value + ? SizedBox.shrink() + : Column( + children: [ + Padding( + padding: const EdgeInsets.fromLTRB(0, 0, 8, 0), + child: IconButton( + icon: const Icon(Icons.menu), + onPressed: () { + isLeftPaneOpen.value = !isLeftPaneOpen.value; + }, + ), + ), + Expanded(child: SizedBox.shrink()), + ], + ), + AnimatedSize( + duration: const Duration(milliseconds: 300), + child: SizedBox( + width: isLeftPaneOpen.value ? 350 : 0, + child: FullTextLeftPane(tab: widget.tab), + )), + NotificationListener( + onNotification: (scrollNotification) { + Future.microtask(() { + isLeftPaneOpen.value = false; + }); + return false; // Don't block the notification + }, + child: Expanded( + child: Column( + children: [ + Row( + children: [ + isLeftPaneOpen.value + ? SizedBox.shrink() + : Padding( + padding: + const EdgeInsets.fromLTRB(0, 0, 8, 0), + child: IconButton( + icon: const Icon(Icons.menu), + onPressed: () { + isLeftPaneOpen.value = + !isLeftPaneOpen.value; + }, + ), + ), + Expanded( + child: Padding( + padding: + const EdgeInsets.fromLTRB(60, 5, 60, 10), + child: TextField( + autofocus: true, + controller: widget.tab.queryController, + onChanged: (e) => updateResults(), + decoration: InputDecoration( + hintText: "חפש כאן..", + suffixIcon: IconButton( + icon: const Icon(Icons.clear), + onPressed: () { + widget.tab.queryController.clear(); + updateResults(); + }, + ), + ), + ), + ), + ), + ], + ), + Expanded( + child: FutureBuilder( + future: widget.tab.results, + builder: (context, snapshot) { + if (snapshot.connectionState == + ConnectionState.waiting) { + return const Center( + child: CircularProgressIndicator()); + } + if (snapshot.hasError) { + return Center( + child: Text('Error: ${snapshot.error}')); + } + if (snapshot.data!.isEmpty) { + return const Center( + child: Text('אין תוצאות')); + } + return Column( + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: Center( + child: Text( + '${snapshot.data!.length} תוצאות', + ), + ), + ), + Expanded( + child: ListView.builder( + shrinkWrap: true, + itemCount: snapshot.data!.length, + itemBuilder: (context, index) { + return ListTile( + onTap: () { + if (snapshot.data![index].isPdf) { + context + .read() + .openTab( + PdfBookTab( + PdfBook( + title: snapshot + .data![ + index] + .title, + path: snapshot + .data![ + index] + .filePath), + snapshot + .data![ + index] + .segment + .toInt() + + 1), + index: snapshot + .data![index] + .segment + .toInt() + + 1); + } else { + context + .read() + .openTab( + TextBookTab( + book: TextBook( + title: snapshot + .data![index] + .title, + ), + index: snapshot + .data![index] + .segment + .toInt(), + searchText: widget + .tab + .queryController + .text), + ); + } + }, + title: snapshot.data![index].isPdf + ? Text(snapshot + .data![index].title + + ' עמוד ${snapshot.data![index].segment.toInt() + 1}') + : FutureBuilder( + future: refFromIndex( + snapshot.data![index] + .segment + .toInt(), + TextBook( + title: snapshot + .data![ + index] + .title) + .tableOfContents), + builder: (context, ref) { + if (!ref.hasData) { + return Text( + '${snapshot.data![index].title} ...'); + } + return Text( + ref.data!, + ); + }), + subtitle: Html( + data: highLight( + snapshot.data![index].text, + widget.tab.queryController + .text)), + ); + }, + ), + ), + ], + ); + }), + ) + ], + ), + ), + ), + ], + ); + }), + ); + } +} diff --git a/lib/screens/library_browser.dart b/lib/screens/library_browser.dart index 957542a28..23453c3d3 100644 --- a/lib/screens/library_browser.dart +++ b/lib/screens/library_browser.dart @@ -1,6 +1,5 @@ import 'dart:math'; -import 'package:filter_list/filter_list.dart'; import 'package:flutter/material.dart'; import 'package:flutter_settings_screens/flutter_settings_screens.dart'; import 'package:otzaria/models/app_model.dart'; @@ -9,6 +8,8 @@ import 'package:otzaria/models/library.dart'; import 'package:otzaria/utils/daf_yomi_helper.dart'; import 'package:otzaria/utils/extraction.dart'; import 'package:otzaria/widgets/daf_yomi.dart'; +import 'package:otzaria/widgets/filter_list/src/filter_list_dialog.dart'; +import 'package:otzaria/widgets/filter_list/src/theme/filter_list_theme.dart'; import 'package:otzaria/widgets/grid_items.dart'; import 'package:otzaria/widgets/otzar_book_dialog.dart'; import 'package:provider/provider.dart'; @@ -197,7 +198,7 @@ class _LibraryBrowserState extends State : null, fontSize: 11, ), - labelPadding: EdgeInsets.all(0), + labelPadding: const EdgeInsets.all(0), ), ), ); diff --git a/lib/screens/main_window_screen.dart b/lib/screens/main_window_screen.dart index aa271701c..ff164cb50 100644 --- a/lib/screens/main_window_screen.dart +++ b/lib/screens/main_window_screen.dart @@ -1,8 +1,9 @@ import 'package:flutter/material.dart'; import 'package:flutter_settings_screens/flutter_settings_screens.dart'; import 'package:otzaria/models/app_model.dart'; -import 'package:otzaria/screens/favoriets.dart'; -import 'package:otzaria/screens/reading_screen.dart'; +import 'package:otzaria/screens/favorites/favoriets.dart'; +import 'package:otzaria/screens/find_ref_screen.dart'; +import 'package:otzaria/screens/reading/reading_screen.dart'; //imports from otzaria import 'package:otzaria/screens/library_browser.dart'; @@ -88,6 +89,10 @@ class MainWindowScreenState extends State icon: Icon(Icons.library_books), label: Text('ספרייה'), ), + const NavigationRailDestination( + icon: Icon(Icons.auto_stories_rounded), + label: Text('איתור'), + ), const NavigationRailDestination( icon: Icon(Icons.menu_book), label: Text('עיון'), @@ -104,7 +109,7 @@ class MainWindowScreenState extends State icon: const Icon(Icons.settings), label: const Text('הגדרות'), padding: EdgeInsets.only( - top: constraints.maxHeight - 340), + top: constraints.maxHeight - 410), ), ], selectedIndex: appModel.currentView.value.index, @@ -113,10 +118,12 @@ class MainWindowScreenState extends State pageController = PageController( initialPage: index, keepPage: true); switch (index) { - case 2: + case 3: appModel.openNewSearchTab(); case 0: appModel.bookLocatorFocusNode.requestFocus(); + case 1: + appModel.findReferenceFocusNode.requestFocus(); } setState(() {}); }), @@ -133,6 +140,7 @@ class MainWindowScreenState extends State controller: pageController, children: const [ LibraryBrowser(), + FindRefScreen(), ReadingScreen(), SizedBox.shrink(), FavouritesScreen(), @@ -151,6 +159,7 @@ class MainWindowScreenState extends State controller: pageController, children: const [ LibraryBrowser(), + FindRefScreen(), ReadingScreen(), SizedBox.shrink(), FavouritesScreen(), @@ -165,6 +174,10 @@ class MainWindowScreenState extends State icon: Icon(Icons.library_books), label: 'ספרייה', ), + NavigationDestination( + icon: Icon(Icons.auto_stories_rounded), + label: 'איתור', + ), NavigationDestination( icon: Icon(Icons.menu_book), label: 'עיון', @@ -189,7 +202,7 @@ class MainWindowScreenState extends State pageController = PageController( initialPage: index, keepPage: true); switch (index) { - case 2: + case 3: appModel.openNewSearchTab(); } }); diff --git a/lib/screens/pdf_book_screen.dart b/lib/screens/reading/pdf/pdf_book_screen.dart similarity index 99% rename from lib/screens/pdf_book_screen.dart rename to lib/screens/reading/pdf/pdf_book_screen.dart index 9fa71075d..bf880c647 100644 --- a/lib/screens/pdf_book_screen.dart +++ b/lib/screens/reading/pdf/pdf_book_screen.dart @@ -7,7 +7,7 @@ import 'package:provider/provider.dart'; import 'pdf_search_screen.dart'; import 'package:url_launcher/url_launcher.dart'; import 'pdf_outlines_screen.dart'; -import '../widgets/password_dialog.dart'; +import '../../../widgets/password_dialog.dart'; import 'pdf_thumbnails_screen.dart'; import 'package:otzaria/models/tabs.dart'; import 'package:printing/printing.dart'; diff --git a/lib/screens/pdf_outlines_screen.dart b/lib/screens/reading/pdf/pdf_outlines_screen.dart similarity index 100% rename from lib/screens/pdf_outlines_screen.dart rename to lib/screens/reading/pdf/pdf_outlines_screen.dart diff --git a/lib/screens/pdf_search_screen.dart b/lib/screens/reading/pdf/pdf_search_screen.dart similarity index 100% rename from lib/screens/pdf_search_screen.dart rename to lib/screens/reading/pdf/pdf_search_screen.dart diff --git a/lib/screens/pdf_thumbnails_screen.dart b/lib/screens/reading/pdf/pdf_thumbnails_screen.dart similarity index 100% rename from lib/screens/pdf_thumbnails_screen.dart rename to lib/screens/reading/pdf/pdf_thumbnails_screen.dart diff --git a/lib/screens/reading_screen.dart b/lib/screens/reading/reading_screen.dart similarity index 96% rename from lib/screens/reading_screen.dart rename to lib/screens/reading/reading_screen.dart index 6d4c8270f..e9979a0ea 100644 --- a/lib/screens/reading_screen.dart +++ b/lib/screens/reading/reading_screen.dart @@ -2,9 +2,9 @@ import 'dart:math'; import 'package:flutter/material.dart'; import 'package:otzaria/models/app_model.dart'; import 'package:otzaria/models/tabs.dart'; -import 'package:otzaria/screens/full_text_search_screen.dart'; -import 'package:otzaria/screens/pdf_book_screen.dart'; -import 'package:otzaria/screens/text_book_screen.dart'; +import 'package:otzaria/screens/full_text_search/full_text_search_screen.dart'; +import 'package:otzaria/screens/reading/pdf/pdf_book_screen.dart'; +import 'package:otzaria/screens/reading/text/text_book_screen.dart'; import 'package:otzaria/utils/calendar.dart'; import 'package:provider/provider.dart'; import 'package:flutter_context_menu/flutter_context_menu.dart'; @@ -35,9 +35,9 @@ class _ReadingScreenState extends State data: tab.text, ); } else if (tab is SearchingTab) { - return TextFileSearchScreen( + return FullTextSearchScreen( + tab: tab, openBookCallback: appModel.openTab, - searcher: tab.searcher, ); } return const SizedBox.shrink(); @@ -141,7 +141,7 @@ class _ReadingScreenState extends State 20, 10, 20, 15), child: Text( tab is SearchingTab - ? '${tab.title}: ${tab.searcher.queryController.text}' + ? '${tab.title}: ${tab.queryController.text}' : tab.title, style: TextStyle( fontSize: 14, @@ -243,9 +243,9 @@ class _ReadingScreenState extends State data: tab.text, ); } else if (tab is SearchingTab) { - return TextFileSearchScreen( + return FullTextSearchScreen( + tab: tab, openBookCallback: appModel.openTab, - searcher: tab.searcher, ); } return const SizedBox.shrink(); diff --git a/lib/screens/combined_book_screen.dart b/lib/screens/reading/text/combined_book_screen.dart similarity index 94% rename from lib/screens/combined_book_screen.dart rename to lib/screens/reading/text/combined_book_screen.dart index e5debbbae..f38a94238 100644 --- a/lib/screens/combined_book_screen.dart +++ b/lib/screens/reading/text/combined_book_screen.dart @@ -70,10 +70,10 @@ class _CombinedViewState extends State { builder: (context, removeNikud, child) => Html( //remove nikud if needed data: removeNikud - ? highLight(removeVolwels(widget.data[index]), + ? highLight(removeVolwels('${widget.data[index]}\n'), widget.tab.searchTextController.text) - : highLight( - widget.data[index], widget.tab.searchTextController.text), + : highLight('${widget.data[index]}\n', + widget.tab.searchTextController.text), style: { 'body': Style( fontSize: FontSize(widget.textSize), diff --git a/lib/screens/commentators_list_screen.dart b/lib/screens/reading/text/commentators_list_screen.dart similarity index 97% rename from lib/screens/commentators_list_screen.dart rename to lib/screens/reading/text/commentators_list_screen.dart index 399ac4a07..eddc0a217 100644 --- a/lib/screens/commentators_list_screen.dart +++ b/lib/screens/reading/text/commentators_list_screen.dart @@ -1,7 +1,8 @@ -import 'package:filter_list/filter_list.dart'; import 'package:flutter/material.dart'; import 'package:otzaria/models/tabs.dart'; import 'package:otzaria/utils/text_manipulation.dart'; +import 'package:otzaria/widgets/filter_list/src/filter_list_dialog.dart'; +import 'package:otzaria/widgets/filter_list/src/theme/filter_list_theme.dart'; class CommentatorsListView extends StatefulWidget { final TextBookTab tab; diff --git a/lib/screens/links_screen.dart b/lib/screens/reading/text/links_screen.dart similarity index 100% rename from lib/screens/links_screen.dart rename to lib/screens/reading/text/links_screen.dart diff --git a/lib/screens/simple_book_view.dart b/lib/screens/reading/text/simple_book_view.dart similarity index 94% rename from lib/screens/simple_book_view.dart rename to lib/screens/reading/text/simple_book_view.dart index d848b45bf..cefab9838 100644 --- a/lib/screens/simple_book_view.dart +++ b/lib/screens/reading/text/simple_book_view.dart @@ -53,9 +53,9 @@ class _SimpleBookViewState extends State { child: Html( //remove nikud if needed data: removeNikud - ? highLight(removeVolwels(widget.data[index]), + ? highLight(removeVolwels('${widget.data[index]}\n'), widget.tab.searchTextController.text) - : highLight(widget.data[index], + : highLight('${widget.data[index]}\n', widget.tab.searchTextController.text), style: { 'body': Style( diff --git a/lib/screens/splited_view_screen.dart b/lib/screens/reading/text/splited_view_screen.dart similarity index 93% rename from lib/screens/splited_view_screen.dart rename to lib/screens/reading/text/splited_view_screen.dart index a1e99ee03..b229af0e8 100644 --- a/lib/screens/splited_view_screen.dart +++ b/lib/screens/reading/text/splited_view_screen.dart @@ -1,8 +1,8 @@ import 'package:flutter/material.dart'; -import 'package:otzaria/screens/text_book_screen.dart'; +import 'package:otzaria/screens/reading/text/text_book_screen.dart'; import 'package:multi_split_view/multi_split_view.dart'; import 'package:otzaria/widgets/commentary_list.dart'; -import 'package:otzaria/screens/simple_book_view.dart'; +import 'package:otzaria/screens/reading/text/simple_book_view.dart'; class SplitedViewScreen extends StatelessWidget { const SplitedViewScreen({ diff --git a/lib/screens/text_book_screen.dart b/lib/screens/reading/text/text_book_screen.dart similarity index 98% rename from lib/screens/text_book_screen.dart rename to lib/screens/reading/text/text_book_screen.dart index fb7352627..38a5b9bdb 100644 --- a/lib/screens/text_book_screen.dart +++ b/lib/screens/reading/text/text_book_screen.dart @@ -1,14 +1,14 @@ import 'package:flutter/material.dart'; import 'package:flutter_context_menu/flutter_context_menu.dart'; import 'package:otzaria/models/app_model.dart'; -import 'package:otzaria/screens/combined_book_screen.dart'; +import 'package:otzaria/screens/reading/text/combined_book_screen.dart'; import 'package:otzaria/screens/printing_screen.dart'; -import 'package:otzaria/screens/splited_view_screen.dart'; +import 'package:otzaria/screens/reading/text/splited_view_screen.dart'; import 'package:otzaria/utils/daf_yomi_helper.dart'; import 'package:provider/provider.dart'; -import 'package:otzaria/screens/text_book_search_screen.dart'; +import 'package:otzaria/screens/reading/text/text_book_search_screen.dart'; import 'dart:io'; -import 'package:otzaria/screens/toc_navigator_screen.dart'; +import 'package:otzaria/screens/reading/text/toc_navigator_screen.dart'; import 'dart:math'; import 'links_screen.dart'; import 'commentators_list_screen.dart'; diff --git a/lib/screens/text_book_search_screen.dart b/lib/screens/reading/text/text_book_search_screen.dart similarity index 68% rename from lib/screens/text_book_search_screen.dart rename to lib/screens/reading/text/text_book_search_screen.dart index 6d24dee2e..dbdf891be 100644 --- a/lib/screens/text_book_search_screen.dart +++ b/lib/screens/reading/text/text_book_search_screen.dart @@ -80,34 +80,35 @@ class TextBookSearchViewState extends State ), ), ), - SizedBox.fromSize( - size: const Size.fromHeight(400), - child: ListView.builder( - itemCount: searchResults.length, - itemBuilder: (context, index) { - if (searchResults.isNotEmpty) { - final result = searchResults[index]; - return ListTile( - title: Text( - result.address, - style: const TextStyle(fontWeight: FontWeight.bold), - ), - subtitle: SearchHighlightText(result.snippet, - searchText: result.query), - onTap: () { - widget.scrollControler.scrollTo( - index: result.index, - duration: const Duration(milliseconds: 250), - curve: Curves.ease, - ); - if (Platform.isAndroid) { - widget.closeLeftPaneCallback(); - } - }); - } else { - return const SizedBox.shrink(); - } - })) + Expanded( + child: ListView.builder( + shrinkWrap: true, + itemCount: searchResults.length, + itemBuilder: (context, index) { + if (searchResults.isNotEmpty) { + final result = searchResults[index]; + return ListTile( + title: Text( + result.address, + style: const TextStyle(fontWeight: FontWeight.bold), + ), + subtitle: SearchHighlightText(result.snippet, + searchText: result.query), + onTap: () { + widget.scrollControler.scrollTo( + index: result.index, + duration: const Duration(milliseconds: 250), + curve: Curves.ease, + ); + if (Platform.isAndroid) { + widget.closeLeftPaneCallback(); + } + }); + } else { + return const SizedBox.shrink(); + } + }), + ) ]); } diff --git a/lib/screens/toc_navigator_screen.dart b/lib/screens/reading/text/toc_navigator_screen.dart similarity index 100% rename from lib/screens/toc_navigator_screen.dart rename to lib/screens/reading/text/toc_navigator_screen.dart diff --git a/lib/screens/ref_indexing_screen.dart b/lib/screens/ref_indexing_screen.dart new file mode 100644 index 000000000..cc6cc692c --- /dev/null +++ b/lib/screens/ref_indexing_screen.dart @@ -0,0 +1,99 @@ +import 'package:flutter/material.dart'; +import 'package:otzaria/data/data_providers/isar_data_provider.dart'; +import 'package:otzaria/models/app_model.dart'; +import 'package:provider/provider.dart'; + +class RefIndexingScreen extends StatefulWidget { + const RefIndexingScreen({Key? key}) : super(key: key); + + @override + State createState() => _RefIndexingScreenState(); +} + +class _RefIndexingScreenState extends State { + late AppModel appModel; + + @override + void initState() { + appModel = Provider.of(context, listen: false); + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Center(child: Text('אינדקס מקורות')), + ), + body: Center( + child: Column( + children: [ + Center( + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 30), + child: TextButton( + onPressed: () async { + final result = showDialog( + context: context, + builder: (context) => AlertDialog( + content: const Text( + 'האם ברצונך ליצור אינדקס מקורות? הדבר יאפס את האינדקס הקיים ועלול לקחת זמן ארוך מאד.'), + actions: [ + ElevatedButton( + child: const Text('ביטול'), + onPressed: () { + Navigator.pop(context, false); + }, + ), + TextButton( + child: const Text('אישור'), + onPressed: () { + Navigator.pop(context, true); + }, + ), + ], + )); + if (await result == true) { + appModel.createRefsFromLibrary(0); + } + }, + child: const Text( + 'יצירת אינדקס מקורות', + ), + ), + ), + ), + ValueListenableBuilder( + valueListenable: IsarDataProvider.instance.refsNumOfbooksDone, + builder: (context, valueDone, child) { + if (valueDone == null) { + return const SizedBox.shrink(); + } + return ValueListenableBuilder( + valueListenable: + IsarDataProvider.instance.refsNumOfbooksTotal, + builder: (context, valueTotal, child) { + if (valueTotal == null) { + return const SizedBox.shrink(); + } + return Padding( + padding: const EdgeInsets.symmetric( + horizontal: 20, vertical: 50), + child: Column( + children: [ + LinearProgressIndicator( + borderRadius: BorderRadius.circular(20), + value: valueDone / valueTotal, + ), + Text(' $valueTotal / $valueDone'), + ], + ), + ); + }); + }), + ], + ), + ), + ); + } +} diff --git a/lib/screens/settings_screen.dart b/lib/screens/settings_screen.dart index 93644134c..a99cf1354 100644 --- a/lib/screens/settings_screen.dart +++ b/lib/screens/settings_screen.dart @@ -5,7 +5,6 @@ import 'dart:io'; import 'package:otzaria/models/app_model.dart'; import 'package:provider/provider.dart'; import 'package:package_info_plus/package_info_plus.dart'; -import 'package:package_info_plus/package_info_plus.dart'; class MySettingsScreen extends StatefulWidget { const MySettingsScreen({ @@ -139,12 +138,19 @@ class _MySettingsScreenState extends State { titleTextStyle: TextStyle(fontSize: 25), children: [ DropDownSettingsTile( - selected: 'ctrl+o', + selected: 'ctrl+l', settingKey: 'key-shortcut-open-library-browser', title: 'ספרייה', values: shortcuctsList, leading: Icon(Icons.library_books), ), + DropDownSettingsTile( + selected: 'ctrl+o', + settingKey: 'key-shortcut-open-find-ref', + title: 'איתור', + values: shortcuctsList, + leading: Icon(Icons.auto_stories_rounded), + ), DropDownSettingsTile( selected: 'ctrl+r', settingKey: 'key-shortcut-open-reading-screen', @@ -197,6 +203,19 @@ class _MySettingsScreenState extends State { leading: Icon(Icons.vertical_split), defaultValue: false, ), + SwitchSettingsTile( + settingKey: 'key-use-fast-search', + title: 'חיפוש מהיר באמצעות אינדקס', + enabledLabel: + 'החיפוש יהיה מהיר יותר, נדרש ליצור אינדקס', + disabledLabel: 'החיפוש יהיה איטי יותר, לא נדרש אינדקס', + leading: Icon(Icons.search), + defaultValue: true, + onChange: (value) => context + .read() + .useFastSearch + .value = value, + ), SwitchSettingsTile( settingKey: 'key-show-external-books', title: 'איתור ספרים באתרים חיצוניים', diff --git a/lib/screens/temp.dart b/lib/screens/temp.dart deleted file mode 100644 index 051236b30..000000000 --- a/lib/screens/temp.dart +++ /dev/null @@ -1,329 +0,0 @@ -// import 'dart:isolate'; -// import 'dart:math'; -// import 'package:flutter/material.dart'; -// import 'package:fuzzywuzzy/fuzzywuzzy.dart'; -// import 'package:otzaria/models/app_model.dart'; -// import 'package:otzaria/models/books.dart'; -// import 'package:otzaria/models/library.dart'; -// import 'package:otzaria/widgets/daf_yomi.dart'; -// import 'package:otzaria/widgets/grid_items.dart'; -// import 'package:provider/provider.dart'; -// import 'package:otzaria/widgets/otzar_book_dialog.dart'; - -// class LibraryBrowser extends StatefulWidget { -// const LibraryBrowser({Key? key}) : super(key: key); - -// @override -// State createState() => _LibraryBrowserState(); -// } - -// class _LibraryBrowserState extends State { -// late Category currentTopCategory; -// TextEditingController searchController = TextEditingController(); - -// @override -// void initState() { -// super.initState(); -// WidgetsFlutterBinding.ensureInitialized(); -// currentTopCategory = Provider.of(context, listen: false).library; -// } - -// @override -// void dispose() { -// searchController.dispose(); -// super.dispose(); -// } - -// @override -// Widget build(BuildContext context) { -// return Scaffold( -// appBar: AppBar( -// title: Row( -// mainAxisSize: MainAxisSize.min, -// children: [ -// Align( -// alignment: Alignment.centerRight, -// child: IconButton( -// icon: const Icon(Icons.home), -// tooltip: 'חזרה לתיקיה הראשית', -// onPressed: () => setState(() { -// searchController.clear(); -// currentTopCategory = -// Provider.of(context, listen: false).library; -// }), -// ), -// ), -// Expanded( -// child: Center( -// child: Text(currentTopCategory.title, -// style: TextStyle( -// color: Theme.of(context).colorScheme.secondary, -// fontSize: 20, -// fontWeight: FontWeight.bold, -// ))), -// ), -// DafYomi() -// ], -// ), -// leading: IconButton( -// icon: const Icon(Icons.arrow_upward), -// tooltip: 'חזרה לתיקיה הקודמת', -// onPressed: () => setState(() { -// searchController.clear(); -// currentTopCategory = currentTopCategory.parent!.parent!; -// }), -// ), -// ), -// body: Column( -// children: [ -// buildSearchBar(), -// Expanded( -// child: ListView(children: [ -// currentTopCategory.title == 'ספריית אוצריא' -// ? MyGridView( -// items: currentTopCategory.subCategories.map((element) { -// return CategoryGridItem( -// category: element, -// onCategoryClickCallback: () { -// _openCategory(element); -// }, -// ); -// }).toList()) -// : Column( -// children: [ -// MyGridView( -// items: currentTopCategory.books.map((element) { -// return BookGridItem( -// book: element, -// onBookClickCallback: () { -// Provider.of(context, listen: false) -// .openBook(element, 0, openLeftPane: true); -// }, -// ); -// }).toList()), - -// } - -// Widget buildSearchBar() { -// return Padding( -// padding: const EdgeInsets.all(8.0), -// child: Row( -// children: [ -// Expanded( -// child: TextField( -// focusNode: Provider.of(context).bookLocatorFocusNode, -// autofocus: true, -// controller: searchController, -// decoration: InputDecoration( -// constraints: const BoxConstraints(maxWidth: 400), -// prefixIcon: const Icon(Icons.search), -// suffixIcon: IconButton( -// onPressed: () => searchController.clear(), -// icon: const Icon(Icons.cancel)), -// border: const OutlineInputBorder( -// borderRadius: BorderRadius.all(Radius.circular(8.0))), -// hintText: 'איתור ספר ב${currentTopCategory.title}', -// ), -// onChanged: (value) {}), -// ), -// IconButton( -// icon: Icon(Icons.filter_list), -// onPressed: () => _showFilterDialog(), -// ), -// ], -// ), -// ); -// } - -// void _showFilterDialog() { -// showDialog( -// context: context, -// builder: (BuildContext context) { -// return StatefulBuilder(builder: (context, setState) { -// return AlertDialog( -// content: Column( -// mainAxisSize: MainAxisSize.min, -// children: [ -// CheckboxListTile( -// title: Text('הצג ספרים מאוצר החכמה'), -// value: -// Provider.of(context).showOtzarHachochma.value, -// onChanged: (bool? value) { -// setState(() { -// Provider.of(context, listen: false) -// .showOtzarHachochma -// .value = value ?? false; -// }); -// }, -// ), -// CheckboxListTile( -// title: Text('הצג ספרים מהיברובוקס'), -// value: Provider.of(context).showHebrewBooks.value, -// onChanged: (bool? value) { -// setState(() { -// Provider.of(context, listen: false) -// .showHebrewBooks -// .value = value ?? false; -// }); -// }, -// ), -// ], -// ), -// ); -// }); -// }, -// ); -// } - -// Future> getFilteredBooks() async { -// final query = searchController.text.trim().toLowerCase(); -// final queryWords = query.split(RegExp(r'\s+')); - -// List localEntries = -// currentTopCategory.getAllBooksAndCategories().where((element) { -// final title = element.title.toLowerCase(); -// return queryWords.every((word) => title.contains(word)); -// }).toList(); - -// List otzarEntries = []; -// if (Provider.of(context, listen: false) -// .showOtzarHachochma -// .value) { -// final otzarBooksfinal = -// await Provider.of(context, listen: false).otzarBooks; -// otzarEntries = otzarBooksfinal.where((book) { -// final title = book.title.toLowerCase(); -// return queryWords.every((word) => title.contains(word)); -// }).toList(); -// } - -// List allEntries = [...localEntries, ...otzarEntries]; -// allEntries = await sortEntries(allEntries, query); - -// List items = []; - -// for (final entry in allEntries.take(50)) { -// if (entry is Category) { -// items.add( -// CategoryGridItem( -// category: entry, -// onCategoryClickCallback: () => _openCategory(entry), -// ), -// ); -// } else if (entry is Book) { -// if (entry is ExternalBook) { -// items.add( -// BookGridItem( -// book: entry, -// onBookClickCallback: () => _openOtzarBook(entry), -// ), -// ); -// } else { -// items.add( -// BookGridItem( -// book: entry, -// showTopics: true, -// onBookClickCallback: () { -// Provider.of(context, listen: false) -// .openBook(entry, 0, openLeftPane: true); -// }, -// ), -// ); -// } -// } -// } -// return items; -// } - -// Future> sortEntries(List entries, String query) async { -// return await Isolate.run(() { -// entries.sort((a, b) { -// final titleA = a is Book ? a.title : ''; -// final titleB = b is Book ? b.title : ''; -// final scoreA = ratio(query, titleA.toLowerCase()); -// final scoreB = ratio(query, titleB.toLowerCase()); -// return scoreB.compareTo(scoreA); -// }); -// return entries; -// }); -// } - -// void _openOtzarBook(ExternalBook book) { -// showDialog( -// context: context, -// builder: (BuildContext context) { -// return OtzarBookDialog(book: book); -// }, -// ); -// } - -// // Future> getGrids(Category category) async { -// // List items = []; -// // category.books.sort( -// // (a, b) => a.order.compareTo(b.order), -// // ); -// // category.subCategories.sort( -// // (a, b) => a.order.compareTo(b.order), -// // ); -// // if (true) { -// // Future> books = () async { -// // List books = []; -// // for (Book book in category.books) { -// // books.add( -// // BookGridItem( -// // book: book, -// // onBookClickCallback: () { -// // Provider.of(context, listen: false) -// // .openBook(book, 0, openLeftPane: true); -// // }), -// // ); -// // } -// // return books; -// // }(); -// // items.add(MyGridView(items: books)); - -// // for (Category subCategory in category.subCategories) { -// // subCategory.books.sort((a, b) => a.order.compareTo(b.order)); -// // subCategory.subCategories.sort((a, b) => a.order.compareTo(b.order)); - -// // items.add(Center(child: HeaderItem(category: subCategory))); -// // items.add(MyGridView(items: _getGridItems(subCategory))); -// // } -// // } else { -// // items.add(MyGridView( -// // items: _getGridItems(currentTopCategory), -// // )); -// // } - -// // return items; -// // } - -// // Future> _getGridItems(Category category) async { -// // List items = []; -// // for (Book book in category.books) { -// // items.add( -// // BookGridItem( -// // book: book, -// // onBookClickCallback: () { -// // Provider.of(context, listen: false) -// // .openBook(book, 0, openLeftPane: true); -// // }), -// // ); -// // } -// // for (Category subCategory in category.subCategories) { -// // items.add( -// // CategoryGridItem( -// // category: subCategory, -// // onCategoryClickCallback: () => _openCategory(subCategory), -// // ), -// // ); -// // } - -// // return items; -// // } - -// void _openCategory(Category category) { -// currentTopCategory = category; -// setState(() {}); -// } -// } diff --git a/lib/utils/ref_helper.dart b/lib/utils/ref_helper.dart new file mode 100644 index 000000000..30f412c50 --- /dev/null +++ b/lib/utils/ref_helper.dart @@ -0,0 +1,72 @@ +import 'package:isar/isar.dart'; +import 'package:otzaria/models/books.dart'; +import 'package:otzaria/models/isar_collections/ref.dart'; +import 'package:otzaria/models/library.dart'; +import 'package:pdfrx/pdfrx.dart'; + +Future createRefsFromLibrary( + Library library, Isar isar, int startIndex) async { + int i = 0; + final allBooks = library.getAllBooks().whereType().skip(startIndex); + for (TextBook book in allBooks) { + print('Creating refs for ${book.title} (${i++}/${allBooks.length})'); + List refs = []; + final List toc = await book.tableOfContents; + //get all TocEntries recursively + List alltocs = []; + + void searchToc(List entries) { + for (final TocEntry entry in entries) { + alltocs.add(entry); + for (final child in entry.children) { + child.text = '${entry.text},${child.text}'; + } + searchToc(entry.children); + } + } + + searchToc(toc); + for (final TocEntry entry in alltocs) { + final ref = Ref( + id: isar.refs.autoIncrement(), + ref: entry.text + .replaceAll('"', '') + .replaceAll("'", '') + .replaceAll('״', ''), + bookTitle: book.title, + index: entry.index, + pdfBook: false); + refs.add(ref); + } + isar.write((isar) => isar.refs.putAll(refs)); + print('Done creating refs for ${book.title} '); + } + + for (PdfBook book in library.getAllBooks().whereType()) { + final List outlines = await PdfDocument.openFile(book.path) + .then((value) => value.loadOutline()); + + //get all TocEntries recursively + List alloutlines = []; + + void searchOutline(List entries) { + for (final PdfOutlineNode entry in entries) { + alloutlines.add(entry); + searchOutline(entry.children); + } + } + + searchOutline(outlines); + + for (final PdfOutlineNode entry in alloutlines) { + final ref = Ref( + id: isar.refs.autoIncrement(), + ref: entry.title.replaceAll('\n', ''), + bookTitle: book.title, + index: entry.dest?.pageNumber ?? 0, + pdfBook: true); + print('Adding Pdf ref: ${ref.ref}'); + isar.write((isar) => isar.refs.put(ref)); + } + } +} diff --git a/lib/utils/text_manipulation.dart b/lib/utils/text_manipulation.dart index d76cf0bb9..52837d2e6 100644 --- a/lib/utils/text_manipulation.dart +++ b/lib/utils/text_manipulation.dart @@ -1,6 +1,6 @@ import 'dart:io'; -import 'package:otzaria/data/file_system_data_provider.dart'; +import 'package:otzaria/data/data_providers/file_system_data_provider.dart'; import 'package:otzaria/models/books.dart'; String stripHtmlIfNeeded(String text) { @@ -56,3 +56,26 @@ Future refFromIndex( bool hasTopic(String title, String topic) { return FileSystemData.instance.titleToPath[title]?.contains(topic) ?? false; } + +String paraphrase(String text) { + Map paraphrases = { + '־': ' ', + 'שוע': 'שולחן ערוך', + 'שך': 'שפתי כהן', + 'טז': 'טורי זהב', + 'חומ': 'חושן משפט', + 'יוד': 'יורה דעה', + 'אהעז': 'אבן העזר', + 'אוח': 'אורח חיים', + 'בק': 'בבא קמא', + 'במ': 'בבא מציעא', + 'בב': 'בבא בתרא', + 'ראבד': 'ראב"ד', + 'בח': 'ב"ח' + }; + for (var key in paraphrases.keys) { + text = text.replaceAll(key, paraphrases[key] ?? key); + } + + return text; +} diff --git a/packages/filter_list-1.0.3/lib/src/filter_list_delegate.dart b/lib/widgets/filter_list/src/filter_list_delegate.dart similarity index 98% rename from packages/filter_list-1.0.3/lib/src/filter_list_delegate.dart rename to lib/widgets/filter_list/src/filter_list_delegate.dart index d8a6b76ef..842c359c6 100644 --- a/packages/filter_list-1.0.3/lib/src/filter_list_delegate.dart +++ b/lib/widgets/filter_list/src/filter_list_delegate.dart @@ -1,7 +1,7 @@ -import 'package:filter_list/src/filter_list_dialog.dart'; -import 'package:filter_list/src/state/filter_state.dart'; -import 'package:filter_list/src/state/provider.dart'; -import 'package:filter_list/src/theme/filter_list_delegate_theme.dart'; +import 'filter_list_dialog.dart'; +import 'state/filter_state.dart'; +import 'state/provider.dart'; +import 'theme/filter_list_delegate_theme.dart'; import 'package:flutter/material.dart'; typedef SuggestionBuilder = Widget Function( diff --git a/packages/filter_list-1.0.3/lib/src/filter_list_dialog.dart b/lib/widgets/filter_list/src/filter_list_dialog.dart similarity index 96% rename from packages/filter_list-1.0.3/lib/src/filter_list_dialog.dart rename to lib/widgets/filter_list/src/filter_list_dialog.dart index 072421a02..d5977991f 100644 --- a/packages/filter_list-1.0.3/lib/src/filter_list_dialog.dart +++ b/lib/widgets/filter_list/src/filter_list_dialog.dart @@ -1,13 +1,10 @@ library filter_list; -import 'package:filter_list/src/state/filter_state.dart'; -import 'package:filter_list/src/state/provider.dart'; -import 'package:filter_list/src/theme/theme.dart'; -import 'package:filter_list/src/widget/choice_list.dart'; -import 'package:filter_list/src/widget/control_button_bar.dart'; -import 'package:filter_list/src/widget/header.dart'; +import 'state/filter_state.dart'; +import 'state/provider.dart'; +import 'theme/theme.dart'; +import 'widget/choice_list.dart'; import 'package:flutter/material.dart'; - part 'filter_list_widget.dart'; /// The [FilterListDialog.display] is a [Dialog] with some filter utilities and callbacks which helps in single/multiple selection from list of data. diff --git a/packages/filter_list-1.0.3/lib/src/filter_list_widget.dart b/lib/widgets/filter_list/src/filter_list_widget.dart similarity index 100% rename from packages/filter_list-1.0.3/lib/src/filter_list_widget.dart rename to lib/widgets/filter_list/src/filter_list_widget.dart diff --git a/packages/filter_list-1.0.3/lib/src/state/filter_state.dart b/lib/widgets/filter_list/src/state/filter_state.dart similarity index 97% rename from packages/filter_list-1.0.3/lib/src/state/filter_state.dart rename to lib/widgets/filter_list/src/state/filter_state.dart index a20b9739a..b8ebfa212 100644 --- a/packages/filter_list-1.0.3/lib/src/state/filter_state.dart +++ b/lib/widgets/filter_list/src/state/filter_state.dart @@ -1,4 +1,4 @@ -import 'package:filter_list/src/state/provider.dart'; +import 'provider.dart'; import 'package:flutter/material.dart'; class FilterState extends ListenableState { diff --git a/packages/filter_list-1.0.3/lib/src/state/provider.dart b/lib/widgets/filter_list/src/state/provider.dart similarity index 100% rename from packages/filter_list-1.0.3/lib/src/state/provider.dart rename to lib/widgets/filter_list/src/state/provider.dart diff --git a/packages/filter_list-1.0.3/lib/src/theme/choice_chip_theme.dart b/lib/widgets/filter_list/src/theme/choice_chip_theme.dart similarity index 99% rename from packages/filter_list-1.0.3/lib/src/theme/choice_chip_theme.dart rename to lib/widgets/filter_list/src/theme/choice_chip_theme.dart index 9ed9745ec..c8cf5681a 100644 --- a/packages/filter_list-1.0.3/lib/src/theme/choice_chip_theme.dart +++ b/lib/widgets/filter_list/src/theme/choice_chip_theme.dart @@ -1,4 +1,4 @@ -import 'package:filter_list/src/theme/filter_list_theme.dart'; +import 'filter_list_theme.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; diff --git a/packages/filter_list-1.0.3/lib/src/theme/contol_button_theme.dart b/lib/widgets/filter_list/src/theme/contol_button_theme.dart similarity index 99% rename from packages/filter_list-1.0.3/lib/src/theme/contol_button_theme.dart rename to lib/widgets/filter_list/src/theme/contol_button_theme.dart index 746ebca63..db9ee4ade 100644 --- a/packages/filter_list-1.0.3/lib/src/theme/contol_button_theme.dart +++ b/lib/widgets/filter_list/src/theme/contol_button_theme.dart @@ -1,4 +1,4 @@ -import 'package:filter_list/src/theme/filter_list_theme.dart'; +import 'filter_list_theme.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; diff --git a/packages/filter_list-1.0.3/lib/src/theme/control_button_bar_theme.dart b/lib/widgets/filter_list/src/theme/control_button_bar_theme.dart similarity index 99% rename from packages/filter_list-1.0.3/lib/src/theme/control_button_bar_theme.dart rename to lib/widgets/filter_list/src/theme/control_button_bar_theme.dart index 9b66896d2..452959304 100644 --- a/packages/filter_list-1.0.3/lib/src/theme/control_button_bar_theme.dart +++ b/lib/widgets/filter_list/src/theme/control_button_bar_theme.dart @@ -1,4 +1,4 @@ -import 'package:filter_list/src/theme/contol_button_theme.dart'; +import 'contol_button_theme.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; diff --git a/packages/filter_list-1.0.3/lib/src/theme/filter_list_delegate_theme.dart b/lib/widgets/filter_list/src/theme/filter_list_delegate_theme.dart similarity index 100% rename from packages/filter_list-1.0.3/lib/src/theme/filter_list_delegate_theme.dart rename to lib/widgets/filter_list/src/theme/filter_list_delegate_theme.dart diff --git a/packages/filter_list-1.0.3/lib/src/theme/filter_list_theme.dart b/lib/widgets/filter_list/src/theme/filter_list_theme.dart similarity index 97% rename from packages/filter_list-1.0.3/lib/src/theme/filter_list_theme.dart rename to lib/widgets/filter_list/src/theme/filter_list_theme.dart index 22601d85b..0901f3a97 100644 --- a/packages/filter_list-1.0.3/lib/src/theme/filter_list_theme.dart +++ b/lib/widgets/filter_list/src/theme/filter_list_theme.dart @@ -1,6 +1,6 @@ -import 'package:filter_list/src/theme/choice_chip_theme.dart'; -import 'package:filter_list/src/theme/control_button_bar_theme.dart'; -import 'package:filter_list/src/theme/header_theme.dart'; +import 'choice_chip_theme.dart'; +import 'control_button_bar_theme.dart'; +import 'header_theme.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; diff --git a/packages/filter_list-1.0.3/lib/src/theme/header_theme.dart b/lib/widgets/filter_list/src/theme/header_theme.dart similarity index 99% rename from packages/filter_list-1.0.3/lib/src/theme/header_theme.dart rename to lib/widgets/filter_list/src/theme/header_theme.dart index c47e56de1..46a477eec 100644 --- a/packages/filter_list-1.0.3/lib/src/theme/header_theme.dart +++ b/lib/widgets/filter_list/src/theme/header_theme.dart @@ -1,4 +1,4 @@ -import 'package:filter_list/src/theme/filter_list_theme.dart'; +import 'filter_list_theme.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; diff --git a/packages/filter_list-1.0.3/lib/src/theme/theme.dart b/lib/widgets/filter_list/src/theme/theme.dart similarity index 100% rename from packages/filter_list-1.0.3/lib/src/theme/theme.dart rename to lib/widgets/filter_list/src/theme/theme.dart diff --git a/packages/filter_list-1.0.3/lib/src/widget/choice_chip_widget.dart b/lib/widgets/filter_list/src/widget/choice_chip_widget.dart similarity index 94% rename from packages/filter_list-1.0.3/lib/src/widget/choice_chip_widget.dart rename to lib/widgets/filter_list/src/widget/choice_chip_widget.dart index 91ec999be..fedfb7a2f 100644 --- a/packages/filter_list-1.0.3/lib/src/widget/choice_chip_widget.dart +++ b/lib/widgets/filter_list/src/widget/choice_chip_widget.dart @@ -1,4 +1,6 @@ -import 'package:filter_list/filter_list.dart'; +import 'package:otzaria/widgets/filter_list/src/filter_list_dialog.dart'; +import 'package:otzaria/widgets/filter_list/src/theme/filter_list_theme.dart'; + import 'package:flutter/material.dart'; class ChoiceChipWidget extends StatelessWidget { diff --git a/packages/filter_list-1.0.3/lib/src/widget/choice_list.dart b/lib/widgets/filter_list/src/widget/choice_list.dart similarity index 92% rename from packages/filter_list-1.0.3/lib/src/widget/choice_list.dart rename to lib/widgets/filter_list/src/widget/choice_list.dart index b74f13a06..0721f0937 100644 --- a/packages/filter_list-1.0.3/lib/src/widget/choice_list.dart +++ b/lib/widgets/filter_list/src/widget/choice_list.dart @@ -1,7 +1,9 @@ -import 'package:filter_list/filter_list.dart'; -import 'package:filter_list/src/state/filter_state.dart'; -import 'package:filter_list/src/state/provider.dart'; -import 'package:filter_list/src/widget/choice_chip_widget.dart'; +import 'package:otzaria/widgets/filter_list/src/filter_list_dialog.dart'; +import 'package:otzaria/widgets/filter_list/src/theme/filter_list_theme.dart'; + +import '../state/filter_state.dart'; +import '../state/provider.dart'; +import 'choice_chip_widget.dart'; import 'package:flutter/material.dart'; class ChoiceList extends StatelessWidget { diff --git a/packages/filter_list-1.0.3/lib/src/widget/control_button.dart b/lib/widgets/filter_list/src/widget/control_button.dart similarity index 96% rename from packages/filter_list-1.0.3/lib/src/widget/control_button.dart rename to lib/widgets/filter_list/src/widget/control_button.dart index 7a3a3b2a0..d69a1c04e 100644 --- a/packages/filter_list-1.0.3/lib/src/widget/control_button.dart +++ b/lib/widgets/filter_list/src/widget/control_button.dart @@ -1,4 +1,4 @@ -import 'package:filter_list/src/theme/theme.dart'; +import '../theme/theme.dart'; import 'package:flutter/material.dart'; class ControlButton extends StatelessWidget { diff --git a/packages/filter_list-1.0.3/lib/src/widget/control_button_bar.dart b/lib/widgets/filter_list/src/widget/control_button_bar.dart similarity index 91% rename from packages/filter_list-1.0.3/lib/src/widget/control_button_bar.dart rename to lib/widgets/filter_list/src/widget/control_button_bar.dart index 576afcd55..8a55ebcc6 100644 --- a/packages/filter_list-1.0.3/lib/src/widget/control_button_bar.dart +++ b/lib/widgets/filter_list/src/widget/control_button_bar.dart @@ -1,8 +1,11 @@ -import 'package:filter_list/filter_list.dart'; -import 'package:filter_list/src/state/filter_state.dart'; -import 'package:filter_list/src/state/provider.dart'; +import 'package:otzaria/widgets/filter_list/src/filter_list_dialog.dart'; +import 'package:otzaria/widgets/filter_list/src/theme/control_button_bar_theme.dart'; +import 'package:otzaria/widgets/filter_list/src/theme/filter_list_theme.dart'; -import 'package:filter_list/src/widget/control_button.dart'; +import '../state/filter_state.dart'; +import '../state/provider.dart'; + +import 'control_button.dart'; import 'package:flutter/material.dart'; /// {@template control_buttons} diff --git a/packages/filter_list-1.0.3/lib/src/widget/header.dart b/lib/widgets/filter_list/src/widget/header.dart similarity index 96% rename from packages/filter_list-1.0.3/lib/src/widget/header.dart rename to lib/widgets/filter_list/src/widget/header.dart index 0f0ef4ab7..a223d8d76 100644 --- a/packages/filter_list-1.0.3/lib/src/widget/header.dart +++ b/lib/widgets/filter_list/src/widget/header.dart @@ -1,5 +1,6 @@ -import 'package:filter_list/filter_list.dart'; -import 'package:filter_list/src/widget/search_field_widget.dart'; +import 'package:otzaria/widgets/filter_list/src/theme/filter_list_theme.dart'; + +import 'search_field_widget.dart'; import 'package:flutter/material.dart'; class Header extends StatelessWidget { diff --git a/packages/filter_list-1.0.3/lib/src/widget/search_field_widget.dart b/lib/widgets/filter_list/src/widget/search_field_widget.dart similarity index 94% rename from packages/filter_list-1.0.3/lib/src/widget/search_field_widget.dart rename to lib/widgets/filter_list/src/widget/search_field_widget.dart index 5b0ed66de..0a2c27f72 100644 --- a/packages/filter_list-1.0.3/lib/src/widget/search_field_widget.dart +++ b/lib/widgets/filter_list/src/widget/search_field_widget.dart @@ -1,4 +1,4 @@ -import 'package:filter_list/src/theme/filter_list_theme.dart'; +import '../theme/filter_list_theme.dart'; import 'package:flutter/material.dart'; class SearchFieldWidget extends StatelessWidget { diff --git a/lib/widgets/keyboard_shortcuts.dart b/lib/widgets/keyboard_shortcuts.dart index f2187bcf7..61fd07068 100644 --- a/lib/widgets/keyboard_shortcuts.dart +++ b/lib/widgets/keyboard_shortcuts.dart @@ -93,36 +93,32 @@ class KeyboardShortcuts extends StatelessWidget { return Consumer( builder: (context, appModel, child) => CallbackShortcuts( bindings: { - shortcuts[Settings.getValue( - 'key-shortcut-open-library-browser') != - null - ? Settings.getValue('key-shortcut-open-library-browser') - : 'ctrl+o']!: () { + shortcuts[ + Settings.getValue('key-shortcut-open-library-browser') ?? + 'ctrl+l']!: () { appModel.currentView.value = Screens.library; appModel.bookLocatorFocusNode.requestFocus(); }, - shortcuts[Settings.getValue('key-shortcut-close-tab') != null - ? Settings.getValue('key-shortcut-close-tab') - : 'ctrl+w']!: () { + shortcuts[Settings.getValue('key-shortcut-open-find-ref') ?? + 'ctrl+o']!: () { + appModel.currentView.value = Screens.find; + appModel.findReferenceFocusNode.requestFocus(); + }, + shortcuts[Settings.getValue('key-shortcut-close-tab') ?? + 'ctrl+w']!: () { appModel.closeCurrentTab(); }, - shortcuts[ - Settings.getValue('key-shortcut-close-all-tabs') != null - ? Settings.getValue('key-shortcut-close-all-tabs') - : 'ctrl+x']!: () { + shortcuts[Settings.getValue('key-shortcut-close-all-tabs') ?? + 'ctrl+x']!: () { appModel.closeAllTabs(); }, - shortcuts[Settings.getValue( - 'key-shortcut-open-reading-screen') != - null - ? Settings.getValue('key-shortcut-open-reading-screen') - : 'ctrl+r']!: () { + shortcuts[ + Settings.getValue('key-shortcut-open-reading-screen') ?? + 'ctrl+r']!: () { appModel.currentView.value = Screens.reading; }, - shortcuts[ - Settings.getValue('key-shortcut-open-new-search') != null - ? Settings.getValue('key-shortcut-open-new-search') - : 'ctrl+q']!: () { + shortcuts[Settings.getValue('key-shortcut-open-new-search') ?? + 'ctrl+q']!: () { appModel.openNewSearchTab(); }, shortcuts['ctrl+shift+tab']!: () { diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index 5c961a848..b250791df 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -12,6 +12,7 @@ list(APPEND FLUTTER_PLUGIN_LIST list(APPEND FLUTTER_FFI_PLUGIN_LIST pdfrx + search_engine ) set(PLUGIN_BUNDLED_LIBRARIES) diff --git a/packages/filter_list-1.0.3/CHANGELOG.md b/packages/filter_list-1.0.3/CHANGELOG.md deleted file mode 100644 index 56f7cb833..000000000 --- a/packages/filter_list-1.0.3/CHANGELOG.md +++ /dev/null @@ -1,139 +0,0 @@ -## [1.0.3] - 27 May 2024 - -### Changed - -- Update dark theme colors -- Update flutter sdk constraint -- upgrade code as per new flutter version - -### Added - -- Added `onCloseWidgetPress` callback for FilterListDialog -- Add max selected chips param to limit maximum selection. Ref -> https://github.com/TheAlphamerc/filterlist/issues/36 - -### Removed - -- Remove canvasColor from ChoiceChipThemeData - -### Fixed - -- Filter list delegate tile selection issue. -- Search filter issue after its being empty. Ref:-https://github.com/TheAlphamerc/filterlist/issues/49 - -## [1.0.2] - 02 Jul 2022 - -- Make compatible with Flutter 3.0.0 -- Add `applyButtonText` prop to change Apply button text in FilterListDelegate -- Add copyWith method in `FilterListDelegateThemeData` to copy theme data -- Add copyWith method in `FilterListThemeData` to copy theme data - -## [1.0.1] - 18 Jan 2022 - -- 🚨 Breaking change - - - Removed `selectedChipTextStyle` prop - - Removed `unselectedChipTextStyle` prop - - Removed `selectedTextBackgroundColor` prop - - Removed `unselectedTextBackgroundColor` prop - - Removed `hideHeaderText` prop - - Removed `closeIconColor` prop - - Removed `hideHeaderAreaShadow` prop - - Removed `headerTextColor` prop - - Removed `searchFieldBackgroundColor` prop - - Removed `searchFieldTextStyle` prop - - Removed `headerTextStyle` prop - - Removed `searchFieldHintText` prop - - Removed `applyButonTextBackgroundColor` prop - - Removed `buttonRadius` prop - - Removed `buttonSpacing` prop - - Removed `controlButtonTextStyle` prop - - Removed `applyButtonTextStyle` prop - - Removed `applyButtonText` prop - - Removed `wrapAlignment` prop - - Removed `wrapCrossAxisAlignment` prop - - Removed `wrapSpacing` prop - - Removed `borderRadius` prop - - > Above removed parameters are moved to the newly created theme prop - - - Replace `ItemSearchDelegate` with `SearchPredict` method - -- Added Theme - - `FilterListTheme` for filter list widget theme - - `ChoiceChipTheme` for choice chip theme. - - `HeaderTheme` for Header widget theme - - `ControlButtonBarTheme` for control button bar theme - - `ControlButtonTheme` for control button theme - - `FilterListDelegateTheme` for filter list delegate theme - - `controlButtons` prop to display/hide control buttons (All, Reset) -- Added `FilterListDelegate.show` delegate to search/filter data in new screen - -## [1.0.0] 21 May 2021 - -- Improved visual customization. Including remove custom function. -- Added below arguments to improve the customization and make it translatable. - - `allButtonText` = 'All', - - `applyButtonText` = 'Apply', - - `resetButtonText` = 'Reset', - - `selectedItemsText` = 'selected item' -- Added `buttonRadius` button border radius argument. -- Added `controlContainerDecoration` action buttons box decoration argument. -- Added `buttonSpacing` button spacing argument. -- Added `validateRemoveItem` custom remove function that returns the selected list items filtered by the user conditions. -- Added `insetPadding` dialog padding argument. -- Added `wrapAlignment` argument to control the choice chips alignment in main axis. -- Added `wrapCrossAxisAlignment` argument to control choice chip within a run should be aligned relative to each other in the cross axis. -- Added `wrapSpacing` argument to control the space to place between choice chip in a run in the main axis. - -## [0.0.9] - 01 Apr 2021 - -- Migrate to null safety. -- `label` is replaced with `choiceChipLabel` - -## [0.0.8] - 28 Mar 2021 - -- Added `choiceChipBuilder` to build custom choice chip. -- Added `selectedChipTextStyle`,`unselectedChipTextStyle`,`controlButtonTextStyle`,`applyButtonTextStyle`,`headerTextStyle` and `searchFieldTextStyle` styles. -- Removed `applyButonTextColor`,`allResetButonColor`,`selectedTextColor`,`unselectedTextColor` colors properties. - -## [0.0.7] - 20 Feb 2021 - -- Update readme.md - -## [0.0.6] - 20 Feb 2021 - -- Convert filter list package to generic list filter package -- `allTextList` changed to `listData` -- `selectedTextList` changed to `selectedListData` -- `FilterListWidget` and `FilterListDialog` can filter any type if list -- Added `validateSelectedItem` callback to validate which item needs to be selected -- Added `onItemSearch` callback to expose search mechanism on user side to filter list.' - -## [0.0.5] - 22 Sep 2020 - -- Add `FilterListWidget` widget. -- `FilterList.showFilterList` is renamed to `FilterListDialog.display` -- Add `onApplyButtonClick` callback to return selected text list from `FilterListDialog.display`. - -## [0.0.4] - 05 Mar 2020 - -- Added pop-up Corner Radius property -- Added ripple effect on control button. - -## [0.0.3] - 02 Mar 2020 - -- Added pop-up height - -- Added pop-up width -- Added header hide prop -- Added search field hide prop -- Added cross icon hide prop - -## [0.0.2] - 02 Mar 2020 - -- Added filter pop-up theme customization - -## [0.0.1] - 02 Mar 2020 - -- Filter list functionality added -- Return selected list of text diff --git a/packages/filter_list-1.0.3/LICENSE b/packages/filter_list-1.0.3/LICENSE deleted file mode 100644 index ac969633f..000000000 --- a/packages/filter_list-1.0.3/LICENSE +++ /dev/null @@ -1,25 +0,0 @@ -BSD 2-Clause License - -Copyright (c) 2020, Sonu Sharma -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/packages/filter_list-1.0.3/README.md b/packages/filter_list-1.0.3/README.md deleted file mode 100644 index 4dfac58c8..000000000 --- a/packages/filter_list-1.0.3/README.md +++ /dev/null @@ -1,270 +0,0 @@ - -## filter_list -[![pub package](https://img.shields.io/pub/v/filter_list?color=blue)](https://pub.dev/packages/filter_list) -[![Likes](https://badges.bar/filter_list/likes)](https://pub.dev/packages/flutter_plugin_filter_list/score) -[![Popularity](https://badges.bar/filter_list/popularity)](https://pub.dev/packages/filter_list/score) -[![Pub points](https://badges.bar/flutter_week_view/pub%20points)](https://pub.dev/packages/filter_list/score) -[![Hits](https://hits.seeyoufarm.com/api/count/incr/badge.svg?url=https%3A%2F%2Fgithub.com%2FTheAlphamerc%2Fflutter_plugin_filter_list&count_bg=%2379C83D&title_bg=%23555555&icon=&icon_color=%23E7E7E7&title=hits&edge_flat=false)](https://hits.seeyoufarm.com) -[![GitHub stars](https://img.shields.io/github/stars/Thealphamerc/flutter_plugin_filter_list?style=social)](https://github.com/login?return_to=https://github.com/FTheAlphamerc/flutter_plugin_filter_list) -![GitHub forks](https://img.shields.io/github/forks/TheAlphamerc/flutter_plugin_filter_list?style=social) - - -FilterList is a flutter package which provide utility to search/filter on the basis of single/multiple selection from provided dynamic list. - -### Download Demo App ![GitHub All Releases](https://img.shields.io/github/downloads/Thealphamerc/flutter_plugin_filter_list/total?color=green) - - -## Getting Started -1. Add library to your pubspec.yaml -```yaml - -dependencies: - filter_list: ^ - -``` -2. Import library in dart file -```dart -import 'package:filter_list/filter_list.dart'; -``` - -3. Create a list of Strings / dynamic object -``` dart -class User { - final String? name; - final String? avatar; - User({this.name, this.avatar}); -} - -List userList = [ - User(name: "Jon", avatar: ""), - User(name: "Lindsey ", avatar: ""), - User(name: "Valarie ", avatar: ""), - User(name: "Elyse ", avatar: ""), - User(name: "Ethel ", avatar: ""), - User(name: "Emelyan ", avatar: ""), - User(name: "Catherine ", avatar: ""), - User(name: "Stepanida ", avatar: ""), - User(name: "Carolina ", avatar: ""), - User(name: "Nail ", avatar: ""), - User(name: "Kamil ", avatar: ""), - User(name: "Mariana ", avatar: ""), - User(name: "Katerina ", avatar: ""), -]; -``` - -## Filter list offer 3 ways to filter data from list -- FilterListDialog -- FilterListWidget -- FilterListDelegate - -Below is a example of using filter list widgets with minimal code however there is a lot more inside the widget for you to fully customize the widget. - -## How to use FilterListDialog -#### 1. Create a function and call `FilterListDialog.display` -```dart - void openFilterDialog() async { - await FilterListDialog.display( - context, - listData: userList, - selectedListData: selectedUserList, - choiceChipLabel: (user) => user!.name, - validateSelectedItem: (list, val) => list!.contains(val), - onItemSearch: (user, query) { - return user.name!.toLowerCase().contains(query.toLowerCase()); - }, - onApplyButtonClick: (list) { - setState(() { - selectedUserList = List.from(list!); - }); - Navigator.pop(context); - }, - ); - } -``` ->If `Apply` button is pressed without making any selection it will return empty list of items. - -#### 2. Call `openFilterDialog` function on button tap to display filter dialog - -```dart -@override - Widget build(BuildContext context) { - return Scaffold( - floatingActionButton: FloatingActionButton( - onPressed: openFilterDialog, - child: Icon(Icons.add), - ), - body: selectedUserList == null || selectedUserList!.length == 0 - ? Center(child: Text('No user selected')) - : ListView.builder( - itemBuilder: (context, index) { - return ListTile( - title: Text(selectedUserList![index].name!), - ); - }, - itemCount: selectedUserList!.length, - ), - ); - } -``` - - -## How to use `FilterListWidget`. -```dart - -class FilterPage extends StatelessWidget { - const FilterPage({Key? key, this.selectedUserList}) - : super(key: key); - final List? selectedUserList; - @override - Widget build(BuildContext context) { - return Scaffold( - body: FilterListWidget( - listData: userList, - selectedListData: selectedUserList, - onApplyButtonClick: (list) { - // do something with list .. - }, - choiceChipLabel: (item) { - /// Used to display text on chip - return item!.name; - }, - validateSelectedItem: (list, val) { - /// identify if item is selected or not - return list!.contains(val); - }, - onItemSearch: (user, query) { - /// When search query change in search bar then this method will be called - /// - /// Check if items contains query - return user.name!.toLowerCase().contains(query.toLowerCase()); - }, - ), - ); - } -} -``` - -## How to use `FilterListDelegate`. -Create a function and call `FilterListDelegate.open()` on button tap. - -``` dart - void openFilterDelegate() async { - await FilterListDelegate.open( - context: context, - list: userList, - onItemSearch: (user, query) { - return user.name!.toLowerCase().contains(query.toLowerCase()); - }, - tileLabel: (user) => user!.name, - emptySearchChild: Center(child: Text('No user found')), - searchFieldHint: 'Search Here..', - onApplyButtonClick: (list) { - // Do something with selected list - }, - ); - } -``` - -## Screenshots - - -Empty screen | FilterListDialog | Selected chip | Result from dialog -:-------------------------:|:-------------------------:|:-------------------------:|:-------------------------: -| | | - -### Customized Dialog Header - | | | | -:-------------------------:|:-------------------------:|:-------------------------:| -| | | - -### Customized Choice chip -| | | | | -:-------------------------:|:-------------------------:|:-------------------------:|:-------------------------: -| | | - - - ### FilterListWidget -| Default| Customized | customized | -:-------------------------:|:-------------------------:|:-------------------------: -![](https://github.com/TheAlphamerc/flutter_plugin_filter_list/blob/screenshots/13.jpeg?raw=true)|![](https://github.com/TheAlphamerc/flutter_plugin_filter_list/blob/screenshots/15.jpeg?raw=true)|![](https://raw.githubusercontent.com/TheAlphamerc/flutter_plugin_filter_list/screenshots/16.jpeg)| - -### FilterListDelegate -| Single selection | Multiple selection |Multiple selection -|:-:|:-:|:-:| -![](https://github.com/TheAlphamerc/flutter_plugin_filter_list/blob/screenshots/17.jpeg?raw=true)|![](https://github.com/TheAlphamerc/flutter_plugin_filter_list/blob/screenshots/18.jpeg?raw=true)|![](https://github.com/TheAlphamerc/flutter_plugin_filter_list/blob/screenshots/19.jpeg?raw=true)| - - -| Search through list | Customized Tile | -|:-:|:-:| - | - - - - -## Parameters - -| Parameter | Type | Description | -| :-------- | :------- | :------------------------- | -| height | `double` | Set height of filter dialog.| -| width | `double` | Set width of filter dialog.| -| hideCloseIcon|`bool`|Hide close Icon.| -| hideHeader|`bool`|Hide complete header section from filter dialog.| -| headerCloseIcon|`Widget`|Widget to close the dialog.| -| hideSelectedTextCount|`bool`|Hide selected text count.| -| enableOnlySingleSelection|`bool`| Enable only single selection | -| maximumSelectionLength|`int`| Set maximum selection length.| -| hideSearchField|`bool`|Hide search text field.| -| headlineText|`String`|Set header text of filter dialog.| -| backgroundColor|`Color`|Set background color of filter color| -| listData|`List()`|Populate filter dialog with text list. | -| selectedListData|` List()`|Marked selected text in filter dialog.| -| choiceChipLabel|`String Function(T item)`| Display text on choice chip.| -| validateSelectedItem|`bool Function(List? list, T item)`| Identifies weather a item is selected or not| -| onItemSearch|`List Function(List? list, String text)`| Perform search operation and returns filtered list| -| choiceChipBuilder|`Widget Function(BuildContext context, T? item, bool? isSelected)`|The choiceChipBuilder is a builder to design custom choice chip.| -| onApplyButtonClick|`Function(List list)`|Returns list of items when apply button is clicked| -| validateRemoveItem|`List Function(List? list, T item)`| Function Delegate responsible for delete item from list | -| resetButtonText|`String`| Reset button text to customize or translate | -| allButtonText|`String`| All button text to customize or translate | -| selectedItemsText|`String`| Selected items text to customize or translate | -| controlButtons|`List`| configure which control button needs to be display on bottom of dialog along with 'Apply' button.| -| insetPadding| `EdgeInsets`| The amount of padding added to the outside of the dialog.| -| themeData|`FilterListThemeData`| Configure theme of filter dialog and widget.| -| choiceChipTheme|`ChoiceChipThemeData`| Configure theme of choice chip.| -| controlButtonBarTheme|`ControlButtonBarThemeData`| Configure theme of control button bar| -| controlButtonTheme|`ControlButtonThemeData`| Configure theme of control button.| -| headerTheme|`HeaderThemeData`| Configure theme of filter header.| - - -> `T` can be a String or any user defined Model - - -## Other Flutter packages - Name | Stars | Pub | -:-------------------------|------------------------- | ------------------------- | -|[Empty widget](https://github.com/TheAlphamerc/empty_widget) |[![GitHub stars](https://img.shields.io/github/stars/Thealphamerc/empty_widget?style=social)](https://github.com/login?return_to=https://github.com/TheAlphamerc/empty_widget) | [![pub package](https://img.shields.io/pub/v/empty_widget?color=blue)](https://pub.dev/packages/empty_widget) | -|[Add Thumbnail](https://github.com/TheAlphamerc/flutter_plugin_add_thumbnail) |[![GitHub stars](https://img.shields.io/github/stars/Thealphamerc/flutter_plugin_add_thumbnail?style=social)](https://github.com/login?return_to=https://github.com/TheAlphamerc/flutter_plugin_add_thumbnail) | [![pub package](https://img.shields.io/pub/v/add_thumbnail?color=blue)](https://pub.dev/packages/add_thumbnail) | -|[Country Provider](https://github.com/TheAlphamerc/country_provider) |[![GitHub stars](https://img.shields.io/github/stars/Thealphamerc/country_provider?style=social)](https://github.com/login?return_to=https://github.com/TheAlphamerc/country_provider) | [![pub package](https://img.shields.io/pub/v/country_provider?color=blue)](https://pub.dev/packages/country_provider) | - - -## Pull Requests - -I welcome and encourage all pull requests. It usually will take me within 24-48 hours to respond to any issue or request. - -## Created & Maintained By - -[Sonu Sharma](https://github.com/TheAlphamerc) ([Twitter](https://www.twitter.com/TheAlphamerc)) ([Youtube](https://www.youtube.com/user/sonusharma045sonu/)) -([Insta](https://www.instagram.com/_sonu_sharma__)) ![Twitter Follow](https://img.shields.io/twitter/follow/thealphamerc?style=social) - -> If you found this project helpful or you learned something from the source code and want to thank me, consider buying me a cup of :coffee: -> - -> * -> * [PayPal](https://www.paypal.me/TheAlphamerc/) - - -## Visitors Count - -Loading - - diff --git a/packages/filter_list-1.0.3/analysis_options.yaml b/packages/filter_list-1.0.3/analysis_options.yaml deleted file mode 100644 index cbe2ba403..000000000 --- a/packages/filter_list-1.0.3/analysis_options.yaml +++ /dev/null @@ -1,909 +0,0 @@ -analyzer: - - exclude: - - 'lib/**.freezed.dart' - - 'lib/**.g.dart' - - 'lib/ui/widget/form/validator.dart' - -linter: - rules: - # Prevents accidental return type changes which results in a breaking API change. - # Enforcing return type makes API changes visible in a diff - # pedantic: enabled - # http://dart-lang.github.io/linter/lints/always_declare_return_types.html - - always_declare_return_types - - # Single line `if`s are fine as recommended in Effective Dart "DO format your code using dartfmt" - # pedantic: disabled - # http://dart-lang.github.io/linter/lints/always_put_control_body_on_new_line.html - # - always_put_control_body_on_new_line - - # Flutter widgets always put a Key as first optional parameter which breaks this rule. - # Also violates other orderings like matching the class fields or alphabetically. - # pedantic: disabled - # http://dart-lang.github.io/linter/lints/always_declare_return_types.html - # - always_put_required_named_parameters_first - - # All non nullable named parameters should be and annotated with @required. - # This allows API consumers to get warnings via lint rather than a crash a runtime. - # Might become obsolete with Non-Nullable types - # pedantic: enabled - # http://dart-lang.github.io/linter/lints/always_require_non_null_named_parameters.html - - always_require_non_null_named_parameters - - # Since dart 2.0 dart is a sound language, specifying types is not required anymore. - # `var foo = 10;` is enough information for the compiler to make foo a int. - # Violates Effective Dart "AVOID type annotating initialized local variables". - # Makes code unnecessarily complex https://github.com/dart-lang/linter/issues/1620 - # pedantic: disabled - # http://dart-lang.github.io/linter/lints/always_specify_types.html - # - always_specify_types - - # Protect against unintentionally overriding superclass members - # pedantic: enabled - # http://dart-lang.github.io/linter/lints/annotate_overrides.html - - annotate_overrides - - # All methods should define a return type. dynamic is no exception. - # Violates Effective Dart "PREFER annotating with dynamic instead of letting inference fail" - # pedantic: disabled - # http://dart-lang.github.io/linter/lints/avoid_annotating_with_dynamic.html - # - avoid_annotating_with_dynamic - - # A leftover from dart1, should be deprecated - # pedantic: disabled - # - https://github.com/dart-lang/linter/issues/1401 - # http://dart-lang.github.io/linter/lints/avoid_as.html - # - avoid_as - - # Highlights boolean expressions which can be simplified - # http://dart-lang.github.io/linter/lints/avoid_bool_literals_in_conditional_expressions.html - - avoid_bool_literals_in_conditional_expressions - - # There are no strong arguments to enable this rule because it is very strict. Catching anything is useful - # and common even if not always the most correct thing to do. - # pedantic: disabled - # http://dart-lang.github.io/linter/lints/avoid_catches_without_on_clauses.html - # - avoid_catches_without_on_clauses - - # Errors aren't for catching but to prevent prior to runtime - # pedantic: disabled - # http://dart-lang.github.io/linter/lints/avoid_catching_errors.html - - avoid_catching_errors - - # Can usually be replaced with an extension - # pedantic: disabled - # http://dart-lang.github.io/linter/lints/avoid_classes_with_only_static_members.html - # - avoid_classes_with_only_static_membersß - - # Never accidentally use dynamic invocations - # Dart SDK: unreleased • (Linter vnull) - # https://dart-lang.github.io/linter/lints/avoid_dynamic_calls.html - # avoid_dynamic_calls - - # Only useful when targeting JS - # pedantic: disabled - # http://dart-lang.github.io/linter/lints/avoid_double_and_int_checks.html - # - avoid_double_and_int_checks - - # Prevents accidental empty else cases. See samples in documentation - # pedantic: enabled - # http://dart-lang.github.io/linter/lints/avoid_empty_else.html - - avoid_empty_else - - # It is expected that mutable objects which override hash & equals shouldn't be used as keys for hashmaps. - # This one use case doesn't make all hash & equals implementations for mutable classes bad. - # pedantic: disabled - # https://dart-lang.github.io/linter/lints/avoid_equals_and_hash_code_on_mutable_classes.html - # - avoid_equals_and_hash_code_on_mutable_classes - - # Use different quotes instead of escaping - # Dart SDK: >= 2.8.0-dev.11.0 • (Linter v0.1.111) - # https://dart-lang.github.io/linter/lints/avoid_escaping_inner_quotes.html - - avoid_escaping_inner_quotes - - # Prevents unnecessary allocation of a field - # pedantic: disabled - # http://dart-lang.github.io/linter/lints/avoid_field_initializers_in_const_classes.html - - avoid_field_initializers_in_const_classes - - # Prevents allocating a lambda and allows return/break/continue control flow statements inside the loop - # http://dart-lang.github.io/linter/lints/avoid_function_literals_in_foreach_calls.html - - avoid_function_literals_in_foreach_calls - - # Don't break value types by implementing them - # http://dart-lang.github.io/linter/lints/avoid_implementing_value_types.html - - avoid_implementing_value_types - - # Removes redundant `= null;` - # https://dart-lang.github.io/linter/lints/avoid_init_to_null.html - - avoid_init_to_null - - # Only useful when targeting JS - # Warns about too large integers when compiling to JS - # pedantic: disabled - # https://dart-lang.github.io/linter/lints/avoid_js_rounded_ints.html - # - avoid_js_rounded_ints - - # Null checks aren't required in ==() operators - # pedantic: enabled - # https://dart-lang.github.io/linter/lints/avoid_null_checks_in_equality_operators.html - - avoid_null_checks_in_equality_operators - - # Good APIs don't use ambiguous boolean parameters. Instead use named parameters - # https://dart-lang.github.io/linter/lints/avoid_positional_boolean_parameters.html - # - avoid_positional_boolean_parameters - - # Don't call print in production code - # pedantic: disabled - # https://dart-lang.github.io/linter/lints/avoid_print.html - - avoid_print - - # Always prefer function references over typedefs. - # Jumping twice in code to see the signature of a lambda sucks. This is different from the flutter analysis_options - # https://dart-lang.github.io/linter/lints/avoid_private_typedef_functions.html - - avoid_private_typedef_functions - - # Don't explicitly set defaults - # Dart SDK: >= 2.8.0-dev.1.0 • (Linter v0.1.107) - # https://dart-lang.github.io/linter/lints/avoid_redundant_argument_values.html - - avoid_redundant_argument_values - - # package or relative? Let's end the discussion and use package everywhere. - # pedantic: enabled - # https://dart-lang.github.io/linter/lints/avoid_relative_lib_imports.html - - avoid_relative_lib_imports - - # Not recommended to break dartdoc but besides that there is no reason to continue with bad naming - # https://dart-lang.github.io/linter/lints/avoid_renaming_method_parameters.html - # - avoid_renaming_method_parameters - - # Setters always return void, therefore defining void is redundant - # pedantic: enabled - # https://dart-lang.github.io/linter/lints/avoid_return_types_on_setters.html - - avoid_return_types_on_setters - - # Especially with Non-Nullable types on the horizon, `int?` is fine. - # There are plenty of valid reasons to return null. - # pedantic: disabled - # https://dart-lang.github.io/linter/lints/avoid_returning_null.html - # - avoid_returning_null - - # Don't use `Future?`, therefore never return null instead of a Future. - # Will become obsolete one Non-Nullable types land - # https://dart-lang.github.io/linter/lints/avoid_returning_null_for_future.html - - avoid_returning_null_for_future - - # Use empty returns, don't show off with you knowledge about dart internals. - # https://dart-lang.github.io/linter/lints/avoid_returning_null_for_void.html - - avoid_returning_null_for_void - - # Hinting you forgot about the cascade operator. But too often you did this on purpose. - # There are plenty of valid reasons to return this. - # pedantic: disabled - # https://dart-lang.github.io/linter/lints/avoid_returning_this.html - # - avoid_returning_this - - # Prevents logical inconsistencies. It's good practice to define getters for all existing setters. - # https://dart-lang.github.io/linter/lints/avoid_setters_without_getters.html - # - avoid_setters_without_getters - - # Don't reuse a type parameter when on with the same name already exists in the same scope - # pedantic: enabled - # https://dart-lang.github.io/linter/lints/avoid_shadowing_type_parameters.html - - avoid_shadowing_type_parameters - - # A single cascade operator can be replaced with a normal method call - # pedantic: enabled - # https://dart-lang.github.io/linter/lints/avoid_single_cascade_in_expression_statements.html - - avoid_single_cascade_in_expression_statements - - # Might cause frame drops because of synchronous file access on mobile, especially on older phones with slow storage. - # There are no known measurements sync access does *not* drop frames. - # pedantic: disabled - # https://dart-lang.github.io/linter/lints/avoid_slow_async_io.html - # - avoid_slow_async_io - - # Don't use .toString() in production code which might be minified - # Dart SDK: >= 2.10.0-144.0.dev • (Linter v0.1.119) - # https://dart-lang.github.io/linter/lints/avoid_type_to_string.html - - avoid_type_to_string - - # Don't use a parameter names which can be confused with a types (i.e. int, bool, num, ...) - # pedantic: enabled - # https://dart-lang.github.io/linter/lints/avoid_types_as_parameter_names.html - - avoid_types_as_parameter_names - - # Adding the type is not required, but sometimes improves readability. Therefore removing it doesn't always help - # https://dart-lang.github.io/linter/lints/avoid_types_on_closure_parameters.html - # - avoid_types_on_closure_parameters - - # Containers without parameters have no effect and can be removed - # https://dart-lang.github.io/linter/lints/avoid_unnecessary_containers.html - - avoid_unnecessary_containers - - # Unused parameters should be removed - # https://dart-lang.github.io/linter/lints/avoid_unused_constructor_parameters.html - - avoid_unused_constructor_parameters - - # TODO double check - # For async functions use `Future` as return value, not `void` - # This allows usage of the await keyword and prevents operations from running in parallel. - # pedantic: disabled - # https://dart-lang.github.io/linter/lints/avoid_void_async.html - - avoid_void_async - - # Flutter mobile only: Web packages aren't available in mobile flutter apps - # https://dart-lang.github.io/linter/lints/avoid_web_libraries_in_flutter.html - - avoid_web_libraries_in_flutter - - # Use the await keyword only for futures. There is nothing to await in synchronous code - # pedantic: enabled - # https://dart-lang.github.io/linter/lints/await_only_futures.html - - await_only_futures - - # Follow the style guide and use UpperCamelCase for extensions - # pedantic: enabled - # https://dart-lang.github.io/linter/lints/camel_case_extensions.html - - camel_case_extensions - - # Follow the style guide and use UpperCamelCase for class names and typedefs - # https://dart-lang.github.io/linter/lints/camel_case_types.html - - camel_case_types - - # Prevents leaks and code executing after their lifecycle. - # Discussion https://github.com/passsy/dart-lint/issues/4 - # - # pedantic: disabled - # https://dart-lang.github.io/linter/lints/cancel_subscriptions.html - - cancel_subscriptions - - # The cascade syntax is weird and you shouldn't be forced to use it. - # False positives: - # https://github.com/dart-lang/linter/issues/1589 - # - # https://dart-lang.github.io/linter/lints/cascade_invocations.html - # - cascade_invocations - - # Don't cast T? to T. Use ! instead - # Dart SDK: >= 2.11.0-182.0.dev • (Linter v0.1.120) - # https://dart-lang.github.io/linter/lints/cast_nullable_to_non_nullable.html - - cast_nullable_to_non_nullable - - # False positives, not reliable enough - # - https://github.com/dart-lang/linter/issues/1381 - # - # pedantic: disabled - # https://dart-lang.github.io/linter/lints/close_sinks.html - # - close_sinks - - # False positives: - # - https://github.com/dart-lang/linter/issues/1142 - # - # https://dart-lang.github.io/linter/lints/comment_references.html - # - comment_references - - # Follow standard dart naming style. - # pedantic: disabled - # https://dart-lang.github.io/linter/lints/constant_identifier_names.html - - constant_identifier_names - - # Prevents hard to debug code - # pedantic: disabled - # https://dart-lang.github.io/linter/lints/control_flow_in_finally.html - - control_flow_in_finally - - # Single line `if`s are fine, but when a new line splits the bool expression and body curly braces - # are recommended. It prevents the danging else problem and easily allows the addition of more lines inside - # the if body - # pedantic: enabled - # https://dart-lang.github.io/linter/lints/curly_braces_in_flow_control_structures.html - - curly_braces_in_flow_control_structures - - # Still experimental and pretty much work when enforced - # https://dart-lang.github.io/linter/lints/diagnostic_describe_all_properties.html - # - diagnostic_describe_all_properties - - # Follows dart style. Fully supported by IDEs and no manual effort for a consistent style - # pedantic: disabled - # https://dart-lang.github.io/linter/lints/directives_ordering.html - - directives_ordering - - # String.fromEnvironment looks up env variables at compile time. The variable is baked in by the compiler - # and can't be changed by environment variables. - # - # For dart apps: - # Better look up a environment variable at runtime with Platform.environment - # or use code generation to define variables at compile time. - # - # For Flutter apps: - # String.fromEnvironment is the recommended way to include variables defined with `flutter build --dart-define` - # - # pedantic: disabled - # Dart SDK: >= 2.10.0-0.0.dev • (Linter v0.1.117) - # https://dart-lang.github.io/linter/lints/do_not_use_environment.html - # - do_not_use_environment - - # Add a comment why no further error handling is required - # pedantic: enabled - # https://dart-lang.github.io/linter/lints/empty_catches.html - - empty_catches - - # Removed empty constructor bodies - # pedantic: enabled - # https://dart-lang.github.io/linter/lints/empty_constructor_bodies.html - - empty_constructor_bodies - - # Don't allow empty if bodies. Works together with curly_braces_in_flow_control_structures - # pedantic: disabled - # https://dart-lang.github.io/linter/lints/empty_statements.html - - empty_statements - - # Enums aren't powerful enough, now enum like classes get the same linting support - # pedantic: disabled - # Dart SDK: >= 2.9.0-12.0.dev • (Linter v0.1.116) - # https://dart-lang.github.io/linter/lints/exhaustive_cases.html - - exhaustive_cases - - # Follow dart file naming schema - # https://dart-lang.github.io/linter/lints/file_names.html - - file_names - - # Very flutter specific, not applicable for all projects - # pedantic: disabled - # https://dart-lang.github.io/linter/lints/flutter_style_todos.html - # - flutter_style_todos # not all todos require a ticket - - # hashCode and equals need to be consistent. One can't live without another. - # https://dart-lang.github.io/linter/lints/hash_and_equals.html - - hash_and_equals - - # DON'T import implementation files from another package. - # If you need access to some internal code, create an issue - # https://dart-lang.github.io/linter/lints/implementation_imports.html - - implementation_imports - - # Although there are some false positives, this lint generally catches unnecessary checks - # - https://github.com/dart-lang/linter/issues/811 - # - # pedantic: disabled - # https://dart-lang.github.io/linter/lints/invariant_booleans.html - - invariant_booleans - - # Type check for Iterable.contains(other) where other is! T - # otherwise contains will always report false. Those errors are usually very hard to catch. - # https://dart-lang.github.io/linter/lints/iterable_contains_unrelated_type.html - - iterable_contains_unrelated_type - - # Hint to join return and assignment. - # pedantic: disabled - # https://dart-lang.github.io/linter/lints/join_return_with_assignment.html - - join_return_with_assignment - - # Add leading \n which which makes multiline strings easier to read - # Dart SDK: >= 2.8.0-dev.16.0 • (Linter v0.1.113) - # https://dart-lang.github.io/linter/lints/leading_newlines_in_multiline_strings.html - - leading_newlines_in_multiline_strings - - # Makes sure a library name is a valid dart identifier. - # This comes in handy for test files combining multiple tests where the file name can be used as identifier - # - # ``` - # import src/some_test.dart as some_test; - # - # main() { - # some_test.main(); - # } - # ``` - # pedantic: enabled - # https://dart-lang.github.io/linter/lints/library_names.html - - library_names - - # Follow dart style - # pedantic: enabled - # https://dart-lang.github.io/linter/lints/library_prefixes.html - - library_prefixes - - # Nobody wants to manually wrap lines when changing a few words. This rule is too hard to be a "general" rule - # https://dart-lang.github.io/linter/lints/lines_longer_than_80_chars.html - # - lines_longer_than_80_chars - - # Type check for List.remove(item) where item is! T - # The list can't contain item. Those errors are not directly obvious especially when refactoring. - # https://dart-lang.github.io/linter/lints/list_remove_unrelated_type.html - - list_remove_unrelated_type - - # Good for libraries to prevent unnecessary code paths. - # False positives may occur for applications when boolean properties are generated by external programs - # producing auto-generated source code - # - # Known issue: while(true) loops https://github.com/dart-lang/linter/issues/453 - # - # pedantic: disabled - # https://dart-lang.github.io/linter/lints/literal_only_boolean_expressions.html - # - literal_only_boolean_expressions - - # Don't forget the whitespaces at the end - # Dart SDK: >= 2.8.0-dev.10.0 • (Linter v0.1.110) - # https://dart-lang.github.io/linter/lints/missing_whitespace_between_adjacent_strings.html - - missing_whitespace_between_adjacent_strings - - # Concat Strings obviously with `+` inside a list. - # pedantic: disabled - # https://dart-lang.github.io/linter/lints/no_adjacent_strings_in_list.html - - no_adjacent_strings_in_list - - # Second case is basically dead code which will never be reached. - # pedantic: enabled - # https://dart-lang.github.io/linter/lints/no_duplicate_case_values.html - - no_duplicate_case_values - - # Flutter only: `createState` shouldn't pass information into the state - # https://dart-lang.github.io/linter/lints/no_logic_in_create_state.html - - no_logic_in_create_state - - # calling `runtimeType` may be a performance problem - # Dart SDK: >= 2.8.0-dev.10.0 • (Linter v0.1.110) - # https://dart-lang.github.io/linter/lints/no_runtimeType_toString.html - - no_runtimeType_toString - - # Follow dart style naming conventions - # https://dart-lang.github.io/linter/lints/non_constant_identifier_names.html - - non_constant_identifier_names - - # Generic T might have a value of String or String?. Both are valid. - # This lint triggers when ! is used on T? casting (String?)? to String and not (String?)? to String? - # Dart SDK: >= 2.11.0-182.0.dev • (Linter v0.1.120) - # https://dart-lang.github.io/linter/lints/null_check_on_nullable_type_parameter.html - - null_check_on_nullable_type_parameter - - # Might become irrelevant when non-nullable types land in dart. Until then use this lint check which checks for - # non null arguments for specific dart sdk methods. - # pedantic: enabled - # https://dart-lang.github.io/linter/lints/null_closures.html - - null_closures - - # Types for local variables may improve readability. - # pedantic: enabled - # https://dart-lang.github.io/linter/lints/omit_local_variable_types.html - # - omit_local_variable_types - - # Defining interfaces (abstract classes), with only one method, makes sense architecture wise - # Discussion: https://github.com/passsy/dart-lint/issues/2 - # - # pedantic: disabled - # https://dart-lang.github.io/linter/lints/one_member_abstracts.html - # - one_member_abstracts - - # Since Errors aren't intended to be caught (see avoid_catching_errors), throwing anything - # doesn't cause trouble. - # https://dart-lang.github.io/linter/lints/only_throw_errors.html - # - only_throw_errors - - # Highlights unintentionally overridden fields. - # https://dart-lang.github.io/linter/lints/overridden_fields.html - - overridden_fields - - # Only relevant for packages, not applications or general dart code - # https://dart-lang.github.io/linter/lints/package_api_docs.html - # - package_api_docs - - # Follow dart style package naming convention - # https://dart-lang.github.io/linter/lints/package_names.html - - package_names - - # Seems very rare, especially for applications. - # https://dart-lang.github.io/linter/lints/package_prefixed_library_names.html - - package_prefixed_library_names - - # Most likely a mistake, if not: bad practice - # pedantic: disabled - # https://dart-lang.github.io/linter/lints/parameter_assignments.html - # - parameter_assignments - - # Is contradictory to `no_adjacent_strings_in_list` - # pedantic: enabled - # https://dart-lang.github.io/linter/lints/prefer_adjacent_string_concatenation.html - # - prefer_adjacent_string_concatenation - - # Makes it easier to migrate to const constructors and to have final fields - # pedantic: disabled - # https://dart-lang.github.io/linter/lints/prefer_asserts_in_initializer_lists.html - - prefer_asserts_in_initializer_lists - - # Assertions blocks don't require a message because they throw simple to understand errors - # pedantic: disabled - # https://dart-lang.github.io/linter/lints/prefer_asserts_with_message.html - # - prefer_asserts_with_message - - # Collection literals are shorter. They exists, use them. - # pedantic: enabled - # https://dart-lang.github.io/linter/lints/prefer_collection_literals.html - - prefer_collection_literals - - # Use the ??= operator when possible - # pedantic: enabled - # https://dart-lang.github.io/linter/lints/prefer_conditional_assignment.html - - prefer_conditional_assignment - - # Always use const when possible, make runtime faster - # pedantic: disabled - # https://dart-lang.github.io/linter/lints/prefer_const_constructors.html - - prefer_const_constructors - - # Add a const constructor when possible - # pedantic: disabled - # https://dart-lang.github.io/linter/lints/prefer_const_constructors_in_immutables.html - - prefer_const_constructors_in_immutables - - # final is good, const is better - # https://dart-lang.github.io/linter/lints/prefer_const_declarations.html - - prefer_const_declarations - - # Always use const when possible, make runtime faster - # pedantic: disabled - # https://dart-lang.github.io/linter/lints/prefer_const_literals_to_create_immutables.html - - prefer_const_literals_to_create_immutables - - # Dart has named constructors. Static methods in other languages (java) are a workaround which don't have - # named constructors. - # pedantic: disabled - # https://dart-lang.github.io/linter/lints/prefer_constructors_over_static_methods.html - - prefer_constructors_over_static_methods - - # Contains may be faster and is easier to read - # pedantic: enabled - # https://dart-lang.github.io/linter/lints/prefer_contains.html - - prefer_contains - - # Use whatever makes you happy. lint doesn't define a style - # pedantic: disabled - # https://dart-lang.github.io/linter/lints/prefer_double_quotes.html - # - prefer_double_quotes - - # Prevent confusion with call-side when using named parameters - # pedantic: enabled - # https://dart-lang.github.io/linter/lints/prefer_equal_for_default_values.html - - prefer_equal_for_default_values - - # Single line methods + implementation makes it hard to write comments for that line. - # Dense code isn't necessarily better code. - # pedantic: disabled - # https://dart-lang.github.io/linter/lints/prefer_expression_function_bodies.html - # - prefer_expression_function_bodies - - # Avoid accidental reassignments and allows the compiler to do optimizations. - # pedantic: enabled - # https://dart-lang.github.io/linter/lints/prefer_final_fields.html - - prefer_final_fields - - # Helps avoid accidental reassignments and allows the compiler to do optimizations. - # pedantic: disabled - # https://dart-lang.github.io/linter/lints/prefer_final_in_for_each.html - - prefer_final_in_for_each - - # Helps avoid accidental reassignments and allows the compiler to do optimizations. - # pedantic: disabled - # https://dart-lang.github.io/linter/lints/prefer_final_locals.html - - prefer_final_locals - - # Saves lot of code - # pedantic: enabled - # https://dart-lang.github.io/linter/lints/prefer_for_elements_to_map_fromIterable.html - - prefer_for_elements_to_map_fromIterable - - # Dense code isn't necessarily better code - # pedantic: disabled - # https://dart-lang.github.io/linter/lints/prefer_foreach.html - # - prefer_foreach - - # As Dart allows local function declarations, it is a good practice to use them in the place of function literals. - # https://dart-lang.github.io/linter/lints/prefer_function_declarations_over_variables.html - - prefer_function_declarations_over_variables - - # For consistency - # pedantic: enabled - # https://dart-lang.github.io/linter/lints/prefer_generic_function_type_aliases.html - - prefer_generic_function_type_aliases - - # Allows potential usage of const - # https://dart-lang.github.io/linter/lints/prefer_if_elements_to_conditional_expressions.html - - prefer_if_elements_to_conditional_expressions - - # Dart has a special operator for this, use it - # pedantic: enabled - # https://dart-lang.github.io/linter/lints/prefer_if_null_operators.html - - prefer_if_null_operators - - # Terser code - # https://dart-lang.github.io/linter/lints/prefer_initializing_formals.html - - prefer_initializing_formals - - # Easier move towards const, and way easier to read - # pedantic: enabled - # https://dart-lang.github.io/linter/lints/prefer_inlined_adds.html - - prefer_inlined_adds - - # There is no argument which makes int literals better than double literals for doubles. - # pedantic: disabled - # https://dart-lang.github.io/linter/lints/prefer_int_literals.html - # - prefer_int_literals - - # Interpolate, use less "", '' and + - # https://dart-lang.github.io/linter/lints/prefer_interpolation_to_compose_strings.html - - prefer_interpolation_to_compose_strings - - # Iterables do not necessary know their length - # pedantic: enabled - # https://dart-lang.github.io/linter/lints/prefer_is_empty.html - - prefer_is_empty - - # Easier to read - # pedantic: enabled - # https://dart-lang.github.io/linter/lints/prefer_is_not_empty.html - - prefer_is_not_empty - - # Use the `foo is! Foo` instead of `!(foo is Foo)` - # https://dart-lang.github.io/linter/lints/prefer_is_not_operator.html - - prefer_is_not_operator - - # Easier to read - # pedantic: enabled - # https://dart-lang.github.io/linter/lints/prefer_iterable_whereType.html - - prefer_iterable_whereType - - # Users of a 3rd party mixins can't change 3rd party code to use the mixin syntax. - # This makes the rule useless - # https://dart-lang.github.io/linter/lints/prefer_mixin.html - # - prefer_mixin - - # Makes expressions with null checks easier to read. - # https://github.com/flutter/flutter/pull/32711#issuecomment-492930932 - - prefer_null_aware_operators - - # Conflicting with `avoid_relative_lib_imports` which is enforced - # https://dart-lang.github.io/linter/lints/prefer_relative_imports.html - # - prefer_relative_imports - - # Use whatever makes you happy. noexcuse doesn't define a style - # pedantic: enabled - # https://dart-lang.github.io/linter/lints/prefer_single_quotes.html - # - prefer_single_quotes - - # Allows potential usage of const - # pedantic: enabled - # https://dart-lang.github.io/linter/lints/prefer_spread_collections.html - - prefer_spread_collections - - # Define types - # pedantic: disabled - # https://dart-lang.github.io/linter/lints/prefer_typing_uninitialized_variables.html - - prefer_typing_uninitialized_variables - - # Null is not a type, use void - # https://dart-lang.github.io/linter/lints/prefer_void_to_null.html - - prefer_void_to_null - - # Document the replacement API - # https://dart-lang.github.io/linter/lints/provide_deprecation_message.html - - provide_deprecation_message - - # Definitely not a rule for standard dart code. Maybe relevant for packages - # https://dart-lang.github.io/linter/lints/public_member_api_docs.html - # - public_member_api_docs - - # Hints accidental recursions - # pedantic: enabled - # https://dart-lang.github.io/linter/lints/recursive_getters.html - - recursive_getters - - # Flutter only, prefer SizedBox over Container which offers a const constructors - # Dart SDK: >= 2.9.0-4.0.dev • (Linter v0.1.115) - # https://dart-lang.github.io/linter/lints/sized_box_for_whitespace.html - - sized_box_for_whitespace - - # Follow dart style use triple slashes - # pedantic: enabled - # https://dart-lang.github.io/linter/lints/slash_for_doc_comments.html - - slash_for_doc_comments - - # Flutter only, always put child last - # pedantic: enabled - # https://dart-lang.github.io/linter/lints/sort_child_properties_last.html - - sort_child_properties_last - - # Working, results in consistent code. But too opinionated - # Discussion: https://github.com/passsy/dart-lint/issues/1 - # - # pedantic: disabled - # https://dart-lang.github.io/linter/lints/sort_constructors_first.html - # - sort_constructors_first - - # Any sorting is better than no sorting - # https://dart-lang.github.io/linter/lints/sort_pub_dependencies.html - # - sort_pub_dependencies - - # Default constructor comes first. - # pedantic: disabled - # https://dart-lang.github.io/linter/lints/sort_unnamed_constructors_first.html - - sort_unnamed_constructors_first - - # First test, then cast - # pedantic: disabled - # https://dart-lang.github.io/linter/lints/test_types_in_equals.html - - test_types_in_equals - - # Hard to debug and bad style - # pedantic: disabled - # https://dart-lang.github.io/linter/lints/throw_in_finally.html - - throw_in_finally - - # Help the compiler at compile time with non-null asserts rather than crashing at runtime - # Dart SDK: >= 2.11.0-182.0.dev • (Linter v0.1.120) - # https://dart-lang.github.io/linter/lints/tighten_type_of_initializing_formals.html - - tighten_type_of_initializing_formals - - # Type annotations make the compiler intelligent, use them - # https://dart-lang.github.io/linter/lints/type_annotate_public_apis.html - - type_annotate_public_apis - - # Don't add types for already typed constructor parameters. - # pedantic: enabled - # https://dart-lang.github.io/linter/lints/type_init_formals.html - - type_init_formals - - # Too many false positives. - # Using the pedantic package for the unawaited function doesn't make code better readable - # - # pedantic: enabled - # https://dart-lang.github.io/linter/lints/unawaited_futures.html - # - unawaited_futures - - # Remove async/await clutter when not required - # https://dart-lang.github.io/linter/lints/unnecessary_await_in_return.html - - unnecessary_await_in_return - - # Remove unnecessary braces - # pedantic: enabled - # https://dart-lang.github.io/linter/lints/unnecessary_brace_in_string_interps.html - - unnecessary_brace_in_string_interps - - # Yes, const everywhere. But not in an already const scope - # pedantic: enabled - # https://dart-lang.github.io/linter/lints/unnecessary_const.html - - unnecessary_const - - # Disabled because `final` prevents accidental reassignment - # https://dart-lang.github.io/linter/lints/unnecessary_final.html - # - unnecessary_final - - # Getter/setters can be added later on in a non API breaking manner - # pedantic: enabled - # https://dart-lang.github.io/linter/lints/unnecessary_getters_setters.html - - unnecessary_getters_setters - - # Flutter setState is a good example where a lambda should always be used. - # https://github.com/dart-lang/linter/issues/498 - # - # Some generic code sometimes requires lambdas, otherwise the generic type isn't forwarded correctly. - # - # https://dart-lang.github.io/linter/lints/unnecessary_lambdas.html - # - unnecessary_lambdas - - # Remove the optional `new` keyword - # pedantic: enabled - # https://dart-lang.github.io/linter/lints/unnecessary_new.html - - unnecessary_new - - # Don't assign `null` when value is already `null`. - # pedantic: disabled - # https://dart-lang.github.io/linter/lints/unnecessary_null_aware_assignments.html - - unnecessary_null_aware_assignments - - # Remove ! when already non-nullable - # Dart SDK: >= 2.10.0-144.0.dev • (Linter v0.1.119) - # https://dart-lang.github.io/linter/lints/unnecessary_null_checks.html - - unnecessary_null_checks - - # Don't assign `null` when value is already `null`. - # pedantic: enabled - # https://dart-lang.github.io/linter/lints/unnecessary_null_in_if_null_operators.html - - unnecessary_null_in_if_null_operators - - # If a variable doesn't change and is initialized, no need to define it as nullable (NNDB) - # Dart SDK: >= 2.10.0-10.0.dev • (Linter v0.1.118) - # https://dart-lang.github.io/linter/lints/unnecessary_nullable_for_final_variable_declarations.html - - unnecessary_nullable_for_final_variable_declarations - - # Remove overrides which simply call super - # https://dart-lang.github.io/linter/lints/unnecessary_overrides.html - - unnecessary_overrides - - # Remove clutter where possible - # https://dart-lang.github.io/linter/lints/unnecessary_parenthesis.html - - unnecessary_parenthesis - - # Use raw string only when needed - # Dart SDK: >= 2.8.0-dev.11.0 • (Linter v0.1.111) - # https://dart-lang.github.io/linter/lints/unnecessary_raw_strings.html - - unnecessary_raw_strings - - # Avoid magic overloads of + operators - # https://dart-lang.github.io/linter/lints/unnecessary_statements.html - - unnecessary_statements - - # Remove unnecessary escape characters - # Dart SDK: >= 2.8.0-dev.11.0 • (Linter v0.1.111) - # https://dart-lang.github.io/linter/lints/unnecessary_string_escapes.html - - unnecessary_string_escapes - - # Completely unnecessary code, simplify to save a few CPU cycles - # Dart SDK: >= 2.8.0-dev.10.0 • (Linter v0.1.110) - # https://dart-lang.github.io/linter/lints/unnecessary_string_interpolations.html - - unnecessary_string_interpolations - - # The variable is clear, remove clutter - # pedantic: enabled - # https://dart-lang.github.io/linter/lints/unnecessary_this.html - - unnecessary_this - - # Highlights potential bugs where unrelated types are compared with another. (always *not* equal). - # pedantic: enabled - # https://dart-lang.github.io/linter/lints/unrelated_type_equality_checks.html - - unrelated_type_equality_checks - - # Web only - # pedantic: enabled - # https://dart-lang.github.io/linter/lints/unsafe_html.html - - unsafe_html - - # Always use hex syntax Color(0x00000001), never Color(1) - # pedantic: enabled - # https://dart-lang.github.io/linter/lints/use_full_hex_values_for_flutter_colors.html - - use_full_hex_values_for_flutter_colors - - # Always use generic function type syntax, don't mix styles - # pedantic: enabled - # https://dart-lang.github.io/linter/lints/use_function_type_syntax_for_parameters.html - - use_function_type_syntax_for_parameters - - # Adding a key without using it isn't helpful in applications, only for the Flutter SDK - # Dart SDK: >= 2.8.0-dev.1.0 • (Linter v0.1.108) - # https://dart-lang.github.io/linter/lints/use_key_in_widget_constructors.html - # - use_key_in_widget_constructors - - # Some might argue late is a code smell, this lint is very opinionated. It triggers only for private fields and - # therefore might actually cleanup some code. - # There is no performance impact either way https://github.com/dart-lang/linter/pull/2189#discussion_r457945301 - # Dart SDK: >= 2.10.0-10.0.dev • (Linter v0.1.118) - # https://dart-lang.github.io/linter/lints/use_late_for_private_fields_and_variables.html - - use_late_for_private_fields_and_variables - - # Use rethrow to preserve the original stacktrace. - # https://dart.dev/guides/language/effective-dart/usage#do-use-rethrow-to-rethrow-a-caught-exception - # pedantic: enabled - # https://dart-lang.github.io/linter/lints/use_rethrow_when_possible.html - - use_rethrow_when_possible - - # Use the setter syntax - # pedantic: disabled - # https://dart-lang.github.io/linter/lints/use_setters_to_change_properties.html - - use_setters_to_change_properties - - # In most cases, using a string buffer is preferred for composing strings due to its improved performance. - # https://dart-lang.github.io/linter/lints/use_string_buffers.html - - use_string_buffers - - # Naming is hard, strict rules don't help - # pedantic: disabled - # https://dart-lang.github.io/linter/lints/use_to_and_as_if_applicable.html - # - use_to_and_as_if_applicable - - # Catches invalid regular expressions. - # pedantic: enabled - # https://dart-lang.github.io/linter/lints/valid_regexps.html - - valid_regexps - - # Don't assign anything to void - # https://dart-lang.github.io/linter/lints/void_checks.html - - void_checks \ No newline at end of file diff --git a/packages/filter_list-1.0.3/lib/filter_list.dart b/packages/filter_list-1.0.3/lib/filter_list.dart deleted file mode 100644 index 9f46622c2..000000000 --- a/packages/filter_list-1.0.3/lib/filter_list.dart +++ /dev/null @@ -1,6 +0,0 @@ -library filter_list; - -export 'src/filter_list_delegate.dart'; -export 'src/filter_list_dialog.dart'; -export 'src/theme/theme.dart'; -export 'src/widget/choice_list.dart'; diff --git a/packages/filter_list-1.0.3/pubspec.lock b/packages/filter_list-1.0.3/pubspec.lock deleted file mode 100644 index ab2656643..000000000 --- a/packages/filter_list-1.0.3/pubspec.lock +++ /dev/null @@ -1,205 +0,0 @@ -# Generated by pub -# See https://dart.dev/tools/pub/glossary#lockfile -packages: - async: - dependency: transitive - description: - name: async - sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" - url: "https://pub.dev" - source: hosted - version: "2.11.0" - boolean_selector: - dependency: transitive - description: - name: boolean_selector - sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" - url: "https://pub.dev" - source: hosted - version: "2.1.1" - characters: - dependency: transitive - description: - name: characters - sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" - url: "https://pub.dev" - source: hosted - version: "1.3.0" - clock: - dependency: transitive - description: - name: clock - sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf - url: "https://pub.dev" - source: hosted - version: "1.1.1" - collection: - dependency: transitive - description: - name: collection - sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a - url: "https://pub.dev" - source: hosted - version: "1.18.0" - fake_async: - dependency: transitive - description: - name: fake_async - sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" - url: "https://pub.dev" - source: hosted - version: "1.3.1" - flutter: - dependency: "direct main" - description: flutter - source: sdk - version: "0.0.0" - flutter_lints: - dependency: "direct dev" - description: - name: flutter_lints - sha256: "9e8c3858111da373efc5aa341de011d9bd23e2c5c5e0c62bccf32438e192d7b1" - url: "https://pub.dev" - source: hosted - version: "3.0.2" - flutter_test: - dependency: "direct dev" - description: flutter - source: sdk - version: "0.0.0" - leak_tracker: - dependency: transitive - description: - name: leak_tracker - sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a" - url: "https://pub.dev" - source: hosted - version: "10.0.4" - leak_tracker_flutter_testing: - dependency: transitive - description: - name: leak_tracker_flutter_testing - sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8" - url: "https://pub.dev" - source: hosted - version: "3.0.3" - leak_tracker_testing: - dependency: transitive - description: - name: leak_tracker_testing - sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" - url: "https://pub.dev" - source: hosted - version: "3.0.1" - lints: - dependency: transitive - description: - name: lints - sha256: cbf8d4b858bb0134ef3ef87841abdf8d63bfc255c266b7bf6b39daa1085c4290 - url: "https://pub.dev" - source: hosted - version: "3.0.0" - matcher: - dependency: transitive - description: - name: matcher - sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb - url: "https://pub.dev" - source: hosted - version: "0.12.16+1" - material_color_utilities: - dependency: transitive - description: - name: material_color_utilities - sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" - url: "https://pub.dev" - source: hosted - version: "0.8.0" - meta: - dependency: transitive - description: - name: meta - sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136" - url: "https://pub.dev" - source: hosted - version: "1.12.0" - path: - dependency: transitive - description: - name: path - sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" - url: "https://pub.dev" - source: hosted - version: "1.9.0" - sky_engine: - dependency: transitive - description: flutter - source: sdk - version: "0.0.99" - source_span: - dependency: transitive - description: - name: source_span - sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" - url: "https://pub.dev" - source: hosted - version: "1.10.0" - stack_trace: - dependency: transitive - description: - name: stack_trace - sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" - url: "https://pub.dev" - source: hosted - version: "1.11.1" - stream_channel: - dependency: transitive - description: - name: stream_channel - sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 - url: "https://pub.dev" - source: hosted - version: "2.1.2" - string_scanner: - dependency: transitive - description: - name: string_scanner - sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" - url: "https://pub.dev" - source: hosted - version: "1.2.0" - term_glyph: - dependency: transitive - description: - name: term_glyph - sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 - url: "https://pub.dev" - source: hosted - version: "1.2.1" - test_api: - dependency: transitive - description: - name: test_api - sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f" - url: "https://pub.dev" - source: hosted - version: "0.7.0" - vector_math: - dependency: transitive - description: - name: vector_math - sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" - url: "https://pub.dev" - source: hosted - version: "2.1.4" - vm_service: - dependency: transitive - description: - name: vm_service - sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec" - url: "https://pub.dev" - source: hosted - version: "14.2.1" -sdks: - dart: ">=3.3.3 <4.0.0" - flutter: ">=3.18.0-18.0.pre.54" diff --git a/packages/filter_list-1.0.3/pubspec.yaml b/packages/filter_list-1.0.3/pubspec.yaml deleted file mode 100644 index 2dc587f7a..000000000 --- a/packages/filter_list-1.0.3/pubspec.yaml +++ /dev/null @@ -1,54 +0,0 @@ -name: filter_list -description: Filter_list Package is designed to make single/multiple item selection from a list of string/object. -version: 1.0.3 -homepage: https://github.com/TheAlphamerc/flutter_plugin_filter_list - -environment: - sdk: ">=3.3.3 <4.0.0" - flutter: ">=1.17.0" - -dependencies: - flutter: - sdk: flutter - -dev_dependencies: - flutter_test: - sdk: flutter - flutter_lints: ^3.0.0 - -# For information on the generic Dart part of this file, see the -# following page: https://dart.dev/tools/pub/pubspec - -# The following section is specific to Flutter packages. -flutter: - - # To add assets to your package, add an assets section, like this: - # assets: - # - images/a_dot_burr.jpeg - # - images/a_dot_ham.jpeg - # - # For details regarding assets in packages, see - # https://flutter.dev/assets-and-images/#from-packages - # - # An image asset can refer to one or more resolution-specific "variants", see - # https://flutter.dev/assets-and-images/#resolution-aware - - # To add custom fonts to your package, add a fonts section here, - # in this "flutter" section. Each entry in this list should have a - # "family" key with the font family name, and a "fonts" key with a - # list giving the asset and other descriptors for the font. For - # example: - # fonts: - # - family: Schyler - # fonts: - # - asset: fonts/Schyler-Regular.ttf - # - asset: fonts/Schyler-Italic.ttf - # style: italic - # - family: Trajan Pro - # fonts: - # - asset: fonts/TrajanPro.ttf - # - asset: fonts/TrajanPro_Bold.ttf - # weight: 700 - # - # For details regarding fonts in packages, see - # https://flutter.dev/custom-fonts/#from-packages diff --git a/packages/filter_list-1.0.3/test/filter_list_test.dart b/packages/filter_list-1.0.3/test/filter_list_test.dart deleted file mode 100644 index 607a5a289..000000000 --- a/packages/filter_list-1.0.3/test/filter_list_test.dart +++ /dev/null @@ -1,11 +0,0 @@ -import 'package:flutter_test/flutter_test.dart'; - -void main() { - test('adds one to input values', () { - // final calculator = Calculator(); - // expect(calculator.addOne(2), 3); - // expect(calculator.addOne(-7), -6); - // expect(calculator.addOne(0), 1); - // expect(() => calculator.addOne(null), throwsNoSuchMethodError); - }); -} diff --git a/pubspec.lock b/pubspec.lock index 2dd4925e4..ac471233c 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -73,6 +73,70 @@ packages: url: "https://pub.dev" source: hosted version: "2.4.1" + build_cli_annotations: + dependency: transitive + description: + name: build_cli_annotations + sha256: b59d2769769efd6c9ff6d4c4cede0be115a566afc591705c2040b707534b1172 + url: "https://pub.dev" + source: hosted + version: "2.1.0" + build_config: + dependency: transitive + description: + name: build_config + sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1 + url: "https://pub.dev" + source: hosted + version: "1.1.1" + build_daemon: + dependency: transitive + description: + name: build_daemon + sha256: "79b2aef6ac2ed00046867ed354c88778c9c0f029df8a20fe10b5436826721ef9" + url: "https://pub.dev" + source: hosted + version: "4.0.2" + build_resolvers: + dependency: transitive + description: + name: build_resolvers + sha256: "339086358431fa15d7eca8b6a36e5d783728cf025e559b834f4609a1fcfb7b0a" + url: "https://pub.dev" + source: hosted + version: "2.4.2" + build_runner: + dependency: "direct dev" + description: + name: build_runner + sha256: "644dc98a0f179b872f612d3eb627924b578897c629788e858157fa5e704ca0c7" + url: "https://pub.dev" + source: hosted + version: "2.4.11" + build_runner_core: + dependency: transitive + description: + name: build_runner_core + sha256: e3c79f69a64bdfcd8a776a3c28db4eb6e3fb5356d013ae5eb2e52007706d5dbe + url: "https://pub.dev" + source: hosted + version: "7.3.1" + built_collection: + dependency: transitive + description: + name: built_collection + sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100" + url: "https://pub.dev" + source: hosted + version: "5.1.1" + built_value: + dependency: transitive + description: + name: built_value + sha256: c7913a9737ee4007efedaffc968c049fd0f3d0e49109e778edc10de9426005cb + url: "https://pub.dev" + source: hosted + version: "8.9.2" characters: dependency: transitive description: @@ -105,6 +169,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.1" + code_builder: + dependency: transitive + description: + name: code_builder + sha256: f692079e25e7869c14132d39f223f8eec9830eb76131925143b2129c4bb01b37 + url: "https://pub.dev" + source: hosted + version: "4.10.0" collection: dependency: transitive description: @@ -146,13 +218,13 @@ packages: source: hosted version: "0.3.4+1" crypto: - dependency: transitive + dependency: "direct main" description: name: crypto - sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab + sha256: ec30d999af904f33454ba22ed9a86162b35e52b44ac4807d1d93c288041d7d27 url: "https://pub.dev" source: hosted - version: "3.0.3" + version: "3.0.5" csslib: dependency: transitive description: @@ -236,10 +308,19 @@ packages: filter_list: dependency: "direct main" description: - path: "packages/filter_list-1.0.3" - relative: true - source: path + name: filter_list + sha256: "5b2bdfcf37ebe0730b0b46d59ca2091a1dd7a3a6df39c0fbdfa5ea165903d1e1" + url: "https://pub.dev" + source: hosted version: "1.0.3" + fixnum: + dependency: transitive + description: + name: fixnum + sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1" + url: "https://pub.dev" + source: hosted + version: "1.1.0" flutter: dependency: "direct main" description: flutter @@ -298,6 +379,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.17" + flutter_rust_bridge: + dependency: transitive + description: + name: flutter_rust_bridge + sha256: b0271cc147d5afccf9774809e4eef52b7357babe1a1a31db649df6f02dd27580 + url: "https://pub.dev" + source: hosted + version: "2.3.0" flutter_settings_screens: dependency: "direct main" description: @@ -356,6 +445,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.2" + graphs: + dependency: transitive + description: + name: graphs + sha256: "741bbf84165310a68ff28fe9e727332eef1407342fca52759cb21ad8177bb8d0" + url: "https://pub.dev" + source: hosted + version: "2.3.2" hive: dependency: "direct main" description: @@ -373,13 +470,13 @@ packages: source: hosted version: "0.15.4" http: - dependency: transitive + dependency: "direct main" description: name: http - sha256: "761a297c042deedc1ffbb156d6e2af13886bb305c2a343a4d972504cd67dd938" + sha256: b9c29a161230ee03d3ccf545097fccd9b87a5264228c5d348202e0f0c28f9010 url: "https://pub.dev" source: hosted - version: "1.2.1" + version: "1.2.2" http_multi_server: dependency: transitive description: @@ -421,7 +518,7 @@ packages: source: hosted version: "1.0.4" isar: - dependency: transitive + dependency: "direct main" description: name: isar sha256: ebf74d87c400bd9f7da14acb31932b50c2407edbbd40930da3a6c2a8143f85a8 @@ -812,6 +909,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" + pubspec_parse: + dependency: transitive + description: + name: pubspec_parse + sha256: c799b721d79eb6ee6fa56f00c04b472dcd44a30d258fac2174a6ec57302678f8 + url: "https://pub.dev" + source: hosted + version: "1.3.0" qr: dependency: transitive description: @@ -844,6 +949,13 @@ packages: url: "https://pub.dev" source: hosted version: "0.3.8" + search_engine: + dependency: "direct main" + description: + path: "../search_engine" + relative: true + source: path + version: "0.0.1" search_highlight_text: dependency: "direct main" description: @@ -993,6 +1105,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.2" + stream_transform: + dependency: transitive + description: + name: stream_transform + sha256: "14a00e794c7c11aa145a170587321aedce29769c08d7f58b1d141da75e3b1c6f" + url: "https://pub.dev" + source: hosted + version: "2.1.0" string_scanner: dependency: transitive description: @@ -1041,6 +1161,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.6.0" + timing: + dependency: transitive + description: + name: timing + sha256: "70a3b636575d4163c477e6de42f247a23b315ae20e86442bebe32d3cabf61c32" + url: "https://pub.dev" + source: hosted + version: "1.0.1" typed_data: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 2d996fa2a..eff588c74 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -8,7 +8,7 @@ msix_config: display_name: אוצריא publisher_display_name: sivan22 identity_name: sivan22.Otzaria - msix_version: 0.1.8.10 + msix_version: 0.2.1.1 logo_path: assets/icon/icon.png publisher: CN=sivan22, O=sivan22, C=IL certificate_path: C:\dev\sivan22.pfx @@ -33,7 +33,7 @@ msix_config: # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 0.1.8 +version: 0.2.1-alpha.1 environment: sdk: ">=3.2.6 <4.0.0" @@ -51,7 +51,8 @@ dependencies: sdk: flutter flutter_settings_screens: ^0.3.4 hive: ^4.0.0-dev.2 - isar_flutter_libs: ^4.0.0-dev.13 + isar_flutter_libs: ^4.0.0-dev.14 + isar: ^4.0.0-dev.14 msix: ^3.16.7 path_provider: ^2.0.15 html: ^0.15.1 @@ -75,9 +76,13 @@ dependencies: kosher_dart: ^2.0.16 gematria: ^1.0.0 csv: ^6.0.0 - filter_list: - path: packages/filter_list-1.0.3 + + filter_list: 1.0.3 package_info_plus: ^8.0.2 + crypto: ^3.0.5 + http: ^1.2.2 + search_engine: + path: ../search_engine dependency_overrides: # it forces the version of the intl package to be 0.19.0 across all dependencies, even if some packages specify a different compatible version. intl: ^0.19.0 @@ -103,6 +108,7 @@ dev_dependencies: # rules and activating additional ones. flutter_lints: ^2.0.0 test: ^1.25.2 + build_runner: ^2.4.11 # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index ae5ff8543..bf56c4834 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -13,6 +13,7 @@ list(APPEND FLUTTER_PLUGIN_LIST list(APPEND FLUTTER_FFI_PLUGIN_LIST pdfrx + search_engine ) set(PLUGIN_BUNDLED_LIBRARIES)