diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/NotesRoomDao.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/NotesRoomDao.kt new file mode 100644 index 000000000..33c797b56 --- /dev/null +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/NotesRoomDao.kt @@ -0,0 +1,57 @@ +/* + * Kiwix Android + * Copyright (c) 2024 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 androidx.room.Dao +import androidx.room.Insert +import androidx.room.OnConflictStrategy +import androidx.room.Query +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.map +import org.kiwix.kiwixmobile.core.dao.entities.NotesRoomEntity +import org.kiwix.kiwixmobile.core.page.adapter.Page +import org.kiwix.kiwixmobile.core.page.notes.adapter.NoteListItem + +@Dao +abstract class NotesRoomDao : PageRoomDao { + @Query("SELECT * FROM NotesRoomEntity ORDER BY NotesRoomEntity.noteTitle") + abstract fun notesAsEntity(): Flow> + + fun notes(): Flow> = notesAsEntity().map { it.map(::NoteListItem) } + override fun pages(): Flow> = notes() + override fun deletePages(pagesToDelete: List) = + deleteNotes(pagesToDelete as List) + + fun saveNote(noteItem: NoteListItem) { + saveNote(NotesRoomEntity(noteItem)) + } + + @Insert(onConflict = OnConflictStrategy.REPLACE) + abstract fun saveNote(notesRoomEntity: NotesRoomEntity) + + @Query("DELETE FROM NotesRoomEntity WHERE noteTitle=:noteUniqueKey") + abstract fun deleteNote(noteUniqueKey: String) + + fun deleteNotes(notesList: List) { + notesList.forEachIndexed { _, note -> + val notesRoomEntity = NotesRoomEntity(note) + deleteNote(noteUniqueKey = notesRoomEntity.noteTitle) + } + } +} diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/NotesRoomEntity.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/NotesRoomEntity.kt new file mode 100644 index 000000000..ac54c7fb8 --- /dev/null +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/NotesRoomEntity.kt @@ -0,0 +1,46 @@ +/* + * Kiwix Android + * Copyright (c) 2024 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 androidx.room.Entity +import androidx.room.Index +import androidx.room.PrimaryKey +import org.kiwix.kiwixmobile.core.page.notes.adapter.NoteListItem + +@Entity(indices = [Index(value = ["noteTitle"], unique = true)]) +data class NotesRoomEntity( + @PrimaryKey(autoGenerate = true) + var id: Long = 0L, + val zimId: String, + var zimFilePath: String?, + val zimUrl: String, + 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/KiwixRoomDatabase.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/data/KiwixRoomDatabase.kt index aef2b1944..ccc0e79d5 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/data/KiwixRoomDatabase.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/data/KiwixRoomDatabase.kt @@ -27,16 +27,27 @@ import androidx.room.migration.Migration import androidx.sqlite.db.SupportSQLiteDatabase import org.kiwix.kiwixmobile.core.dao.HistoryRoomDao import org.kiwix.kiwixmobile.core.dao.HistoryRoomDaoCoverts +import org.kiwix.kiwixmobile.core.dao.NotesRoomDao import org.kiwix.kiwixmobile.core.dao.RecentSearchRoomDao import org.kiwix.kiwixmobile.core.dao.entities.HistoryRoomEntity +import org.kiwix.kiwixmobile.core.dao.entities.NotesRoomEntity import org.kiwix.kiwixmobile.core.dao.entities.RecentSearchRoomEntity @Suppress("UnnecessaryAbstractClass") -@Database(entities = [RecentSearchRoomEntity::class, HistoryRoomEntity::class], version = 2) +@Database( + entities = [ + RecentSearchRoomEntity::class, + HistoryRoomEntity::class, + NotesRoomEntity::class + ], + version = 3, + exportSchema = false +) @TypeConverters(HistoryRoomDaoCoverts::class) abstract class KiwixRoomDatabase : RoomDatabase() { abstract fun recentSearchRoomDao(): RecentSearchRoomDao abstract fun historyRoomDao(): HistoryRoomDao + abstract fun noteRoomDao(): NotesRoomDao companion object { private var db: KiwixRoomDatabase? = null @@ -46,7 +57,7 @@ abstract class KiwixRoomDatabase : RoomDatabase() { ?: Room.databaseBuilder(context, KiwixRoomDatabase::class.java, "KiwixRoom.db") // We have already database name called kiwix.db in order to avoid complexity we named // as kiwixRoom.db - .addMigrations(MIGRATION_1_2) + .addMigrations(MIGRATION_1_2, MIGRATION_2_3) .build() } } @@ -72,6 +83,31 @@ abstract class KiwixRoomDatabase : RoomDatabase() { } } + @Suppress("MagicNumber") + private val MIGRATION_2_3 = object : Migration(2, 3) { + override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL( + """ + CREATE TABLE IF NOT EXISTS `NotesRoomEntity`( + `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + `zimId` TEXT NOT NULL, + `zimFilePath` TEXT, + `zimUrl` TEXT NOT NULL, + `noteTitle` TEXT NOT NULL, + `noteFilePath` TEXT NOT NULL, + `favicon` TEXT + ) + """ + ) + + database.execSQL( + """ + CREATE UNIQUE INDEX IF NOT EXISTS `index_NotesRoomEntity_noteTitle` ON `NotesRoomEntity` (`noteTitle`) + """ + ) + } + } + fun destroyInstance() { db = null } 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 021da2645..a80695349 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,7 +26,7 @@ import org.kiwix.kiwixmobile.core.dao.HistoryRoomDao import org.kiwix.kiwixmobile.core.dao.LibkiwixBookmarks import org.kiwix.kiwixmobile.core.dao.NewBookDao import org.kiwix.kiwixmobile.core.dao.NewLanguagesDao -import org.kiwix.kiwixmobile.core.dao.NewNoteDao +import org.kiwix.kiwixmobile.core.dao.NotesRoomDao import org.kiwix.kiwixmobile.core.dao.RecentSearchRoomDao import org.kiwix.kiwixmobile.core.di.qualifiers.IO import org.kiwix.kiwixmobile.core.di.qualifiers.MainThread @@ -55,7 +55,7 @@ class Repository @Inject internal constructor( private val bookDao: NewBookDao, private val libkiwixBookmarks: LibkiwixBookmarks, private val historyRoomDao: HistoryRoomDao, - private val notesDao: NewNoteDao, + private val notesRoomDao: NotesRoomDao, private val languageDao: NewLanguagesDao, private val recentSearchRoomDao: RecentSearchRoomDao, private val zimReaderContainer: ZimReaderContainer @@ -125,14 +125,14 @@ class Repository @Inject internal constructor( .subscribeOn(io) override fun saveNote(noteListItem: NoteListItem): Completable = - Completable.fromAction { notesDao.saveNote(noteListItem) } + Completable.fromAction { notesRoomDao.saveNote(noteListItem) } .subscribeOn(io) override fun deleteNotes(noteList: List) = - Completable.fromAction { notesDao.deleteNotes(noteList) } + Completable.fromAction { notesRoomDao.deleteNotes(noteList) } .subscribeOn(io) override fun deleteNote(noteUniqueKey: String): Completable = - Completable.fromAction { notesDao.deleteNote(noteUniqueKey) } + Completable.fromAction { notesRoomDao.deleteNote(noteUniqueKey) } .subscribeOn(io) } 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 828d20459..be4ae15f6 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 @@ -36,6 +36,7 @@ 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.NotesRoomDao import org.kiwix.kiwixmobile.core.dao.RecentSearchRoomDao import org.kiwix.kiwixmobile.core.data.DataModule import org.kiwix.kiwixmobile.core.data.DataSource @@ -102,6 +103,7 @@ interface CoreComponent { fun libkiwixBookmarks(): LibkiwixBookmarks fun recentSearchRoomDao(): RecentSearchRoomDao fun historyRoomDao(): HistoryRoomDao + fun noteRoomDao(): NotesRoomDao fun objectBoxToRoomMigrator(): ObjectBoxToRoomMigrator fun context(): Context fun downloader(): Downloader 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 1f1896228..bda4df235 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 @@ -92,4 +92,8 @@ open class DatabaseModule { @Provides @Singleton fun provideHistoryDao(db: KiwixRoomDatabase) = db.historyRoomDao() + + @Singleton + @Provides + fun provideNoteRoomDao(db: KiwixRoomDatabase) = db.noteRoomDao() } 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 index 4ab8d1669..cb24a152a 100644 --- 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 @@ -1,6 +1,7 @@ package org.kiwix.kiwixmobile.core.page.notes.adapter import org.kiwix.kiwixmobile.core.dao.entities.NotesEntity +import org.kiwix.kiwixmobile.core.dao.entities.NotesRoomEntity import org.kiwix.kiwixmobile.core.page.adapter.Page import org.kiwix.kiwixmobile.core.reader.ZimFileReader @@ -40,4 +41,14 @@ data class NoteListItem( favicon = zimFileReader.favicon, noteFilePath = noteFilePath ) + + constructor(notesRoomEntity: NotesRoomEntity) : this( + notesRoomEntity.id, + notesRoomEntity.zimId, + notesRoomEntity.noteTitle, + notesRoomEntity.zimFilePath, + notesRoomEntity.zimUrl, + notesRoomEntity.noteFilePath, + notesRoomEntity.favicon + ) } 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 index a9071a8e0..b9683deb1 100644 --- 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 @@ -19,7 +19,7 @@ package org.kiwix.kiwixmobile.core.page.notes.viewmodel import kotlinx.coroutines.CoroutineScope -import org.kiwix.kiwixmobile.core.dao.NewNoteDao +import org.kiwix.kiwixmobile.core.dao.NotesRoomDao 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 @@ -33,10 +33,10 @@ import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil import javax.inject.Inject class NotesViewModel @Inject constructor( - notesDao: NewNoteDao, + notesRoomDao: NotesRoomDao, zimReaderContainer: ZimReaderContainer, sharedPrefs: SharedPreferenceUtil -) : PageViewModel(notesDao, sharedPrefs, zimReaderContainer), +) : PageViewModel(notesRoomDao, sharedPrefs, zimReaderContainer), PageViewModelClickListener { init {