diff --git a/app/src/main/java/org/kiwix/kiwixmobile/main/KiwixMainActivity.kt b/app/src/main/java/org/kiwix/kiwixmobile/main/KiwixMainActivity.kt index 0d00e9198..234570a93 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/main/KiwixMainActivity.kt +++ b/app/src/main/java/org/kiwix/kiwixmobile/main/KiwixMainActivity.kt @@ -55,6 +55,7 @@ class KiwixMainActivity : CoreMainActivity() { override val bookmarksFragmentResId: Int = R.id.bookmarksFragment override val settingsFragmentResId: Int = R.id.kiwixSettingsFragment override val historyFragmentResId: Int = R.id.historyFragment + override val notesFragmentResId: Int = R.id.notesFragment override val readerFragmentResId: Int = R.id.readerFragment override val helpFragmentResId: Int = R.id.helpFragment override val topLevelDestinations = diff --git a/app/src/main/res/navigation/kiwix_nav_graph.xml b/app/src/main/res/navigation/kiwix_nav_graph.xml index c88915bc3..c91ae56e4 100644 --- a/app/src/main/res/navigation/kiwix_nav_graph.xml +++ b/app/src/main/res/navigation/kiwix_nav_graph.xml @@ -86,6 +86,11 @@ android:name="org.kiwix.kiwixmobile.core.page.bookmark.BookmarksFragment" android:label="BookmarksFragment" tools:layout="@layout/fragment_page" /> + + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package org.kiwix.kiwixmobile.core.dao + +import io.objectbox.Box +import io.objectbox.kotlin.query +import io.reactivex.Flowable +import org.kiwix.kiwixmobile.core.dao.entities.NotesEntity +import org.kiwix.kiwixmobile.core.dao.entities.NotesEntity_ +import org.kiwix.kiwixmobile.core.page.adapter.Page +import org.kiwix.kiwixmobile.core.page.notes.adapter.NoteListItem +import javax.inject.Inject + +class NewNoteDao @Inject constructor(val box: Box) : PageDao { + fun notes(): Flowable> = box.asFlowable( + box.query { + order(NotesEntity_.noteTitle) + } + ).map { it.map(::NoteListItem) } + + override fun pages(): Flowable> = notes() + + override fun deletePages(pagesToDelete: List) = + deleteNotes(pagesToDelete as List) + + fun saveNote(noteItem: NoteListItem) { + box.put(NotesEntity(noteItem)) + } + + fun deleteNotes(noteList: List) { + box.remove(noteList.map(::NotesEntity)) + } + + fun deleteNote(noteUniqueKey: String) { + box.query { + equal(NotesEntity_.noteTitle, noteUniqueKey) + }.remove() + } +} diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/NotesEntity.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/NotesEntity.kt new file mode 100644 index 000000000..92af24604 --- /dev/null +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/NotesEntity.kt @@ -0,0 +1,46 @@ +/* + * Kiwix Android + * Copyright (c) 2022 Kiwix + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package org.kiwix.kiwixmobile.core.dao.entities + +import io.objectbox.annotation.Entity +import io.objectbox.annotation.Id +import io.objectbox.annotation.Unique +import org.kiwix.kiwixmobile.core.page.notes.adapter.NoteListItem + +@Entity +data class NotesEntity( + @Id var id: Long = 0L, + val zimId: String, + var zimFilePath: String?, + val zimUrl: String, + @Unique + var noteTitle: String, + var noteFilePath: String, + var favicon: String? +) { + constructor(item: NoteListItem) : this( + id = item.databaseId, + zimId = item.zimId, + zimFilePath = item.zimFilePath, + zimUrl = item.zimUrl, + noteTitle = item.title, + noteFilePath = item.noteFilePath, + favicon = item.favicon + ) +} diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/data/DataSource.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/data/DataSource.kt index db64071d2..e9d4b24e8 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/data/DataSource.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/data/DataSource.kt @@ -23,6 +23,7 @@ import io.reactivex.Single import org.kiwix.kiwixmobile.core.page.bookmark.adapter.BookmarkItem import org.kiwix.kiwixmobile.core.page.history.adapter.HistoryListItem import org.kiwix.kiwixmobile.core.page.history.adapter.HistoryListItem.HistoryItem +import org.kiwix.kiwixmobile.core.page.notes.adapter.NoteListItem import org.kiwix.kiwixmobile.core.zim_manager.Language import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.adapter.BooksOnDiskListItem import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.adapter.BooksOnDiskListItem.BookOnDisk @@ -46,4 +47,8 @@ interface DataSource { fun deleteBookmarks(bookmarks: List): Completable fun deleteBookmark(bookmarkUrl: String): Completable? fun booksOnDiskAsListItems(): Flowable> + + fun saveNote(noteListItem: NoteListItem): Completable + fun deleteNote(noteUniqueKey: String): Completable + fun deleteNotes(noteList: List): Completable } diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/data/Repository.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/data/Repository.kt index e5bfb6e0b..2aaf489cb 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/data/Repository.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/data/Repository.kt @@ -26,6 +26,7 @@ import org.kiwix.kiwixmobile.core.dao.HistoryDao import org.kiwix.kiwixmobile.core.dao.NewBookDao import org.kiwix.kiwixmobile.core.dao.NewBookmarksDao import org.kiwix.kiwixmobile.core.dao.NewLanguagesDao +import org.kiwix.kiwixmobile.core.dao.NewNoteDao import org.kiwix.kiwixmobile.core.dao.NewRecentSearchDao import org.kiwix.kiwixmobile.core.di.qualifiers.IO import org.kiwix.kiwixmobile.core.di.qualifiers.MainThread @@ -33,6 +34,7 @@ import org.kiwix.kiwixmobile.core.extensions.HeaderizableList import org.kiwix.kiwixmobile.core.page.bookmark.adapter.BookmarkItem import org.kiwix.kiwixmobile.core.page.history.adapter.HistoryListItem import org.kiwix.kiwixmobile.core.page.history.adapter.HistoryListItem.HistoryItem +import org.kiwix.kiwixmobile.core.page.notes.adapter.NoteListItem import org.kiwix.kiwixmobile.core.reader.ZimReaderContainer import org.kiwix.kiwixmobile.core.zim_manager.Language import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.adapter.BooksOnDiskListItem @@ -45,6 +47,7 @@ import javax.inject.Singleton * A central repository of data which should provide the presenters with the required data. */ +@Suppress("LongParameterList") @Singleton class Repository @Inject internal constructor( @param:IO private val io: Scheduler, @@ -52,6 +55,7 @@ class Repository @Inject internal constructor( private val bookDao: NewBookDao, private val bookmarksDao: NewBookmarksDao, private val historyDao: HistoryDao, + private val notesDao: NewNoteDao, private val languageDao: NewLanguagesDao, private val recentSearchDao: NewRecentSearchDao, private val zimReaderContainer: ZimReaderContainer @@ -71,7 +75,7 @@ class Repository @Inject internal constructor( { current, next -> current.locale.displayName != next.locale.displayName } ) } - .map { it.toList() } + .map(MutableList::toList) override fun saveBooks(books: List) = Completable.fromAction { bookDao.insert(books) } @@ -118,4 +122,16 @@ class Repository @Inject internal constructor( override fun deleteBookmark(bookmarkUrl: String): Completable? = Completable.fromAction { bookmarksDao.deleteBookmark(bookmarkUrl) } .subscribeOn(io) + + override fun saveNote(noteListItem: NoteListItem): Completable = + Completable.fromAction { notesDao.saveNote(noteListItem) } + .subscribeOn(io) + + override fun deleteNotes(noteList: List) = + Completable.fromAction { notesDao.deleteNotes(noteList) } + .subscribeOn(io) + + override fun deleteNote(noteUniqueKey: String): Completable = + Completable.fromAction { notesDao.deleteNote(noteUniqueKey) } + .subscribeOn(io) } diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/data/local/KiwixDatabase.java b/core/src/main/java/org/kiwix/kiwixmobile/core/data/local/KiwixDatabase.java index 7b1f72e24..daf5b4285 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/data/local/KiwixDatabase.java +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/data/local/KiwixDatabase.java @@ -179,7 +179,7 @@ public class KiwixDatabase extends SquidDatabase { public void migrateBookmarksVersion6() { String[] ids = context.fileList(); for (String id : ids) { - if (id.length() == 40 && id.substring(id.length() - 4).equals(".txt")) { + if (id.length() == 40 && id.endsWith(".txt")) { try { String idName = id.substring(0, id.length() - 4); InputStream stream = context.openFileInput(id); diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/di/components/CoreActivityComponent.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/di/components/CoreActivityComponent.kt index 1fc00a639..4cb6b27ba 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/di/components/CoreActivityComponent.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/di/components/CoreActivityComponent.kt @@ -29,6 +29,9 @@ import org.kiwix.kiwixmobile.core.page.bookmark.BookmarksFragment import org.kiwix.kiwixmobile.core.page.bookmark.viewmodel.effects.ShowDeleteBookmarksDialog import org.kiwix.kiwixmobile.core.page.history.HistoryFragment import org.kiwix.kiwixmobile.core.page.history.viewmodel.effects.ShowDeleteHistoryDialog +import org.kiwix.kiwixmobile.core.page.notes.NotesFragment +import org.kiwix.kiwixmobile.core.page.notes.viewmodel.effects.ShowDeleteNotesDialog +import org.kiwix.kiwixmobile.core.page.notes.viewmodel.effects.ShowOpenNoteDialog import org.kiwix.kiwixmobile.core.search.SearchFragment import org.kiwix.kiwixmobile.core.search.viewmodel.effects.ShowDeleteSearchDialog import org.kiwix.kiwixmobile.core.settings.CorePrefsFragment @@ -40,11 +43,14 @@ interface CoreActivityComponent { fun inject(showDeleteSearchDialog: ShowDeleteSearchDialog) fun inject(showDeleteBookmarksDialog: ShowDeleteBookmarksDialog) fun inject(showDeleteHistoryDialog: ShowDeleteHistoryDialog) + fun inject(showOpenNoteDialog: ShowOpenNoteDialog) + fun inject(showDeleteNotesDialog: ShowDeleteNotesDialog) fun inject(corePrefsFragment: CorePrefsFragment) fun inject(historyFragment: HistoryFragment) fun inject(bookmarksFragment: BookmarksFragment) fun inject(addNoteDialog: AddNoteDialog) fun inject(helpFragment: HelpFragment) + fun inject(notesFragment: NotesFragment) @Subcomponent.Builder interface Builder { diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/di/components/CoreComponent.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/di/components/CoreComponent.kt index 52d1667a6..8edb9a8ab 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/di/components/CoreComponent.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/di/components/CoreComponent.kt @@ -31,6 +31,7 @@ import org.kiwix.kiwixmobile.core.dao.HistoryDao import org.kiwix.kiwixmobile.core.dao.NewBookDao import org.kiwix.kiwixmobile.core.dao.NewBookmarksDao import org.kiwix.kiwixmobile.core.dao.NewLanguagesDao +import org.kiwix.kiwixmobile.core.dao.NewNoteDao import org.kiwix.kiwixmobile.core.dao.NewRecentSearchDao import org.kiwix.kiwixmobile.core.data.DataModule import org.kiwix.kiwixmobile.core.data.DataSource @@ -87,6 +88,7 @@ interface CoreComponent { fun fetchDownloadDao(): FetchDownloadDao fun newBookDao(): NewBookDao fun historyDao(): HistoryDao + fun noteDao(): NewNoteDao fun newLanguagesDao(): NewLanguagesDao fun recentSearchDao(): NewRecentSearchDao fun newBookmarksDao(): NewBookmarksDao diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/di/modules/CoreViewModelModule.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/di/modules/CoreViewModelModule.kt index 397244ab7..0d1067f75 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/di/modules/CoreViewModelModule.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/di/modules/CoreViewModelModule.kt @@ -27,6 +27,7 @@ import org.kiwix.kiwixmobile.core.ViewModelFactory import org.kiwix.kiwixmobile.core.di.ViewModelKey import org.kiwix.kiwixmobile.core.page.bookmark.viewmodel.BookmarkViewModel import org.kiwix.kiwixmobile.core.page.history.viewmodel.HistoryViewModel +import org.kiwix.kiwixmobile.core.page.notes.viewmodel.NotesViewModel import org.kiwix.kiwixmobile.core.search.viewmodel.SearchViewModel @Module @@ -45,6 +46,11 @@ abstract class CoreViewModelModule { @ViewModelKey(HistoryViewModel::class) abstract fun bindHistoryViewModel(historyViewModel: HistoryViewModel): ViewModel + @Binds + @IntoMap + @ViewModelKey(NotesViewModel::class) + abstract fun bindNotesViewModel(notesViewModel: NotesViewModel): ViewModel + @Binds @IntoMap @ViewModelKey(BookmarkViewModel::class) diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/di/modules/DatabaseModule.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/di/modules/DatabaseModule.kt index 6ccd463fd..8f9b957a1 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/di/modules/DatabaseModule.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/di/modules/DatabaseModule.kt @@ -28,6 +28,7 @@ import org.kiwix.kiwixmobile.core.dao.HistoryDao import org.kiwix.kiwixmobile.core.dao.NewBookDao import org.kiwix.kiwixmobile.core.dao.NewBookmarksDao import org.kiwix.kiwixmobile.core.dao.NewLanguagesDao +import org.kiwix.kiwixmobile.core.dao.NewNoteDao import org.kiwix.kiwixmobile.core.dao.NewRecentSearchDao import org.kiwix.kiwixmobile.core.dao.entities.MyObjectBox import javax.inject.Singleton @@ -58,6 +59,9 @@ open class DatabaseModule { @Provides @Singleton fun providesNewBookmarksDao(boxStore: BoxStore): NewBookmarksDao = NewBookmarksDao(boxStore.boxFor()) + @Provides @Singleton fun providesNewNoteDao(boxStore: BoxStore): NewNoteDao = + NewNoteDao(boxStore.boxFor()) + @Provides @Singleton fun providesNewRecentSearchDao( boxStore: BoxStore, flowBuilder: FlowBuilder diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/main/AddNoteDialog.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/main/AddNoteDialog.kt index dae4bc19e..a47b294ee 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/main/AddNoteDialog.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/main/AddNoteDialog.kt @@ -43,6 +43,7 @@ import org.kiwix.kiwixmobile.core.CoreApp.Companion.instance import org.kiwix.kiwixmobile.core.R import org.kiwix.kiwixmobile.core.extensions.closeKeyboard import org.kiwix.kiwixmobile.core.extensions.toast +import org.kiwix.kiwixmobile.core.page.notes.adapter.NoteListItem import org.kiwix.kiwixmobile.core.reader.ZimReaderContainer import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil import org.kiwix.kiwixmobile.core.utils.SimpleTextWatcher @@ -66,8 +67,10 @@ const val DISABLE_ICON_ITEM_ALPHA = 130 const val ENABLE_ICON_ITEM_ALPHA = 255 class AddNoteDialog : DialogFragment() { + private lateinit var zimId: String private var zimFileName: String? = null private var zimFileTitle: String? = null + private lateinit var zimFileUrl: String private var articleTitle: String? = null // Corresponds to "ArticleUrl" of "{External Storage}/Kiwix/Notes/ZimFileName/ArticleUrl.txt" @@ -90,6 +93,9 @@ class AddNoteDialog : DialogFragment() { @Inject lateinit var alertDialogShower: AlertDialogShower + @Inject + lateinit var mainRepositoryActions: MainRepositoryActions + private val saveItem by lazy { toolbar.menu.findItem(R.id.save_note) } private val shareItem by lazy { toolbar.menu.findItem(R.id.share_note) } @@ -108,13 +114,20 @@ class AddNoteDialog : DialogFragment() { zimFileName = zimReaderContainer.zimCanonicalPath if (zimFileName != null) { // No zim file currently opened zimFileTitle = zimReaderContainer.zimFileTitle - articleTitle = (activity as WebViewProvider?)?.getCurrentWebView()?.title + zimId = zimReaderContainer.id.orEmpty() + + if (arguments != null) { + articleTitle = arguments?.getString(NOTES_TITLE) + zimFileUrl = arguments?.getString(ARTICLE_URL).orEmpty() + } else { + val webView = (activity as WebViewProvider?)?.getCurrentWebView() + articleTitle = webView?.title + zimFileUrl = webView?.url.orEmpty() + } // Corresponds to "ZimFileName" of "{External Storage}/Kiwix/Notes/ZimFileName/ArticleUrl.txt" - articleNoteFileName = getArticleNotefileName() + articleNoteFileName = getArticleNoteFileName() zimNotesDirectory = "$NOTES_DIRECTORY$zimNoteDirectoryName/" - } else { - onFailureToCreateAddNoteDialog() } } @@ -140,8 +153,12 @@ class AddNoteDialog : DialogFragment() { return (if (noteDirectoryName.isNotEmpty()) noteDirectoryName else zimFileTitle) ?: "" } - private fun getArticleNotefileName(): String { + private fun getArticleNoteFileName(): String { // Returns url of the form: "content://org.kiwix.kiwixmobile.zim.base/A/Main_Page.html" + arguments?.getString(NOTE_FILE_PATH)?.let { + return@getArticleNoteFileName getTextAfterLastSlashWithoutExtension(it) + } + val articleUrl = (activity as WebViewProvider?)?.getCurrentWebView()?.url var noteFileName = "" if (articleUrl == null) { @@ -149,7 +166,7 @@ class AddNoteDialog : DialogFragment() { } else { noteFileName = getTextAfterLastSlashWithoutExtension(articleUrl) } - return (if (noteFileName.isNotEmpty()) noteFileName else articleTitle) ?: "" + return noteFileName.ifEmpty { articleTitle } ?: "" } /* From ".../Kiwix/granbluefantasy_en_all_all_nopic_2018-10.zim", returns "granbluefantasy_en_all_all_nopic_2018-10" @@ -264,7 +281,6 @@ class AddNoteDialog : DialogFragment() { } private fun saveNote(noteText: String) { - /* String content of the EditText, given by noteText, is saved into the text file given by: * "{External Storage}/Kiwix/Notes/ZimFileTitle/ArticleTitle.txt" * */ @@ -298,12 +314,14 @@ class AddNoteDialog : DialogFragment() { context.toast(R.string.note_save_successful, Toast.LENGTH_SHORT) noteEdited = false // As no unsaved changes remain enableDeleteNoteMenuItem() + // adding only if saving file is success + addNoteToDao(noteFile.canonicalPath, "${zimFileTitle.orEmpty()}: $articleTitle") } catch (e: IOException) { e.printStackTrace() .also { context.toast(R.string.note_save_unsuccessful, Toast.LENGTH_LONG) } } } else { - context.toast(R.string.note_save_successful, Toast.LENGTH_LONG) + context.toast(R.string.note_save_unsuccessful, Toast.LENGTH_LONG) Log.d(TAG, "Required folder doesn't exist") } } else { @@ -311,6 +329,27 @@ class AddNoteDialog : DialogFragment() { } } + private fun addNoteToDao(noteFilePath: String?, title: String) { + noteFilePath?.let { filePath -> + if (filePath.isNotEmpty() && zimFileUrl.isNotEmpty()) { + val zimReader = zimReaderContainer.zimFileReader + if (zimReader != null) { + val noteToSave = NoteListItem( + title = title, + url = zimFileUrl, + noteFilePath = noteFilePath, + zimFileReader = zimReader + ) + mainRepositoryActions.saveNote(noteToSave) + } else { + Log.d(TAG, "zim reader found null") + } + } else { + Log.d(TAG, "Cannot process with empty zim url or noteFilePath") + } + } + } + private fun deleteNote() { val notesFolder = File(zimNotesDirectory) val noteFile = @@ -318,6 +357,7 @@ class AddNoteDialog : DialogFragment() { val noteDeleted = noteFile.delete() if (noteDeleted) { add_note_edit_text.text.clear() + mainRepositoryActions.deleteNote(articleNoteFileName) disableMenuItems() context.toast(R.string.note_delete_successful, Toast.LENGTH_LONG) } else { @@ -330,7 +370,6 @@ class AddNoteDialog : DialogFragment() { * is displayed in the EditText field (note content area) */ private fun displayNote() { - val noteFile = File("$zimNotesDirectory$articleNoteFileName.txt") if (noteFile.exists()) { readNoteFromFile(noteFile) @@ -403,5 +442,8 @@ class AddNoteDialog : DialogFragment() { @JvmField val NOTES_DIRECTORY = instance.getExternalFilesDir("").toString() + "/Kiwix/Notes/" const val TAG = "AddNoteDialog" + const val NOTE_FILE_PATH = "NoteFilePath" + const val ARTICLE_URL = "ArticleUrl" + const val NOTES_TITLE = "NotesTitle" } } diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/main/CoreMainActivity.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/main/CoreMainActivity.kt index 4e00d5381..397d21e34 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/main/CoreMainActivity.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/main/CoreMainActivity.kt @@ -72,6 +72,7 @@ abstract class CoreMainActivity : BaseActivity(), WebViewProvider { abstract val bookmarksFragmentResId: Int abstract val settingsFragmentResId: Int abstract val historyFragmentResId: Int + abstract val notesFragmentResId: Int abstract val helpFragmentResId: Int abstract val cachedComponent: CoreActivityComponent abstract val topLevelDestinations: Set @@ -194,6 +195,7 @@ abstract class CoreMainActivity : BaseActivity(), WebViewProvider { R.id.menu_support_kiwix -> openSupportKiwixExternalLink() R.id.menu_settings -> openSettings() R.id.menu_help -> openHelpFragment() + R.id.menu_notes -> openNotes() R.id.menu_history -> openHistory() R.id.menu_bookmarks_list -> openBookmarks() else -> return false @@ -303,6 +305,10 @@ abstract class CoreMainActivity : BaseActivity(), WebViewProvider { handleDrawerOnNavigation() } + private fun openNotes() { + navigate(notesFragmentResId) + } + protected fun handleDrawerOnNavigation() { closeNavigationDrawer() disableDrawer() diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/main/MainRepositoryActions.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/main/MainRepositoryActions.kt index 0cea23f17..9c417d846 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/main/MainRepositoryActions.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/main/MainRepositoryActions.kt @@ -22,6 +22,7 @@ import org.kiwix.kiwixmobile.core.data.DataSource import org.kiwix.kiwixmobile.core.di.ActivityScope import org.kiwix.kiwixmobile.core.page.bookmark.adapter.BookmarkItem import org.kiwix.kiwixmobile.core.page.history.adapter.HistoryListItem.HistoryItem +import org.kiwix.kiwixmobile.core.page.notes.adapter.NoteListItem import javax.inject.Inject private const val TAG = "MainPresenter" @@ -44,4 +45,14 @@ class MainRepositoryActions @Inject constructor(private val dataSource: DataSour ?.subscribe({}, { e -> Log.e(TAG, "Unable to delete bookmark", e) }) ?: Log.e(TAG, "Unable to delete bookmark") } + + fun saveNote(note: NoteListItem) { + dataSource.saveNote(note) + .subscribe({}, { e -> Log.e(TAG, "Unable to save note", e) }) + } + + fun deleteNote(noteUniqueKey: String) { + dataSource.deleteNote(noteUniqueKey) + .subscribe({}, { e -> Log.e(TAG, "Unable to delete note", e) }) + } } diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/page/notes/NotesFragment.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/page/notes/NotesFragment.kt new file mode 100644 index 000000000..5f4a93df7 --- /dev/null +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/page/notes/NotesFragment.kt @@ -0,0 +1,49 @@ +/* + * Kiwix Android + * Copyright (c) 2020 Kiwix + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package org.kiwix.kiwixmobile.core.page.notes + +import org.kiwix.kiwixmobile.core.R +import org.kiwix.kiwixmobile.core.base.BaseActivity +import org.kiwix.kiwixmobile.core.extensions.ActivityExtensions.cachedComponent +import org.kiwix.kiwixmobile.core.extensions.viewModel +import org.kiwix.kiwixmobile.core.page.PageFragment +import org.kiwix.kiwixmobile.core.page.adapter.PageAdapter +import org.kiwix.kiwixmobile.core.page.adapter.PageDelegate +import org.kiwix.kiwixmobile.core.page.notes.viewmodel.NotesViewModel + +class NotesFragment : PageFragment() { + override val pageViewModel by lazy { viewModel(viewModelFactory) } + + override val screenTitle: String + get() = getString(R.string.pref_notes) + + override val pageAdapter: PageAdapter by lazy { + PageAdapter(PageDelegate.PageItemDelegate(this)) + } + + override val noItemsString: String by lazy { getString(R.string.no_notes) } + override val switchString: String by lazy { getString(R.string.notes_from_all_books) } + override val switchIsChecked: Boolean = true + + override fun inject(baseActivity: BaseActivity) { + baseActivity.cachedComponent.inject(this) + } + + override val searchQueryHint: String by lazy { getString(R.string.search_notes) } +} diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/page/notes/adapter/NoteListItem.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/page/notes/adapter/NoteListItem.kt new file mode 100644 index 000000000..4f40d24cd --- /dev/null +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/page/notes/adapter/NoteListItem.kt @@ -0,0 +1,43 @@ +package org.kiwix.kiwixmobile.core.page.notes.adapter + +import org.kiwix.kiwixmobile.core.dao.entities.NotesEntity +import org.kiwix.kiwixmobile.core.page.adapter.Page +import org.kiwix.kiwixmobile.core.reader.ZimFileReader + +data class NoteListItem( + val databaseId: Long = 0L, + override val zimId: String, + override val title: String, + override val zimFilePath: String?, + val zimUrl: String, + val noteFilePath: String, + override val favicon: String?, + override var isSelected: Boolean = false, + override val url: String = zimUrl, + override val id: Long = databaseId +) : Page { + + constructor(notesEntity: NotesEntity) : this( + notesEntity.id, + notesEntity.zimId, + notesEntity.noteTitle, + notesEntity.zimFilePath, + notesEntity.zimUrl, + notesEntity.noteFilePath, + notesEntity.favicon + ) + + constructor( + title: String, + url: String, + noteFilePath: String, + zimFileReader: ZimFileReader + ) : this( + zimId = zimFileReader.id, + title = title, + zimFilePath = zimFileReader.zimFile.canonicalPath, + zimUrl = url, + favicon = zimFileReader.favicon, + noteFilePath = noteFilePath + ) +} diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/page/notes/viewmodel/NotesState.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/page/notes/viewmodel/NotesState.kt new file mode 100644 index 000000000..948926b77 --- /dev/null +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/page/notes/viewmodel/NotesState.kt @@ -0,0 +1,35 @@ +/* + * Kiwix Android + * Copyright (c) 2020 Kiwix + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package org.kiwix.kiwixmobile.core.page.notes.viewmodel + +import org.kiwix.kiwixmobile.core.page.adapter.PageRelated +import org.kiwix.kiwixmobile.core.page.notes.adapter.NoteListItem +import org.kiwix.kiwixmobile.core.page.viewmodel.PageState + +data class NotesState( + override val pageItems: List, + override val showAll: Boolean, + override val currentZimId: String?, + override val searchTerm: String = "" +) : PageState() { + override val visiblePageItems: List = filteredPageItems + + override fun copyWithNewItems(newItems: List): PageState = + copy(pageItems = newItems) +} diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/page/notes/viewmodel/NotesViewModel.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/page/notes/viewmodel/NotesViewModel.kt new file mode 100644 index 000000000..ad7aa7462 --- /dev/null +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/page/notes/viewmodel/NotesViewModel.kt @@ -0,0 +1,73 @@ +/* + * Kiwix Android + * Copyright (c) 2020 Kiwix + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package org.kiwix.kiwixmobile.core.page.notes.viewmodel + +import org.kiwix.kiwixmobile.core.dao.NewNoteDao +import org.kiwix.kiwixmobile.core.page.adapter.Page +import org.kiwix.kiwixmobile.core.page.notes.adapter.NoteListItem +import org.kiwix.kiwixmobile.core.page.notes.viewmodel.effects.ShowDeleteNotesDialog +import org.kiwix.kiwixmobile.core.page.notes.viewmodel.effects.ShowOpenNoteDialog +import org.kiwix.kiwixmobile.core.page.notes.viewmodel.effects.UpdateAllNotesPreference +import org.kiwix.kiwixmobile.core.page.viewmodel.Action +import org.kiwix.kiwixmobile.core.page.viewmodel.PageViewModel +import org.kiwix.kiwixmobile.core.page.viewmodel.PageViewModelClickListener +import org.kiwix.kiwixmobile.core.reader.ZimReaderContainer +import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil +import javax.inject.Inject + +class NotesViewModel @Inject constructor( + notesDao: NewNoteDao, + zimReaderContainer: ZimReaderContainer, + sharedPrefs: SharedPreferenceUtil +) : PageViewModel(notesDao, sharedPrefs, zimReaderContainer), + PageViewModelClickListener { + + init { + setOnItemClickListener(this) + } + + override fun initialState(): NotesState = + NotesState(emptyList(), sharedPreferenceUtil.showNotesAllBooks, zimReaderContainer.id) + + override fun updatePagesBasedOnFilter(state: NotesState, action: Action.Filter): NotesState = + state.copy(searchTerm = action.searchTerm) + + override fun updatePages(state: NotesState, action: Action.UpdatePages): NotesState = + state.copy(pageItems = action.pages.filterIsInstance()) + + override fun offerUpdateToShowAllToggle( + action: Action.UserClickedShowAllToggle, + state: NotesState + ): NotesState { + effects.offer(UpdateAllNotesPreference(sharedPreferenceUtil, action.isChecked)) + return state.copy(showAll = action.isChecked) + } + + override fun copyWithNewItems(state: NotesState, newItems: List): NotesState = + state.copy(pageItems = newItems) + + override fun deselectAllPages(state: NotesState): NotesState = + state.copy(pageItems = state.pageItems.map { it.copy(isSelected = false) }) + + override fun createDeletePageDialogEffect(state: NotesState) = + ShowDeleteNotesDialog(effects, state, pageDao) + + override fun onItemClick(page: Page) = + ShowOpenNoteDialog(effects, page, zimReaderContainer) +} diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/page/notes/viewmodel/effects/ShowDeleteNotesDialog.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/page/notes/viewmodel/effects/ShowDeleteNotesDialog.kt new file mode 100644 index 000000000..957c4ded2 --- /dev/null +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/page/notes/viewmodel/effects/ShowDeleteNotesDialog.kt @@ -0,0 +1,50 @@ +package org.kiwix.kiwixmobile.core.page.notes.viewmodel.effects + +/* + * Kiwix Android + * Copyright (c) 2020 Kiwix + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +import android.util.Log +import androidx.appcompat.app.AppCompatActivity +import io.reactivex.processors.PublishProcessor +import org.kiwix.kiwixmobile.core.base.SideEffect +import org.kiwix.kiwixmobile.core.dao.PageDao +import org.kiwix.kiwixmobile.core.extensions.ActivityExtensions.cachedComponent +import org.kiwix.kiwixmobile.core.page.notes.viewmodel.NotesState +import org.kiwix.kiwixmobile.core.page.viewmodel.effects.DeletePageItems +import org.kiwix.kiwixmobile.core.utils.dialog.DialogShower +import org.kiwix.kiwixmobile.core.utils.dialog.KiwixDialog.DeleteAllNotes +import org.kiwix.kiwixmobile.core.utils.dialog.KiwixDialog.DeleteSelectedNotes +import javax.inject.Inject + +data class ShowDeleteNotesDialog( + private val effects: PublishProcessor>, + private val state: NotesState, + private val pageDao: PageDao +) : SideEffect { + @Inject lateinit var dialogShower: DialogShower + override fun invokeWith(activity: AppCompatActivity) { + activity.cachedComponent.inject(this) + Log.d("invoke", "invokeWith: invoked") + dialogShower.show( + if (state.isInSelectionState) DeleteSelectedNotes else DeleteAllNotes, + { + effects.offer(DeletePageItems(state, pageDao)) + } + ) + } +} diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/page/notes/viewmodel/effects/ShowOpenNoteDialog.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/page/notes/viewmodel/effects/ShowOpenNoteDialog.kt new file mode 100644 index 000000000..77873906d --- /dev/null +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/page/notes/viewmodel/effects/ShowOpenNoteDialog.kt @@ -0,0 +1,54 @@ +/* + * Kiwix Android + * Copyright (c) 2021 Kiwix + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package org.kiwix.kiwixmobile.core.page.notes.viewmodel.effects + +import androidx.appcompat.app.AppCompatActivity +import io.reactivex.processors.PublishProcessor +import org.kiwix.kiwixmobile.core.base.SideEffect +import org.kiwix.kiwixmobile.core.extensions.ActivityExtensions.cachedComponent +import org.kiwix.kiwixmobile.core.page.adapter.Page +import org.kiwix.kiwixmobile.core.page.notes.adapter.NoteListItem +import org.kiwix.kiwixmobile.core.page.viewmodel.effects.OpenNote +import org.kiwix.kiwixmobile.core.page.viewmodel.effects.OpenPage +import org.kiwix.kiwixmobile.core.reader.ZimReaderContainer +import org.kiwix.kiwixmobile.core.utils.dialog.DialogShower +import org.kiwix.kiwixmobile.core.utils.dialog.KiwixDialog.ShowNoteDialog +import java.io.File +import javax.inject.Inject + +data class ShowOpenNoteDialog( + private val effects: PublishProcessor>, + private val page: Page, + private val zimReaderContainer: ZimReaderContainer +) : SideEffect { + @Inject lateinit var dialogShower: DialogShower + override fun invokeWith(activity: AppCompatActivity) { + activity.cachedComponent.inject(this) + dialogShower.show( + ShowNoteDialog, + { effects.offer(OpenPage(page, zimReaderContainer)) }, + { + val item = page as NoteListItem + val file = File(item.zimFilePath.orEmpty()) + zimReaderContainer.setZimFile(file) + effects.offer(OpenNote(item.noteFilePath, item.zimUrl, item.title)) + } + ) + } +} diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/page/notes/viewmodel/effects/UpdateAllNotesPreference.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/page/notes/viewmodel/effects/UpdateAllNotesPreference.kt new file mode 100644 index 000000000..8a00fea06 --- /dev/null +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/page/notes/viewmodel/effects/UpdateAllNotesPreference.kt @@ -0,0 +1,32 @@ +/* + * Kiwix Android + * Copyright (c) 2020 Kiwix + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package org.kiwix.kiwixmobile.core.page.notes.viewmodel.effects + +import androidx.appcompat.app.AppCompatActivity +import org.kiwix.kiwixmobile.core.base.SideEffect +import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil + +data class UpdateAllNotesPreference( + private val sharedPreferenceUtil: SharedPreferenceUtil, + private val isChecked: Boolean +) : SideEffect { + override fun invokeWith(activity: AppCompatActivity) { + sharedPreferenceUtil.showNotesAllBooks = isChecked + } +} diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/page/viewmodel/PageViewModel.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/page/viewmodel/PageViewModel.kt index f0c93c3ce..edda2f164 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/page/viewmodel/PageViewModel.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/page/viewmodel/PageViewModel.kt @@ -49,6 +49,8 @@ abstract class PageViewModel>( abstract fun initialState(): S + private lateinit var pageViewModelClickListener: PageViewModelClickListener + val state: MutableLiveData by lazy { MutableLiveData().apply { value = initialState() @@ -106,13 +108,21 @@ abstract class PageViewModel>( abstract fun copyWithNewItems(state: S, newItems: List): S private fun handleItemClick(state: S, action: Action.OnItemClick): S { - if (state.isInSelectionState) { - return copyWithNewItems(state, state.getItemsAfterToggleSelectionOfItem(action.page)) + if (::pageViewModelClickListener.isInitialized) { + effects.offer(pageViewModelClickListener.onItemClick(action.page)) + } else { + if (state.isInSelectionState) { + return copyWithNewItems(state, state.getItemsAfterToggleSelectionOfItem(action.page)) + } + effects.offer(OpenPage(action.page, zimReaderContainer)) } - effects.offer(OpenPage(action.page, zimReaderContainer)) return state } + fun setOnItemClickListener(clickListener: PageViewModelClickListener) { + pageViewModelClickListener = clickListener + } + abstract fun deselectAllPages(state: S): S private fun exitFragment(state: S): S { diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/page/viewmodel/PageViewModelClickListener.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/page/viewmodel/PageViewModelClickListener.kt new file mode 100644 index 000000000..b549a89a2 --- /dev/null +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/page/viewmodel/PageViewModelClickListener.kt @@ -0,0 +1,26 @@ +/* + * Kiwix Android + * Copyright (c) 2021 Kiwix + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package org.kiwix.kiwixmobile.core.page.viewmodel + +import org.kiwix.kiwixmobile.core.base.SideEffect +import org.kiwix.kiwixmobile.core.page.adapter.Page + +interface PageViewModelClickListener { + fun onItemClick(page: Page): SideEffect<*> +} diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/page/viewmodel/effects/OpenNote.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/page/viewmodel/effects/OpenNote.kt new file mode 100644 index 000000000..fe15a416a --- /dev/null +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/page/viewmodel/effects/OpenNote.kt @@ -0,0 +1,60 @@ +/* + * Kiwix Android + * Copyright (c) 2020 Kiwix + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package org.kiwix.kiwixmobile.core.page.viewmodel.effects + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.fragment.app.Fragment +import androidx.fragment.app.FragmentTransaction +import org.kiwix.kiwixmobile.core.base.SideEffect +import org.kiwix.kiwixmobile.core.main.AddNoteDialog +import org.kiwix.kiwixmobile.core.main.AddNoteDialog.Companion.ARTICLE_URL +import org.kiwix.kiwixmobile.core.main.AddNoteDialog.Companion.NOTES_TITLE +import org.kiwix.kiwixmobile.core.main.AddNoteDialog.Companion.NOTE_FILE_PATH +import org.kiwix.kiwixmobile.core.main.CoreMainActivity + +class OpenNote( + private val noteFilePath: String, + private val zimFileUrl: String, + private val title: String, +) : SideEffect { + override fun invokeWith(activity: AppCompatActivity) { + activity as CoreMainActivity + showAddNoteDialog(activity) + } + + private fun showAddNoteDialog(activity: AppCompatActivity) { + val coreMainActivity: CoreMainActivity = activity as CoreMainActivity + val fragmentTransaction: FragmentTransaction = + coreMainActivity.supportFragmentManager.beginTransaction() + val previousInstance: Fragment? = + coreMainActivity.supportFragmentManager.findFragmentByTag(AddNoteDialog.TAG) + + if (previousInstance == null) { + val dialogFragment = AddNoteDialog() + val bundle = Bundle().apply { + putString(NOTE_FILE_PATH, noteFilePath) + putString(ARTICLE_URL, zimFileUrl) + putString(NOTES_TITLE, title) + } + dialogFragment.arguments = bundle + dialogFragment.show(fragmentTransaction, AddNoteDialog.TAG) + } + } +} diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/utils/SharedPreferenceUtil.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/utils/SharedPreferenceUtil.kt index ffb3760c1..ab0fd6c0a 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/utils/SharedPreferenceUtil.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/utils/SharedPreferenceUtil.kt @@ -151,6 +151,12 @@ class SharedPreferenceUtil @Inject constructor(val context: Context) { putBoolean(PREF_SHOW_BOOKMARKS_ALL_BOOKS, prefShowBookmarksFromCurrentBook) } + var showNotesAllBooks: Boolean + get() = sharedPreferences.getBoolean(PREF_SHOW_NOTES_ALL_BOOKS, true) + set(prefShowBookmarksFromCurrentBook) = sharedPreferences.edit { + putBoolean(PREF_SHOW_NOTES_ALL_BOOKS, prefShowBookmarksFromCurrentBook) + } + val nightMode: NightModeConfig.Mode get() = from( sharedPreferences.getString(PREF_NIGHT_MODE, null)?.toInt() @@ -209,6 +215,7 @@ class SharedPreferenceUtil @Inject constructor(val context: Context) { private const val PREF_IS_FIRST_RUN = "isFirstRun" private const val PREF_SHOW_BOOKMARKS_ALL_BOOKS = "show_bookmarks_current_book" private const val PREF_SHOW_HISTORY_ALL_BOOKS = "show_history_current_book" + private const val PREF_SHOW_NOTES_ALL_BOOKS = "show_notes_current_book" private const val PREF_HOSTED_BOOKS = "hosted_books" const val PREF_NIGHT_MODE = "pref_night_mode" private const val TEXT_ZOOM = "true_text_zoom" diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/utils/dialog/KiwixDialog.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/utils/dialog/KiwixDialog.kt index d078632c2..fb2aac57b 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/utils/dialog/KiwixDialog.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/utils/dialog/KiwixDialog.kt @@ -257,6 +257,27 @@ sealed class KiwixDialog( positiveMessage = R.string.delete, negativeMessage = R.string.cancel ) + + object DeleteAllNotes : KiwixDialog( + R.string.delete_notes_confirmation_msg, + R.string.delete_note_dialog_message, + positiveMessage = R.string.delete, + negativeMessage = R.string.cancel + ) + + object DeleteSelectedNotes : KiwixDialog( + R.string.delete_selected_notes, + R.string.delete_note_dialog_message, + positiveMessage = R.string.delete, + negativeMessage = R.string.cancel + ) + + object ShowNoteDialog : KiwixDialog( + R.string.choose_your_action, + null, + positiveMessage = R.string.open_article, + negativeMessage = R.string.open_note + ) } interface HasBodyFormatArgs { diff --git a/core/src/main/res/layout/fragment_page.xml b/core/src/main/res/layout/fragment_page.xml index 4ef25707f..bdb365b42 100644 --- a/core/src/main/res/layout/fragment_page.xml +++ b/core/src/main/res/layout/fragment_page.xml @@ -13,7 +13,6 @@ app:layout_constraintTop_toTopOf="parent" tools:showIn="@layout/fragment_help"> - + app:layout_constraintTop_toBottomOf="@id/app_bar" + tools:listitem="@layout/item_bookmark_history" /> diff --git a/core/src/main/res/menu/menu_drawer_main.xml b/core/src/main/res/menu/menu_drawer_main.xml index 00c284e0f..929dca42a 100644 --- a/core/src/main/res/menu/menu_drawer_main.xml +++ b/core/src/main/res/menu/menu_drawer_main.xml @@ -17,6 +17,12 @@ android:title="@string/history" app:showAsAction="never" /> + + 1 -1 + No Notes + View Notes From All Books + Search Notes + Choose your Action + Open Note + Open Article + Note: Notes are not deleted from your storage + Delete Selected Notes? diff --git a/core/src/test/java/org/kiwix/kiwixmobile/core/dao/NewNoteDaoTest.kt b/core/src/test/java/org/kiwix/kiwixmobile/core/dao/NewNoteDaoTest.kt new file mode 100644 index 000000000..c9eed304a --- /dev/null +++ b/core/src/test/java/org/kiwix/kiwixmobile/core/dao/NewNoteDaoTest.kt @@ -0,0 +1,65 @@ +/* + * Kiwix Android + * Copyright (c) 2022 Kiwix + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package org.kiwix.kiwixmobile.core.dao + +import io.mockk.every +import io.mockk.mockk +import io.mockk.verify +import io.objectbox.Box +import io.objectbox.query.Query +import io.objectbox.query.QueryBuilder +import org.junit.jupiter.api.Test +import org.kiwix.kiwixmobile.core.dao.entities.NotesEntity +import org.kiwix.kiwixmobile.core.dao.entities.NotesEntity_ +import org.kiwix.kiwixmobile.core.page.adapter.Page +import org.kiwix.kiwixmobile.core.page.notes.adapter.NoteListItem + +internal class NewNoteDaoTest { + + private val notesBox: Box = mockk(relaxed = true) + private val newNotesDao = NewNoteDao(notesBox) + + @Test + fun deletePages() { + val notesItem: NoteListItem = mockk(relaxed = true) + val notesItemList: List = listOf(notesItem) + val pagesToDelete: List = notesItemList + newNotesDao.deletePages(pagesToDelete) + verify { newNotesDao.deleteNotes(notesItemList) } + } + + @Test + fun deleteNotePage() { + val noteTitle = "abNotesTitle" + val queryBuilder: QueryBuilder = mockk(relaxed = true) + every { notesBox.query() } returns queryBuilder + every { queryBuilder.equal(NotesEntity_.noteTitle, noteTitle) } returns queryBuilder + val query: Query = mockk(relaxed = true) + every { queryBuilder.build() } returns query + newNotesDao.deleteNote(noteTitle) + verify { query.remove() } + } + + @Test + fun saveNotePage() { + val newNote: NoteListItem = mockk(relaxed = true) + newNotesDao.saveNote(newNote) + verify { notesBox.put(NotesEntity(newNote)) } + } +} diff --git a/custom/src/main/java/org/kiwix/kiwixmobile/custom/main/CustomMainActivity.kt b/custom/src/main/java/org/kiwix/kiwixmobile/custom/main/CustomMainActivity.kt index 54da5d072..5a4314d37 100644 --- a/custom/src/main/java/org/kiwix/kiwixmobile/custom/main/CustomMainActivity.kt +++ b/custom/src/main/java/org/kiwix/kiwixmobile/custom/main/CustomMainActivity.kt @@ -47,6 +47,7 @@ class CustomMainActivity : CoreMainActivity() { override val settingsFragmentResId: Int = R.id.customSettingsFragment override val readerFragmentResId: Int = R.id.customReaderFragment override val historyFragmentResId: Int = R.id.historyFragment + override val notesFragmentResId: Int = R.id.notesFragment override val helpFragmentResId: Int = R.id.helpFragment override val cachedComponent by lazy { customActivityComponent } override val topLevelDestinations = diff --git a/custom/src/main/res/navigation/custom_nav_graph.xml b/custom/src/main/res/navigation/custom_nav_graph.xml index 319da58c9..198bb8c4b 100644 --- a/custom/src/main/res/navigation/custom_nav_graph.xml +++ b/custom/src/main/res/navigation/custom_nav_graph.xml @@ -47,6 +47,10 @@ android:id="@+id/historyFragment" android:name="org.kiwix.kiwixmobile.core.page.history.HistoryFragment" android:label="HistoryFragment" /> +