Migrated to Room

This commit is contained in:
Gouri Panda 2022-12-31 15:24:57 +05:30
parent 6cab5e924f
commit 7d5b985726
16 changed files with 321 additions and 122 deletions

View File

@ -26,30 +26,30 @@ import org.kiwix.kiwixmobile.core.dao.entities.NotesEntity_
import org.kiwix.kiwixmobile.core.page.adapter.Page import org.kiwix.kiwixmobile.core.page.adapter.Page
import org.kiwix.kiwixmobile.core.page.notes.adapter.NoteListItem import org.kiwix.kiwixmobile.core.page.notes.adapter.NoteListItem
import javax.inject.Inject import javax.inject.Inject
// @Deprecated("Replaced with the Room")
class NewNoteDao @Inject constructor(val box: Box<NotesEntity>) : PageDao { // class NewNoteDao @Inject constructor(val box: Box<NotesEntity>) : PageDao {
fun notes(): Flowable<List<Page>> = box.asFlowable( // fun notes(): Flowable<List<Page>> = box.asFlowable(
box.query { // box.query {
order(NotesEntity_.noteTitle) // order(NotesEntity_.noteTitle)
} // }
).map { it.map(::NoteListItem) } // ).map { it.map(::NoteListItem) }
//
override fun pages(): Flowable<List<Page>> = notes() // override fun pages(): Flowable<List<Page>> = notes()
//
override fun deletePages(pagesToDelete: List<Page>) = // override fun deletePages(pagesToDelete: List<Page>) =
deleteNotes(pagesToDelete as List<NoteListItem>) // deleteNotes(pagesToDelete as List<NoteListItem>)
//
fun saveNote(noteItem: NoteListItem) { // fun saveNote(noteItem: NoteListItem) {
box.put(NotesEntity(noteItem)) // box.put(NotesEntity(noteItem))
} // }
//
fun deleteNotes(noteList: List<NoteListItem>) { // fun deleteNotes(noteList: List<NoteListItem>) {
box.remove(noteList.map(::NotesEntity)) // box.remove(noteList.map(::NotesEntity))
} // }
//
fun deleteNote(noteUniqueKey: String) { // fun deleteNote(noteUniqueKey: String) {
box.query { // box.query {
equal(NotesEntity_.noteTitle, noteUniqueKey) // equal(NotesEntity_.noteTitle, noteUniqueKey)
}.remove() // }.remove()
} // }
} // }

View File

@ -0,0 +1,74 @@
/*
* Kiwix Android
* Copyright (c) 2022 Kiwix <android.kiwix.org>
* 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 <http://www.gnu.org/licenses/>.
*
*/
package org.kiwix.kiwixmobile.core.dao
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import androidx.room.Update
import io.objectbox.Box
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
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.page.notes.adapter.NoteListItem
@Dao
abstract class NotesRoomDao : PageRoomDao {
@Query("SELECT * FROM NotesRoomEntity ORDER BY NotesRoomEntity.noteTitle")
abstract fun notesAsEntity(): Flow<List<NotesRoomEntity>>
fun notes(): Flow<List<Page>> = notesAsEntity().map { it.map(::NoteListItem) }
override fun pages(): Flow<List<Page>> = notes()
override fun deletePages(pagesToDelete: List<Page>) =
deleteNotes(pagesToDelete as List<NoteListItem>)
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<NoteListItem>) {
notesList.forEachIndexed { _, note ->
val notesRoomEntity = NotesRoomEntity(note)
deleteNote(noteUniqueKey = notesRoomEntity.noteTitle)
}
}
fun migrationToRoomInsert(
box: Box<NotesEntity>
) {
val notesEntities = box.all
notesEntities.forEachIndexed { _, notesEntity ->
CoroutineScope(Dispatchers.IO).launch {
saveNote(NoteListItem(notesEntity))
}
}
}
}

View File

@ -19,9 +19,18 @@
package org.kiwix.kiwixmobile.core.dao package org.kiwix.kiwixmobile.core.dao
import io.reactivex.Flowable import io.reactivex.Flowable
import kotlinx.coroutines.flow.Flow
import org.kiwix.kiwixmobile.core.page.adapter.Page import org.kiwix.kiwixmobile.core.page.adapter.Page
interface PageDao { interface PageDao : BasePageDao {
fun pages(): Flowable<List<Page>> override fun pages(): Flowable<List<Page>>
}
interface PageRoomDao : BasePageDao {
override fun pages(): Flow<List<Page>>
}
interface BasePageDao {
fun pages(): Any
fun deletePages(pagesToDelete: List<Page>) fun deletePages(pagesToDelete: List<Page>)
} }

View File

@ -0,0 +1,46 @@
/*
* Kiwix Android
* Copyright (c) 2022 Kiwix <android.kiwix.org>
* 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 <http://www.gnu.org/licenses/>.
*
*/
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
)
}

View File

@ -26,8 +26,8 @@ import org.kiwix.kiwixmobile.core.dao.HistoryDao
import org.kiwix.kiwixmobile.core.dao.NewBookDao import org.kiwix.kiwixmobile.core.dao.NewBookDao
import org.kiwix.kiwixmobile.core.dao.NewBookmarksDao import org.kiwix.kiwixmobile.core.dao.NewBookmarksDao
import org.kiwix.kiwixmobile.core.dao.NewLanguagesDao import org.kiwix.kiwixmobile.core.dao.NewLanguagesDao
import org.kiwix.kiwixmobile.core.dao.NewNoteDao
import org.kiwix.kiwixmobile.core.dao.NewRecentSearchRoomDao import org.kiwix.kiwixmobile.core.dao.NewRecentSearchRoomDao
import org.kiwix.kiwixmobile.core.dao.NotesRoomDao
import org.kiwix.kiwixmobile.core.di.qualifiers.IO import org.kiwix.kiwixmobile.core.di.qualifiers.IO
import org.kiwix.kiwixmobile.core.di.qualifiers.MainThread import org.kiwix.kiwixmobile.core.di.qualifiers.MainThread
import org.kiwix.kiwixmobile.core.extensions.HeaderizableList import org.kiwix.kiwixmobile.core.extensions.HeaderizableList
@ -55,7 +55,7 @@ class Repository @Inject internal constructor(
private val bookDao: NewBookDao, private val bookDao: NewBookDao,
private val bookmarksDao: NewBookmarksDao, private val bookmarksDao: NewBookmarksDao,
private val historyDao: HistoryDao, private val historyDao: HistoryDao,
private val notesDao: NewNoteDao, private val notesDao: NotesRoomDao,
private val languageDao: NewLanguagesDao, private val languageDao: NewLanguagesDao,
private val recentSearchDao: NewRecentSearchRoomDao, private val recentSearchDao: NewRecentSearchRoomDao,
private val zimReaderContainer: ZimReaderContainer private val zimReaderContainer: ZimReaderContainer

View File

@ -19,22 +19,30 @@
package org.kiwix.kiwixmobile.core.data.local package org.kiwix.kiwixmobile.core.data.local
import android.content.Context import android.content.Context
import android.util.Log
import androidx.room.Database import androidx.room.Database
import androidx.room.Room import androidx.room.Room
import androidx.room.RoomDatabase import androidx.room.RoomDatabase
import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase
import io.objectbox.BoxStore import io.objectbox.BoxStore
import io.objectbox.kotlin.boxFor import io.objectbox.kotlin.boxFor
import org.kiwix.kiwixmobile.core.dao.NewRecentSearchRoomDao import org.kiwix.kiwixmobile.core.dao.NewRecentSearchRoomDao
import org.kiwix.kiwixmobile.core.dao.NotesRoomDao
import org.kiwix.kiwixmobile.core.dao.entities.NotesRoomEntity
import org.kiwix.kiwixmobile.core.dao.entities.RecentSearchRoomEntity import org.kiwix.kiwixmobile.core.dao.entities.RecentSearchRoomEntity
@Suppress("UnnecessaryAbstractClass") @Suppress("UnnecessaryAbstractClass")
@Database(entities = [RecentSearchRoomEntity::class], version = 1) @Database(entities = [RecentSearchRoomEntity::class, NotesRoomEntity::class], version = 1)
abstract class KiwixRoomDatabase : RoomDatabase() { abstract class KiwixRoomDatabase : RoomDatabase() {
abstract fun newRecentSearchRoomDao(): NewRecentSearchRoomDao abstract fun newRecentSearchRoomDao(): NewRecentSearchRoomDao
abstract fun noteRoomDao(): NotesRoomDao
companion object { companion object {
private var db: KiwixRoomDatabase? = null private var db: KiwixRoomDatabase? = null
private lateinit var boxStore: BoxStore
fun getInstance(context: Context, boxStore: BoxStore): KiwixRoomDatabase { fun getInstance(context: Context, boxStore: BoxStore): KiwixRoomDatabase {
this.boxStore = boxStore
return db ?: synchronized(KiwixRoomDatabase::class) { return db ?: synchronized(KiwixRoomDatabase::class) {
return@getInstance db return@getInstance db
?: Room.databaseBuilder(context, KiwixRoomDatabase::class.java, "KiwixRoom.db") ?: Room.databaseBuilder(context, KiwixRoomDatabase::class.java, "KiwixRoom.db")
@ -42,10 +50,18 @@ abstract class KiwixRoomDatabase : RoomDatabase() {
// kiwixRoom.db // kiwixRoom.db
.build().also { .build().also {
it.migrateRecentSearch(boxStore) it.migrateRecentSearch(boxStore)
it.migrateNote(boxStore)
} }
} }
} }
val MIGRATION_1_2 = object : Migration(1, 2) {
override fun migrate(database: SupportSQLiteDatabase) {
Log.d("gouri", "migration helper started and ${db == null} and ${boxStore == null}")
// database.db?.migrateNote(boxStore)
}
}
fun destroyInstance() { fun destroyInstance() {
db = null db = null
} }
@ -54,4 +70,8 @@ abstract class KiwixRoomDatabase : RoomDatabase() {
fun migrateRecentSearch(boxStore: BoxStore) { fun migrateRecentSearch(boxStore: BoxStore) {
newRecentSearchRoomDao().migrationToRoomInsert(boxStore.boxFor()) newRecentSearchRoomDao().migrationToRoomInsert(boxStore.boxFor())
} }
fun migrateNote(boxStore: BoxStore) {
noteRoomDao().migrationToRoomInsert(boxStore.boxFor())
}
} }

View File

@ -31,9 +31,9 @@ import org.kiwix.kiwixmobile.core.dao.HistoryDao
import org.kiwix.kiwixmobile.core.dao.NewBookDao import org.kiwix.kiwixmobile.core.dao.NewBookDao
import org.kiwix.kiwixmobile.core.dao.NewBookmarksDao import org.kiwix.kiwixmobile.core.dao.NewBookmarksDao
import org.kiwix.kiwixmobile.core.dao.NewLanguagesDao 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.NewRecentSearchDao
import org.kiwix.kiwixmobile.core.dao.NewRecentSearchRoomDao import org.kiwix.kiwixmobile.core.dao.NewRecentSearchRoomDao
import org.kiwix.kiwixmobile.core.dao.NotesRoomDao
import org.kiwix.kiwixmobile.core.data.DataModule import org.kiwix.kiwixmobile.core.data.DataModule
import org.kiwix.kiwixmobile.core.data.DataSource import org.kiwix.kiwixmobile.core.data.DataSource
import org.kiwix.kiwixmobile.core.data.local.dao.BookDao import org.kiwix.kiwixmobile.core.data.local.dao.BookDao
@ -89,10 +89,11 @@ interface CoreComponent {
fun fetchDownloadDao(): FetchDownloadDao fun fetchDownloadDao(): FetchDownloadDao
fun newBookDao(): NewBookDao fun newBookDao(): NewBookDao
fun historyDao(): HistoryDao fun historyDao(): HistoryDao
fun noteDao(): NewNoteDao // fun noteDao(): NewNoteDao
fun newLanguagesDao(): NewLanguagesDao fun newLanguagesDao(): NewLanguagesDao
fun recentSearchDao(): NewRecentSearchDao fun recentSearchDao(): NewRecentSearchDao
fun recentSearchRoomDao(): NewRecentSearchRoomDao fun recentSearchRoomDao(): NewRecentSearchRoomDao
fun noteRoomDao(): NotesRoomDao
fun newBookmarksDao(): NewBookmarksDao fun newBookmarksDao(): NewBookmarksDao
fun connectivityManager(): ConnectivityManager fun connectivityManager(): ConnectivityManager
fun context(): Context fun context(): Context

View File

@ -28,7 +28,7 @@ import org.kiwix.kiwixmobile.core.dao.HistoryDao
import org.kiwix.kiwixmobile.core.dao.NewBookDao import org.kiwix.kiwixmobile.core.dao.NewBookDao
import org.kiwix.kiwixmobile.core.dao.NewBookmarksDao import org.kiwix.kiwixmobile.core.dao.NewBookmarksDao
import org.kiwix.kiwixmobile.core.dao.NewLanguagesDao import org.kiwix.kiwixmobile.core.dao.NewLanguagesDao
import org.kiwix.kiwixmobile.core.dao.NewNoteDao // import org.kiwix.kiwixmobile.core.dao.NewNoteDao
import org.kiwix.kiwixmobile.core.dao.NewRecentSearchDao import org.kiwix.kiwixmobile.core.dao.NewRecentSearchDao
import org.kiwix.kiwixmobile.core.dao.entities.MyObjectBox import org.kiwix.kiwixmobile.core.dao.entities.MyObjectBox
import org.kiwix.kiwixmobile.core.data.local.KiwixRoomDatabase import org.kiwix.kiwixmobile.core.data.local.KiwixRoomDatabase
@ -60,8 +60,8 @@ open class DatabaseModule {
@Provides @Singleton fun providesNewBookmarksDao(boxStore: BoxStore): NewBookmarksDao = @Provides @Singleton fun providesNewBookmarksDao(boxStore: BoxStore): NewBookmarksDao =
NewBookmarksDao(boxStore.boxFor()) NewBookmarksDao(boxStore.boxFor())
@Provides @Singleton fun providesNewNoteDao(boxStore: BoxStore): NewNoteDao = // @Provides @Singleton fun providesNewNoteDao(boxStore: BoxStore): NewNoteDao =
NewNoteDao(boxStore.boxFor()) // NewNoteDao(boxStore.boxFor())
@Provides @Singleton fun providesNewRecentSearchDao( @Provides @Singleton fun providesNewRecentSearchDao(
boxStore: BoxStore, boxStore: BoxStore,
@ -88,4 +88,8 @@ open class DatabaseModule {
@Singleton @Singleton
@Provides @Provides
fun provideNewRecentSearchRoomDao(db: KiwixRoomDatabase) = db.newRecentSearchRoomDao() fun provideNewRecentSearchRoomDao(db: KiwixRoomDatabase) = db.newRecentSearchRoomDao()
@Singleton
@Provides
fun provideNoteRoomDao(db: KiwixRoomDatabase) = db.noteRoomDao()
} }

View File

@ -19,8 +19,10 @@ package org.kiwix.kiwixmobile.core.page.bookmark.viewmodel.effects
*/ */
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope
import io.reactivex.processors.PublishProcessor import io.reactivex.processors.PublishProcessor
import org.kiwix.kiwixmobile.core.base.SideEffect import org.kiwix.kiwixmobile.core.base.SideEffect
import org.kiwix.kiwixmobile.core.dao.BasePageDao
import org.kiwix.kiwixmobile.core.dao.PageDao import org.kiwix.kiwixmobile.core.dao.PageDao
import org.kiwix.kiwixmobile.core.extensions.ActivityExtensions.cachedComponent import org.kiwix.kiwixmobile.core.extensions.ActivityExtensions.cachedComponent
import org.kiwix.kiwixmobile.core.page.bookmark.adapter.BookmarkItem import org.kiwix.kiwixmobile.core.page.bookmark.adapter.BookmarkItem
@ -34,14 +36,14 @@ import javax.inject.Inject
data class ShowDeleteBookmarksDialog( data class ShowDeleteBookmarksDialog(
private val effects: PublishProcessor<SideEffect<*>>, private val effects: PublishProcessor<SideEffect<*>>,
private val state: PageState<BookmarkItem>, private val state: PageState<BookmarkItem>,
private val pageDao: PageDao private val pageDao: BasePageDao
) : SideEffect<Unit> { ) : SideEffect<Unit> {
@Inject lateinit var dialogShower: DialogShower @Inject lateinit var dialogShower: DialogShower
override fun invokeWith(activity: AppCompatActivity) { override fun invokeWith(activity: AppCompatActivity) {
activity.cachedComponent.inject(this) activity.cachedComponent.inject(this)
dialogShower.show( dialogShower.show(
if (state.isInSelectionState) DeleteSelectedBookmarks else DeleteAllBookmarks, if (state.isInSelectionState) DeleteSelectedBookmarks else DeleteAllBookmarks,
{ effects.offer(DeletePageItems(state, pageDao)) } { effects.offer(DeletePageItems(state, pageDao, activity.lifecycleScope)) }
) )
} }
} }

View File

@ -19,8 +19,10 @@ package org.kiwix.kiwixmobile.core.page.history.viewmodel.effects
*/ */
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope
import io.reactivex.processors.PublishProcessor import io.reactivex.processors.PublishProcessor
import org.kiwix.kiwixmobile.core.base.SideEffect import org.kiwix.kiwixmobile.core.base.SideEffect
import org.kiwix.kiwixmobile.core.dao.BasePageDao
import org.kiwix.kiwixmobile.core.dao.PageDao import org.kiwix.kiwixmobile.core.dao.PageDao
import org.kiwix.kiwixmobile.core.extensions.ActivityExtensions.cachedComponent import org.kiwix.kiwixmobile.core.extensions.ActivityExtensions.cachedComponent
import org.kiwix.kiwixmobile.core.page.history.viewmodel.HistoryState import org.kiwix.kiwixmobile.core.page.history.viewmodel.HistoryState
@ -33,13 +35,13 @@ import javax.inject.Inject
data class ShowDeleteHistoryDialog( data class ShowDeleteHistoryDialog(
private val effects: PublishProcessor<SideEffect<*>>, private val effects: PublishProcessor<SideEffect<*>>,
private val state: HistoryState, private val state: HistoryState,
private val pageDao: PageDao private val pageDao: BasePageDao
) : SideEffect<Unit> { ) : SideEffect<Unit> {
@Inject lateinit var dialogShower: DialogShower @Inject lateinit var dialogShower: DialogShower
override fun invokeWith(activity: AppCompatActivity) { override fun invokeWith(activity: AppCompatActivity) {
activity.cachedComponent.inject(this) activity.cachedComponent.inject(this)
dialogShower.show(if (state.isInSelectionState) DeleteSelectedHistory else DeleteAllHistory, { dialogShower.show(if (state.isInSelectionState) DeleteSelectedHistory else DeleteAllHistory, {
effects.offer(DeletePageItems(state, pageDao)) effects.offer(DeletePageItems(state, pageDao, activity.lifecycleScope))
}) })
} }
} }

View File

@ -1,6 +1,7 @@
package org.kiwix.kiwixmobile.core.page.notes.adapter package org.kiwix.kiwixmobile.core.page.notes.adapter
import org.kiwix.kiwixmobile.core.dao.entities.NotesEntity 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.page.adapter.Page
import org.kiwix.kiwixmobile.core.reader.ZimFileReader import org.kiwix.kiwixmobile.core.reader.ZimFileReader
@ -27,6 +28,16 @@ data class NoteListItem(
notesEntity.favicon notesEntity.favicon
) )
constructor(notesRoomEntity: NotesRoomEntity) : this(
notesRoomEntity.id,
notesRoomEntity.zimId,
notesRoomEntity.noteTitle,
notesRoomEntity.zimFilePath,
notesRoomEntity.zimUrl,
notesRoomEntity.noteFilePath,
notesRoomEntity.favicon
)
constructor( constructor(
title: String, title: String,
url: String, url: String,

View File

@ -18,7 +18,7 @@
package org.kiwix.kiwixmobile.core.page.notes.viewmodel package org.kiwix.kiwixmobile.core.page.notes.viewmodel
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.adapter.Page
import org.kiwix.kiwixmobile.core.page.notes.adapter.NoteListItem 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.ShowDeleteNotesDialog
@ -32,7 +32,7 @@ import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil
import javax.inject.Inject import javax.inject.Inject
class NotesViewModel @Inject constructor( class NotesViewModel @Inject constructor(
notesDao: NewNoteDao, notesDao: NotesRoomDao,
zimReaderContainer: ZimReaderContainer, zimReaderContainer: ZimReaderContainer,
sharedPrefs: SharedPreferenceUtil sharedPrefs: SharedPreferenceUtil
) : PageViewModel<NoteListItem, NotesState>(notesDao, sharedPrefs, zimReaderContainer), ) : PageViewModel<NoteListItem, NotesState>(notesDao, sharedPrefs, zimReaderContainer),

View File

@ -20,9 +20,10 @@ package org.kiwix.kiwixmobile.core.page.notes.viewmodel.effects
import android.util.Log import android.util.Log
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope
import io.reactivex.processors.PublishProcessor import io.reactivex.processors.PublishProcessor
import org.kiwix.kiwixmobile.core.base.SideEffect import org.kiwix.kiwixmobile.core.base.SideEffect
import org.kiwix.kiwixmobile.core.dao.PageDao import org.kiwix.kiwixmobile.core.dao.BasePageDao
import org.kiwix.kiwixmobile.core.extensions.ActivityExtensions.cachedComponent import org.kiwix.kiwixmobile.core.extensions.ActivityExtensions.cachedComponent
import org.kiwix.kiwixmobile.core.page.notes.viewmodel.NotesState import org.kiwix.kiwixmobile.core.page.notes.viewmodel.NotesState
import org.kiwix.kiwixmobile.core.page.viewmodel.effects.DeletePageItems import org.kiwix.kiwixmobile.core.page.viewmodel.effects.DeletePageItems
@ -34,7 +35,7 @@ import javax.inject.Inject
data class ShowDeleteNotesDialog( data class ShowDeleteNotesDialog(
private val effects: PublishProcessor<SideEffect<*>>, private val effects: PublishProcessor<SideEffect<*>>,
private val state: NotesState, private val state: NotesState,
private val pageDao: PageDao private val pageDao: BasePageDao
) : SideEffect<Unit> { ) : SideEffect<Unit> {
@Inject lateinit var dialogShower: DialogShower @Inject lateinit var dialogShower: DialogShower
override fun invokeWith(activity: AppCompatActivity) { override fun invokeWith(activity: AppCompatActivity) {
@ -43,7 +44,7 @@ data class ShowDeleteNotesDialog(
dialogShower.show( dialogShower.show(
if (state.isInSelectionState) DeleteSelectedNotes else DeleteAllNotes, if (state.isInSelectionState) DeleteSelectedNotes else DeleteAllNotes,
{ {
effects.offer(DeletePageItems(state, pageDao)) effects.offer(DeletePageItems(state, pageDao, activity.lifecycleScope))
} }
) )
} }

View File

@ -18,14 +18,23 @@
package org.kiwix.kiwixmobile.core.page.viewmodel package org.kiwix.kiwixmobile.core.page.viewmodel
import android.util.Log
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import io.reactivex.disposables.CompositeDisposable import io.reactivex.disposables.CompositeDisposable
import io.reactivex.disposables.Disposable import io.reactivex.disposables.Disposable
import io.reactivex.processors.PublishProcessor import io.reactivex.processors.PublishProcessor
import io.reactivex.schedulers.Schedulers import io.reactivex.schedulers.Schedulers
import io.reactivex.subjects.SingleSubject
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.launch
import org.kiwix.kiwixmobile.core.base.SideEffect import org.kiwix.kiwixmobile.core.base.SideEffect
import org.kiwix.kiwixmobile.core.dao.BasePageDao
import org.kiwix.kiwixmobile.core.dao.PageDao import org.kiwix.kiwixmobile.core.dao.PageDao
import org.kiwix.kiwixmobile.core.dao.PageRoomDao
import org.kiwix.kiwixmobile.core.page.adapter.Page import org.kiwix.kiwixmobile.core.page.adapter.Page
import org.kiwix.kiwixmobile.core.page.viewmodel.Action.Exit import org.kiwix.kiwixmobile.core.page.viewmodel.Action.Exit
import org.kiwix.kiwixmobile.core.page.viewmodel.Action.ExitActionModeMenu import org.kiwix.kiwixmobile.core.page.viewmodel.Action.ExitActionModeMenu
@ -40,9 +49,10 @@ import org.kiwix.kiwixmobile.core.page.viewmodel.effects.OpenPage
import org.kiwix.kiwixmobile.core.reader.ZimReaderContainer import org.kiwix.kiwixmobile.core.reader.ZimReaderContainer
import org.kiwix.kiwixmobile.core.search.viewmodel.effects.PopFragmentBackstack import org.kiwix.kiwixmobile.core.search.viewmodel.effects.PopFragmentBackstack
import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil
import kotlin.coroutines.CoroutineContext
abstract class PageViewModel<T : Page, S : PageState<T>>( abstract class PageViewModel<T : Page, S : PageState<T>>(
protected val pageDao: PageDao, protected val pageDao: BasePageDao,
val sharedPreferenceUtil: SharedPreferenceUtil, val sharedPreferenceUtil: SharedPreferenceUtil,
val zimReaderContainer: ZimReaderContainer val zimReaderContainer: ZimReaderContainer
) : ViewModel() { ) : ViewModel() {
@ -70,12 +80,24 @@ abstract class PageViewModel<T : Page, S : PageState<T>>(
.subscribe(state::postValue, Throwable::printStackTrace) .subscribe(state::postValue, Throwable::printStackTrace)
protected fun addDisposablesToCompositeDisposable() { protected fun addDisposablesToCompositeDisposable() {
when (pageDao) {
is PageDao -> {
compositeDisposable.addAll( compositeDisposable.addAll(
viewStateReducer(), viewStateReducer(),
pageDao.pages().subscribeOn(Schedulers.io()) pageDao.pages().subscribeOn(Schedulers.io())
.subscribe({ actions.offer(UpdatePages(it)) }, Throwable::printStackTrace) .subscribe({ actions.offer(UpdatePages(it)) }, Throwable::printStackTrace)
) )
} }
is PageRoomDao -> {
compositeDisposable.add(viewStateReducer())
viewModelScope.launch {
pageDao.pages().collect {
actions.offer(UpdatePages(it))
}
}
}
}
}
private fun reduce(action: Action, state: S): S = when (action) { private fun reduce(action: Action, state: S): S = when (action) {
Exit -> exitFragment(state) Exit -> exitFragment(state)

View File

@ -19,16 +19,22 @@
package org.kiwix.kiwixmobile.core.page.viewmodel.effects package org.kiwix.kiwixmobile.core.page.viewmodel.effects
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import org.kiwix.kiwixmobile.core.base.SideEffect import org.kiwix.kiwixmobile.core.base.SideEffect
import org.kiwix.kiwixmobile.core.dao.BasePageDao
import org.kiwix.kiwixmobile.core.dao.PageDao import org.kiwix.kiwixmobile.core.dao.PageDao
import org.kiwix.kiwixmobile.core.page.adapter.Page import org.kiwix.kiwixmobile.core.page.adapter.Page
import org.kiwix.kiwixmobile.core.page.viewmodel.PageState import org.kiwix.kiwixmobile.core.page.viewmodel.PageState
data class DeletePageItems( data class DeletePageItems(
private val state: PageState<*>, private val state: PageState<*>,
private val pageDao: PageDao private val pageDao: BasePageDao,
private val coroutineScope: CoroutineScope
) : SideEffect<Unit> { ) : SideEffect<Unit> {
override fun invokeWith(activity: AppCompatActivity) { override fun invokeWith(activity: AppCompatActivity) {
coroutineScope.launch(Dispatchers.IO) {
if (state.isInSelectionState) { if (state.isInSelectionState) {
pageDao.deletePages(state.pageItems.filter(Page::isSelected)) pageDao.deletePages(state.pageItems.filter(Page::isSelected))
} else { } else {
@ -36,3 +42,4 @@ data class DeletePageItems(
} }
} }
} }
}

View File

@ -1,65 +1,65 @@
/* // /*
* Kiwix Android // * Kiwix Android
* Copyright (c) 2022 Kiwix <android.kiwix.org> // * Copyright (c) 2022 Kiwix <android.kiwix.org>
* This program is free software: you can redistribute it and/or modify // * 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 // * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or // * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. // * (at your option) any later version.
* // *
* This program is distributed in the hope that it will be useful, // * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of // * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. // * GNU General Public License for more details.
* // *
* You should have received a copy of the GNU General Public License // * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. // * along with this program. If not, see <http://www.gnu.org/licenses/>.
* // *
*/ // */
//
package org.kiwix.kiwixmobile.core.dao // package org.kiwix.kiwixmobile.core.dao
//
import io.mockk.every // import io.mockk.every
import io.mockk.mockk // import io.mockk.mockk
import io.mockk.verify // import io.mockk.verify
import io.objectbox.Box // import io.objectbox.Box
import io.objectbox.query.Query // import io.objectbox.query.Query
import io.objectbox.query.QueryBuilder // import io.objectbox.query.QueryBuilder
import org.junit.jupiter.api.Test // 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.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.adapter.Page
import org.kiwix.kiwixmobile.core.page.notes.adapter.NoteListItem // import org.kiwix.kiwixmobile.core.page.notes.adapter.NoteListItem
//
internal class NewNoteDaoTest { // internal class NewNoteDaoTest {
//
private val notesBox: Box<NotesEntity> = mockk(relaxed = true) // private val notesBox: Box<NotesEntity> = mockk(relaxed = true)
private val newNotesDao = NewNoteDao(notesBox) // private val newNotesDao = NewNoteDao(notesBox)
//
@Test // @Test
fun deletePages() { // fun deletePages() {
val notesItem: NoteListItem = mockk(relaxed = true) // val notesItem: NoteListItem = mockk(relaxed = true)
val notesItemList: List<NoteListItem> = listOf(notesItem) // val notesItemList: List<NoteListItem> = listOf(notesItem)
val pagesToDelete: List<Page> = notesItemList // val pagesToDelete: List<Page> = notesItemList
newNotesDao.deletePages(pagesToDelete) // newNotesDao.deletePages(pagesToDelete)
verify { newNotesDao.deleteNotes(notesItemList) } // verify { newNotesDao.deleteNotes(notesItemList) }
} // }
//
@Test // @Test
fun deleteNotePage() { // fun deleteNotePage() {
val noteTitle = "abNotesTitle" // val noteTitle = "abNotesTitle"
val queryBuilder: QueryBuilder<NotesEntity> = mockk(relaxed = true) // val queryBuilder: QueryBuilder<NotesEntity> = mockk(relaxed = true)
every { notesBox.query() } returns queryBuilder // every { notesBox.query() } returns queryBuilder
every { queryBuilder.equal(NotesEntity_.noteTitle, noteTitle) } returns queryBuilder // every { queryBuilder.equal(NotesEntity_.noteTitle, noteTitle) } returns queryBuilder
val query: Query<NotesEntity> = mockk(relaxed = true) // val query: Query<NotesEntity> = mockk(relaxed = true)
every { queryBuilder.build() } returns query // every { queryBuilder.build() } returns query
newNotesDao.deleteNote(noteTitle) // newNotesDao.deleteNote(noteTitle)
verify { query.remove() } // verify { query.remove() }
} // }
//
@Test // @Test
fun saveNotePage() { // fun saveNotePage() {
val newNote: NoteListItem = mockk(relaxed = true) // val newNote: NoteListItem = mockk(relaxed = true)
newNotesDao.saveNote(newNote) // newNotesDao.saveNote(newNote)
verify { notesBox.put(NotesEntity(newNote)) } // verify { notesBox.put(NotesEntity(newNote)) }
} // }
} // }