Backup Restore reading stats
This commit is contained in:
@@ -28,6 +28,7 @@ import org.koitharu.kotatsu.backups.data.model.HistoryBackup
|
|||||||
import org.koitharu.kotatsu.backups.data.model.MangaBackup
|
import org.koitharu.kotatsu.backups.data.model.MangaBackup
|
||||||
import org.koitharu.kotatsu.backups.data.model.ScrobblingBackup
|
import org.koitharu.kotatsu.backups.data.model.ScrobblingBackup
|
||||||
import org.koitharu.kotatsu.backups.data.model.SourceBackup
|
import org.koitharu.kotatsu.backups.data.model.SourceBackup
|
||||||
|
import org.koitharu.kotatsu.backups.data.model.StatisticBackup
|
||||||
import org.koitharu.kotatsu.backups.domain.BackupSection
|
import org.koitharu.kotatsu.backups.domain.BackupSection
|
||||||
import org.koitharu.kotatsu.core.db.MangaDatabase
|
import org.koitharu.kotatsu.core.db.MangaDatabase
|
||||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||||
@@ -116,6 +117,12 @@ class BackupRepository @Inject constructor(
|
|||||||
data = database.getScrobblingDao().dumpEnabled().map { ScrobblingBackup(it) },
|
data = database.getScrobblingDao().dumpEnabled().map { ScrobblingBackup(it) },
|
||||||
serializer = serializer(),
|
serializer = serializer(),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
BackupSection.STATS -> output.writeJsonArray(
|
||||||
|
section = BackupSection.STATS,
|
||||||
|
data = database.getStatsDao().dumpEnabled().map { StatisticBackup(it) },
|
||||||
|
serializer = serializer(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
progress?.emit(commonProgress)
|
progress?.emit(commonProgress)
|
||||||
commonProgress++
|
commonProgress++
|
||||||
@@ -174,6 +181,10 @@ class BackupRepository @Inject constructor(
|
|||||||
getScrobblingDao().upsert(it.toEntity())
|
getScrobblingDao().upsert(it.toEntity())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BackupSection.STATS -> input.readJsonArray<StatisticBackup>(serializer()).restoreToDb {
|
||||||
|
getStatsDao().upsert(it.toEntity())
|
||||||
|
}
|
||||||
|
|
||||||
null -> CompositeResult.EMPTY // skip unknown entries
|
null -> CompositeResult.EMPTY // skip unknown entries
|
||||||
}
|
}
|
||||||
progress?.emit(commonProgress)
|
progress?.emit(commonProgress)
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package org.koitharu.kotatsu.backups.data.model
|
||||||
|
|
||||||
|
import kotlinx.serialization.SerialName
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import org.koitharu.kotatsu.stats.data.StatsEntity
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
class StatisticBackup(
|
||||||
|
@SerialName("manga_id") val mangaId: Long,
|
||||||
|
@SerialName("started_at") val startedAt: Long,
|
||||||
|
@SerialName("duration") val duration: Long,
|
||||||
|
@SerialName("pages") val pages: Int,
|
||||||
|
) {
|
||||||
|
|
||||||
|
constructor(entity: StatsEntity) : this(
|
||||||
|
mangaId = entity.mangaId,
|
||||||
|
startedAt = entity.startedAt,
|
||||||
|
duration = entity.duration,
|
||||||
|
pages = entity.pages,
|
||||||
|
)
|
||||||
|
|
||||||
|
fun toEntity() = StatsEntity(
|
||||||
|
mangaId = mangaId,
|
||||||
|
startedAt = startedAt,
|
||||||
|
duration = duration,
|
||||||
|
pages = pages,
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -16,6 +16,7 @@ enum class BackupSection(
|
|||||||
BOOKMARKS("bookmarks"),
|
BOOKMARKS("bookmarks"),
|
||||||
SOURCES("sources"),
|
SOURCES("sources"),
|
||||||
SCROBBLING("scrobbling"),
|
SCROBBLING("scrobbling"),
|
||||||
|
STATS("statistics"),
|
||||||
;
|
;
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ data class BackupSectionModel(
|
|||||||
BackupSection.BOOKMARKS -> R.string.bookmarks
|
BackupSection.BOOKMARKS -> R.string.bookmarks
|
||||||
BackupSection.SOURCES -> R.string.remote_sources
|
BackupSection.SOURCES -> R.string.remote_sources
|
||||||
BackupSection.SCROBBLING -> R.string.tracking
|
BackupSection.SCROBBLING -> R.string.tracking
|
||||||
|
BackupSection.STATS -> R.string.statistics
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun areItemsTheSame(other: ListModel): Boolean {
|
override fun areItemsTheSame(other: ListModel): Boolean {
|
||||||
|
|||||||
@@ -7,8 +7,12 @@ import androidx.room.RawQuery
|
|||||||
import androidx.room.Upsert
|
import androidx.room.Upsert
|
||||||
import androidx.sqlite.db.SimpleSQLiteQuery
|
import androidx.sqlite.db.SimpleSQLiteQuery
|
||||||
import androidx.sqlite.db.SupportSQLiteQuery
|
import androidx.sqlite.db.SupportSQLiteQuery
|
||||||
|
import kotlinx.coroutines.currentCoroutineContext
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.flow
|
||||||
|
import kotlinx.coroutines.isActive
|
||||||
import org.koitharu.kotatsu.core.db.entity.MangaEntity
|
import org.koitharu.kotatsu.core.db.entity.MangaEntity
|
||||||
|
import kotlin.collections.forEach
|
||||||
|
|
||||||
@Dao
|
@Dao
|
||||||
abstract class StatsDao {
|
abstract class StatsDao {
|
||||||
@@ -61,4 +65,19 @@ abstract class StatsDao {
|
|||||||
protected abstract suspend fun getDurationStatsImpl(
|
protected abstract suspend fun getDurationStatsImpl(
|
||||||
query: SupportSQLiteQuery
|
query: SupportSQLiteQuery
|
||||||
): Map<@MapColumn("manga") MangaEntity, @MapColumn("d") Long>
|
): Map<@MapColumn("manga") MangaEntity, @MapColumn("d") Long>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM stats ORDER BY started_at LIMIT :limit OFFSET :offset")
|
||||||
|
protected abstract suspend fun findAll(offset: Int, limit: Int): List<StatsEntity>
|
||||||
|
fun dumpEnabled(): Flow<StatsEntity> = flow {
|
||||||
|
val window = 10
|
||||||
|
var offset = 0
|
||||||
|
while (currentCoroutineContext().isActive) {
|
||||||
|
val list = findAll(offset, window)
|
||||||
|
if (list.isEmpty()) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
offset += window
|
||||||
|
list.forEach { emit(it) }
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user