Update history
parent
a957021582
commit
64b38c561c
@ -1 +1,2 @@
|
|||||||
/build
|
/build
|
||||||
|
/schemas/
|
||||||
|
|||||||
@ -0,0 +1,40 @@
|
|||||||
|
package org.koitharu.kotatsu.core.db
|
||||||
|
|
||||||
|
import androidx.room.*
|
||||||
|
import org.koitharu.kotatsu.core.db.entity.MangaEntity
|
||||||
|
import org.koitharu.kotatsu.core.db.entity.MangaTagsEntity
|
||||||
|
import org.koitharu.kotatsu.core.db.entity.TagEntity
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
abstract class MangaDao {
|
||||||
|
|
||||||
|
@Query("SELECT * FROM manga")
|
||||||
|
abstract suspend fun getAllManga(): List<MangaEntity>
|
||||||
|
|
||||||
|
@Insert(onConflict = OnConflictStrategy.IGNORE)
|
||||||
|
abstract suspend fun insert(manga: MangaEntity): Long
|
||||||
|
|
||||||
|
@Update(onConflict = OnConflictStrategy.IGNORE)
|
||||||
|
abstract suspend fun update(manga: MangaEntity): Int
|
||||||
|
|
||||||
|
@Insert(onConflict = OnConflictStrategy.IGNORE)
|
||||||
|
abstract suspend fun insertTagRelation(tag: MangaTagsEntity): Long
|
||||||
|
|
||||||
|
@Query("DELETE FROM manga_tags WHERE manga_id = :mangaId")
|
||||||
|
abstract suspend fun clearTagRelation(mangaId: Long)
|
||||||
|
|
||||||
|
@Transaction
|
||||||
|
open suspend fun upsert(manga: MangaEntity, tags: Iterable<TagEntity>? = null) {
|
||||||
|
if (update(manga) <= 0) {
|
||||||
|
insert(manga)
|
||||||
|
if (tags != null) {
|
||||||
|
clearTagRelation(manga.id)
|
||||||
|
tags.map {
|
||||||
|
MangaTagsEntity(manga.id, it.id)
|
||||||
|
}.forEach {
|
||||||
|
insertTagRelation(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,14 +1,26 @@
|
|||||||
package org.koitharu.kotatsu.core.db
|
package org.koitharu.kotatsu.core.db
|
||||||
|
|
||||||
import androidx.room.Dao
|
import androidx.room.*
|
||||||
import androidx.room.Query
|
|
||||||
import androidx.room.Transaction
|
|
||||||
import org.koitharu.kotatsu.core.db.entity.TagEntity
|
import org.koitharu.kotatsu.core.db.entity.TagEntity
|
||||||
|
|
||||||
@Dao
|
@Dao
|
||||||
interface TagsDao {
|
interface TagsDao {
|
||||||
|
|
||||||
@Transaction
|
|
||||||
@Query("SELECT * FROM tags")
|
@Query("SELECT * FROM tags")
|
||||||
fun getAllTags(): List<TagEntity>
|
suspend fun getAllTags(): List<TagEntity>
|
||||||
|
|
||||||
|
@Insert(onConflict = OnConflictStrategy.IGNORE)
|
||||||
|
suspend fun insert(tag: TagEntity): Long
|
||||||
|
|
||||||
|
@Update(onConflict = OnConflictStrategy.IGNORE)
|
||||||
|
suspend fun update(tag: TagEntity): Int
|
||||||
|
|
||||||
|
@Transaction
|
||||||
|
suspend fun upsert(tags: Iterable<TagEntity>) {
|
||||||
|
tags.forEach { tag ->
|
||||||
|
if (update(tag) <= 0) {
|
||||||
|
insert(tag)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -1,53 +0,0 @@
|
|||||||
package org.koitharu.kotatsu.domain
|
|
||||||
|
|
||||||
import org.koin.core.KoinComponent
|
|
||||||
import org.koin.core.inject
|
|
||||||
import org.koitharu.kotatsu.core.db.MangaDatabase
|
|
||||||
import org.koitharu.kotatsu.core.db.entity.HistoryEntity
|
|
||||||
import org.koitharu.kotatsu.core.db.entity.HistoryWithManga
|
|
||||||
import org.koitharu.kotatsu.core.db.entity.MangaEntity
|
|
||||||
import org.koitharu.kotatsu.core.model.Manga
|
|
||||||
import org.koitharu.kotatsu.core.model.MangaHistory
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
class HistoryRepository : KoinComponent {
|
|
||||||
|
|
||||||
private val db: MangaDatabase by inject()
|
|
||||||
|
|
||||||
suspend fun getList(offset: Int) : List<Manga> {
|
|
||||||
val entities = db.historyDao().getAll(offset, 20, "updated_by")
|
|
||||||
return entities.map { it.manga.toManga() }
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun addOrUpdate(manga: Manga, chapterId: Long, page: Int) {
|
|
||||||
val dao = db.historyDao()
|
|
||||||
val entity = HistoryEntity(
|
|
||||||
mangaId = manga.id,
|
|
||||||
createdAt = System.currentTimeMillis(),
|
|
||||||
updatedAt = System.currentTimeMillis(),
|
|
||||||
chapterId = chapterId,
|
|
||||||
page = page
|
|
||||||
)
|
|
||||||
dao.upsert(
|
|
||||||
HistoryWithManga(
|
|
||||||
history = entity,
|
|
||||||
manga = MangaEntity.from(manga)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun getOne(manga: Manga): MangaHistory? {
|
|
||||||
return db.historyDao().getOneOrNull(manga.id)?.let {
|
|
||||||
MangaHistory(
|
|
||||||
createdAt = Date(it.createdAt),
|
|
||||||
updatedAt = Date(it.updatedAt),
|
|
||||||
chapterId = it.chapterId,
|
|
||||||
page = it.page
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun clear() {
|
|
||||||
db.historyDao().clear()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package org.koitharu.kotatsu.domain
|
package org.koitharu.kotatsu.domain.history
|
||||||
|
|
||||||
enum class ChapterExtra {
|
enum class ChapterExtra {
|
||||||
|
|
||||||
@ -0,0 +1,74 @@
|
|||||||
|
package org.koitharu.kotatsu.domain.history
|
||||||
|
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
import org.koin.core.KoinComponent
|
||||||
|
import org.koin.core.inject
|
||||||
|
import org.koitharu.kotatsu.core.db.MangaDatabase
|
||||||
|
import org.koitharu.kotatsu.core.db.entity.HistoryEntity
|
||||||
|
import org.koitharu.kotatsu.core.db.entity.MangaEntity
|
||||||
|
import org.koitharu.kotatsu.core.db.entity.TagEntity
|
||||||
|
import org.koitharu.kotatsu.core.model.Manga
|
||||||
|
import org.koitharu.kotatsu.core.model.MangaHistory
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
class HistoryRepository : KoinComponent {
|
||||||
|
|
||||||
|
private val db: MangaDatabase by inject()
|
||||||
|
|
||||||
|
suspend fun getList(offset: Int): List<Manga> {
|
||||||
|
val entities = db.historyDao().getAll(offset, 20, "updated_at")
|
||||||
|
return entities.map { it.manga.toManga(it.tags.map(TagEntity::toMangaTag).toSet()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun addOrUpdate(manga: Manga, chapterId: Long, page: Int) {
|
||||||
|
val tags = manga.tags.map(TagEntity.Companion::fromMangaTag)
|
||||||
|
db.tagsDao().upsert(tags)
|
||||||
|
db.mangaDao().upsert(MangaEntity.from(manga), tags)
|
||||||
|
db.historyDao().upsert(
|
||||||
|
HistoryEntity(
|
||||||
|
mangaId = manga.id,
|
||||||
|
createdAt = System.currentTimeMillis(),
|
||||||
|
updatedAt = System.currentTimeMillis(),
|
||||||
|
chapterId = chapterId,
|
||||||
|
page = page
|
||||||
|
)
|
||||||
|
)
|
||||||
|
notifyHistoryChanged()
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun getOne(manga: Manga): MangaHistory? {
|
||||||
|
return db.historyDao().getOneOrNull(manga.id)?.let {
|
||||||
|
MangaHistory(
|
||||||
|
createdAt = Date(it.createdAt),
|
||||||
|
updatedAt = Date(it.updatedAt),
|
||||||
|
chapterId = it.chapterId,
|
||||||
|
page = it.page
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun clear() {
|
||||||
|
db.historyDao().clear()
|
||||||
|
notifyHistoryChanged()
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
private val listeners = HashSet<OnHistoryChangeListener>()
|
||||||
|
|
||||||
|
fun subscribe(listener: OnHistoryChangeListener) {
|
||||||
|
listeners += listener
|
||||||
|
}
|
||||||
|
|
||||||
|
fun unsubscribe(listener: OnHistoryChangeListener) {
|
||||||
|
listeners += listener
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun notifyHistoryChanged() {
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
listeners.forEach { x -> x.onHistoryChanged() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
package org.koitharu.kotatsu.domain.history
|
||||||
|
|
||||||
|
interface OnHistoryChangeListener {
|
||||||
|
|
||||||
|
fun onHistoryChanged()
|
||||||
|
}
|
||||||
@ -0,0 +1,33 @@
|
|||||||
|
package org.koitharu.kotatsu.ui.common
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.View
|
||||||
|
|
||||||
|
abstract class BaseFullscreenActivity : BaseActivity() {
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onWindowFocusChanged(hasFocus: Boolean) {
|
||||||
|
super.onWindowFocusChanged(hasFocus)
|
||||||
|
if (hasFocus) hideSystemUI()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun hideSystemUI() {
|
||||||
|
window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
|
||||||
|
or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
|
||||||
|
or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
|
||||||
|
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
|
||||||
|
or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
|
||||||
|
or View.SYSTEM_UI_FLAG_FULLSCREEN)
|
||||||
|
}
|
||||||
|
|
||||||
|
protected fun showSystemUI() {
|
||||||
|
window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LAYOUT_STABLE
|
||||||
|
or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
|
||||||
|
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract fun onFullscreenModeChanged(isFullscreen: Boolean)
|
||||||
|
}
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<vector
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:tint="?android:textColorPrimary"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="#000"
|
||||||
|
android:pathData="M17,18V5H7V18L12,15.82L17,18M17,3A2,2 0 0,1 19,5V21L12,18L5,21V5C5,3.89 5.9,3 7,3H17M11,7H13V9H15V11H13V13H11V11H9V9H11V7Z" />
|
||||||
|
</vector>
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
<vector
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:tint="?android:textColorPrimary"
|
||||||
|
android:viewportWidth="24.0"
|
||||||
|
android:viewportHeight="24.0">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M3,17v2h6v-2L3,17zM3,5v2h10L13,5L3,5zM13,21v-2h8v-2h-8v-2h-2v6h2zM7,9v2L3,11v2h4v2h2L9,9L7,9zM21,13v-2L11,11v2h10zM15,9h2L17,7h4L21,5h-4L17,3h-2v6z" />
|
||||||
|
</vector>
|
||||||
@ -1,8 +1,18 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
<menu
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
<item android:id="@+id/action_settings"
|
<item
|
||||||
android:title="@string/settings" />
|
android:id="@+id/action_bookmark_add"
|
||||||
|
android:icon="@drawable/ic_bookmark_add"
|
||||||
|
android:title="@string/add_bookmark"
|
||||||
|
app:showAsAction="ifRoom" />
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_settings"
|
||||||
|
android:icon="@drawable/ic_tune"
|
||||||
|
android:title="@string/settings"
|
||||||
|
app:showAsAction="ifRoom" />
|
||||||
|
|
||||||
</menu>
|
</menu>
|
||||||
Loading…
Reference in New Issue