mirror of
https://github.com/aniyomiorg/aniyomi.git
synced 2024-11-22 04:39:32 +03:00
parent
338b54a39c
commit
83dcd5ea31
50 changed files with 360 additions and 220 deletions
|
@ -2,6 +2,7 @@ package eu.kanade.presentation.browse.anime
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.PaddingValues
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
@ -19,7 +20,6 @@ import eu.kanade.tachiyomi.ui.browse.anime.source.globalsearch.AnimeSearchItemRe
|
||||||
import eu.kanade.tachiyomi.ui.browse.anime.source.globalsearch.GlobalAnimeSearchState
|
import eu.kanade.tachiyomi.ui.browse.anime.source.globalsearch.GlobalAnimeSearchState
|
||||||
import eu.kanade.tachiyomi.util.system.LocaleHelper
|
import eu.kanade.tachiyomi.util.system.LocaleHelper
|
||||||
import tachiyomi.domain.entries.anime.model.Anime
|
import tachiyomi.domain.entries.anime.model.Anime
|
||||||
import tachiyomi.presentation.core.components.LazyColumn
|
|
||||||
import tachiyomi.presentation.core.components.material.Scaffold
|
import tachiyomi.presentation.core.components.material.Scaffold
|
||||||
import tachiyomi.presentation.core.components.material.padding
|
import tachiyomi.presentation.core.components.material.padding
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package eu.kanade.presentation.browse.anime
|
package eu.kanade.presentation.browse.anime
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.PaddingValues
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.State
|
import androidx.compose.runtime.State
|
||||||
import eu.kanade.presentation.browse.GlobalSearchEmptyResultItem
|
import eu.kanade.presentation.browse.GlobalSearchEmptyResultItem
|
||||||
|
@ -14,7 +15,6 @@ import eu.kanade.tachiyomi.ui.browse.anime.migration.search.MigrateAnimeSearchSt
|
||||||
import eu.kanade.tachiyomi.ui.browse.anime.source.globalsearch.AnimeSearchItemResult
|
import eu.kanade.tachiyomi.ui.browse.anime.source.globalsearch.AnimeSearchItemResult
|
||||||
import eu.kanade.tachiyomi.util.system.LocaleHelper
|
import eu.kanade.tachiyomi.util.system.LocaleHelper
|
||||||
import tachiyomi.domain.entries.anime.model.Anime
|
import tachiyomi.domain.entries.anime.model.Anime
|
||||||
import tachiyomi.presentation.core.components.LazyColumn
|
|
||||||
import tachiyomi.presentation.core.components.material.Scaffold
|
import tachiyomi.presentation.core.components.material.Scaffold
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package eu.kanade.presentation.browse.anime.components
|
package eu.kanade.presentation.browse.anime.components
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.PaddingValues
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
|
@ -14,7 +15,6 @@ import eu.kanade.presentation.library.EntryListItem
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import tachiyomi.domain.entries.anime.model.Anime
|
import tachiyomi.domain.entries.anime.model.Anime
|
||||||
import tachiyomi.domain.entries.anime.model.AnimeCover
|
import tachiyomi.domain.entries.anime.model.AnimeCover
|
||||||
import tachiyomi.presentation.core.components.LazyColumn
|
|
||||||
import tachiyomi.presentation.core.util.plus
|
import tachiyomi.presentation.core.util.plus
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
|
|
@ -2,6 +2,7 @@ package eu.kanade.presentation.browse.manga
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.PaddingValues
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
@ -19,7 +20,6 @@ import eu.kanade.tachiyomi.ui.browse.manga.source.globalsearch.GlobalMangaSearch
|
||||||
import eu.kanade.tachiyomi.ui.browse.manga.source.globalsearch.MangaSearchItemResult
|
import eu.kanade.tachiyomi.ui.browse.manga.source.globalsearch.MangaSearchItemResult
|
||||||
import eu.kanade.tachiyomi.util.system.LocaleHelper
|
import eu.kanade.tachiyomi.util.system.LocaleHelper
|
||||||
import tachiyomi.domain.entries.manga.model.Manga
|
import tachiyomi.domain.entries.manga.model.Manga
|
||||||
import tachiyomi.presentation.core.components.LazyColumn
|
|
||||||
import tachiyomi.presentation.core.components.material.Scaffold
|
import tachiyomi.presentation.core.components.material.Scaffold
|
||||||
import tachiyomi.presentation.core.components.material.padding
|
import tachiyomi.presentation.core.components.material.padding
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package eu.kanade.presentation.browse.manga
|
package eu.kanade.presentation.browse.manga
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.PaddingValues
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.State
|
import androidx.compose.runtime.State
|
||||||
import eu.kanade.presentation.browse.GlobalSearchEmptyResultItem
|
import eu.kanade.presentation.browse.GlobalSearchEmptyResultItem
|
||||||
|
@ -14,7 +15,6 @@ import eu.kanade.tachiyomi.ui.browse.manga.migration.search.MigrateMangaSearchSt
|
||||||
import eu.kanade.tachiyomi.ui.browse.manga.source.globalsearch.MangaSearchItemResult
|
import eu.kanade.tachiyomi.ui.browse.manga.source.globalsearch.MangaSearchItemResult
|
||||||
import eu.kanade.tachiyomi.util.system.LocaleHelper
|
import eu.kanade.tachiyomi.util.system.LocaleHelper
|
||||||
import tachiyomi.domain.entries.manga.model.Manga
|
import tachiyomi.domain.entries.manga.model.Manga
|
||||||
import tachiyomi.presentation.core.components.LazyColumn
|
|
||||||
import tachiyomi.presentation.core.components.material.Scaffold
|
import tachiyomi.presentation.core.components.material.Scaffold
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package eu.kanade.presentation.browse.manga.components
|
package eu.kanade.presentation.browse.manga.components
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.PaddingValues
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
|
@ -13,7 +14,6 @@ import eu.kanade.presentation.library.EntryListItem
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import tachiyomi.domain.entries.manga.model.Manga
|
import tachiyomi.domain.entries.manga.model.Manga
|
||||||
import tachiyomi.domain.entries.manga.model.MangaCover
|
import tachiyomi.domain.entries.manga.model.MangaCover
|
||||||
import tachiyomi.presentation.core.components.LazyColumn
|
|
||||||
import tachiyomi.presentation.core.util.plus
|
import tachiyomi.presentation.core.util.plus
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
|
|
@ -2,13 +2,13 @@ package eu.kanade.presentation.category.components
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.PaddingValues
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.LazyListState
|
import androidx.compose.foundation.lazy.LazyListState
|
||||||
import androidx.compose.foundation.lazy.itemsIndexed
|
import androidx.compose.foundation.lazy.itemsIndexed
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import tachiyomi.domain.category.model.Category
|
import tachiyomi.domain.category.model.Category
|
||||||
import tachiyomi.presentation.core.components.LazyColumn
|
|
||||||
import tachiyomi.presentation.core.components.material.padding
|
import tachiyomi.presentation.core.components.material.padding
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
|
|
@ -18,6 +18,7 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.only
|
import androidx.compose.foundation.layout.only
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.systemBars
|
import androidx.compose.foundation.layout.systemBars
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.LazyListScope
|
import androidx.compose.foundation.lazy.LazyListScope
|
||||||
import androidx.compose.foundation.lazy.items
|
import androidx.compose.foundation.lazy.items
|
||||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||||
|
@ -81,7 +82,6 @@ import tachiyomi.domain.items.episode.model.Episode
|
||||||
import tachiyomi.domain.items.service.missingItemsCount
|
import tachiyomi.domain.items.service.missingItemsCount
|
||||||
import tachiyomi.domain.library.service.LibraryPreferences
|
import tachiyomi.domain.library.service.LibraryPreferences
|
||||||
import tachiyomi.domain.source.anime.model.StubAnimeSource
|
import tachiyomi.domain.source.anime.model.StubAnimeSource
|
||||||
import tachiyomi.presentation.core.components.LazyColumn
|
|
||||||
import tachiyomi.presentation.core.components.TwoPanelBox
|
import tachiyomi.presentation.core.components.TwoPanelBox
|
||||||
import tachiyomi.presentation.core.components.VerticalFastScroller
|
import tachiyomi.presentation.core.components.VerticalFastScroller
|
||||||
import tachiyomi.presentation.core.components.material.ExtendedFloatingActionButton
|
import tachiyomi.presentation.core.components.material.ExtendedFloatingActionButton
|
||||||
|
|
|
@ -18,6 +18,7 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.only
|
import androidx.compose.foundation.layout.only
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.systemBars
|
import androidx.compose.foundation.layout.systemBars
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.LazyListScope
|
import androidx.compose.foundation.lazy.LazyListScope
|
||||||
import androidx.compose.foundation.lazy.items
|
import androidx.compose.foundation.lazy.items
|
||||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||||
|
@ -75,7 +76,6 @@ import tachiyomi.domain.items.chapter.model.Chapter
|
||||||
import tachiyomi.domain.items.service.missingItemsCount
|
import tachiyomi.domain.items.service.missingItemsCount
|
||||||
import tachiyomi.domain.library.service.LibraryPreferences
|
import tachiyomi.domain.library.service.LibraryPreferences
|
||||||
import tachiyomi.domain.source.manga.model.StubMangaSource
|
import tachiyomi.domain.source.manga.model.StubMangaSource
|
||||||
import tachiyomi.presentation.core.components.LazyColumn
|
|
||||||
import tachiyomi.presentation.core.components.TwoPanelBox
|
import tachiyomi.presentation.core.components.TwoPanelBox
|
||||||
import tachiyomi.presentation.core.components.VerticalFastScroller
|
import tachiyomi.presentation.core.components.VerticalFastScroller
|
||||||
import tachiyomi.presentation.core.components.material.ExtendedFloatingActionButton
|
import tachiyomi.presentation.core.components.material.ExtendedFloatingActionButton
|
||||||
|
|
|
@ -4,6 +4,7 @@ import androidx.annotation.StringRes
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.isSystemInDarkTheme
|
import androidx.compose.foundation.isSystemInDarkTheme
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.itemsIndexed
|
import androidx.compose.foundation.lazy.itemsIndexed
|
||||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
@ -50,7 +51,6 @@ import eu.kanade.presentation.more.settings.widget.TextPreferenceWidget
|
||||||
import eu.kanade.presentation.util.LocalBackPress
|
import eu.kanade.presentation.util.LocalBackPress
|
||||||
import eu.kanade.presentation.util.Screen
|
import eu.kanade.presentation.util.Screen
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import tachiyomi.presentation.core.components.LazyColumn
|
|
||||||
import tachiyomi.presentation.core.components.material.Scaffold
|
import tachiyomi.presentation.core.components.material.Scaffold
|
||||||
import cafe.adriel.voyager.core.screen.Screen as VoyagerScreen
|
import cafe.adriel.voyager.core.screen.Screen as VoyagerScreen
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ import android.content.Context
|
||||||
import androidx.compose.foundation.horizontalScroll
|
import androidx.compose.foundation.horizontalScroll
|
||||||
import androidx.compose.foundation.layout.PaddingValues
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.ArrowBack
|
import androidx.compose.material.icons.filled.ArrowBack
|
||||||
|
@ -39,7 +40,6 @@ import eu.kanade.tachiyomi.util.system.workManager
|
||||||
import kotlinx.coroutines.flow.SharingStarted
|
import kotlinx.coroutines.flow.SharingStarted
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
import kotlinx.coroutines.flow.stateIn
|
import kotlinx.coroutines.flow.stateIn
|
||||||
import tachiyomi.presentation.core.components.LazyColumn
|
|
||||||
import tachiyomi.presentation.core.components.material.Scaffold
|
import tachiyomi.presentation.core.components.material.Scaffold
|
||||||
import tachiyomi.presentation.core.util.plus
|
import tachiyomi.presentation.core.util.plus
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.defaultMinSize
|
import androidx.compose.foundation.layout.defaultMinSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.itemsIndexed
|
import androidx.compose.foundation.lazy.itemsIndexed
|
||||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
|
@ -28,7 +29,6 @@ import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import tachiyomi.presentation.core.components.LazyColumn
|
|
||||||
import tachiyomi.presentation.core.components.material.Divider
|
import tachiyomi.presentation.core.components.material.Divider
|
||||||
import tachiyomi.presentation.core.util.isScrolledToEnd
|
import tachiyomi.presentation.core.util.isScrolledToEnd
|
||||||
import tachiyomi.presentation.core.util.isScrolledToStart
|
import tachiyomi.presentation.core.util.isScrolledToStart
|
||||||
|
|
|
@ -3,6 +3,7 @@ package eu.kanade.presentation.more.stats
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.PaddingValues
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.outlined.CollectionsBookmark
|
import androidx.compose.material.icons.outlined.CollectionsBookmark
|
||||||
|
@ -19,7 +20,6 @@ import eu.kanade.presentation.more.stats.components.StatsSection
|
||||||
import eu.kanade.presentation.more.stats.data.StatsData
|
import eu.kanade.presentation.more.stats.data.StatsData
|
||||||
import eu.kanade.presentation.util.toDurationString
|
import eu.kanade.presentation.util.toDurationString
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import tachiyomi.presentation.core.components.LazyColumn
|
|
||||||
import tachiyomi.presentation.core.components.material.padding
|
import tachiyomi.presentation.core.components.material.padding
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
import kotlin.time.DurationUnit
|
import kotlin.time.DurationUnit
|
||||||
|
|
|
@ -3,6 +3,7 @@ package eu.kanade.presentation.more.stats
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.PaddingValues
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.outlined.CollectionsBookmark
|
import androidx.compose.material.icons.outlined.CollectionsBookmark
|
||||||
|
@ -19,7 +20,6 @@ import eu.kanade.presentation.more.stats.components.StatsSection
|
||||||
import eu.kanade.presentation.more.stats.data.StatsData
|
import eu.kanade.presentation.more.stats.data.StatsData
|
||||||
import eu.kanade.presentation.util.toDurationString
|
import eu.kanade.presentation.util.toDurationString
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import tachiyomi.presentation.core.components.LazyColumn
|
|
||||||
import tachiyomi.presentation.core.components.material.padding
|
import tachiyomi.presentation.core.components.material.padding
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
import kotlin.time.DurationUnit
|
import kotlin.time.DurationUnit
|
||||||
|
|
|
@ -8,6 +8,7 @@ import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxHeight
|
import androidx.compose.foundation.layout.fillMaxHeight
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
|
@ -19,7 +20,6 @@ import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import eu.kanade.presentation.util.isTabletUi
|
import eu.kanade.presentation.util.isTabletUi
|
||||||
import tachiyomi.domain.category.model.Category
|
import tachiyomi.domain.category.model.Category
|
||||||
import tachiyomi.presentation.core.components.LazyColumn
|
|
||||||
import tachiyomi.presentation.core.components.material.padding
|
import tachiyomi.presentation.core.components.material.padding
|
||||||
import tachiyomi.presentation.core.screens.LoadingScreen
|
import tachiyomi.presentation.core.screens.LoadingScreen
|
||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
|
|
|
@ -37,6 +37,8 @@ data class BackupAnime(
|
||||||
@ProtoNumber(103) var viewer_flags: Int = 0,
|
@ProtoNumber(103) var viewer_flags: Int = 0,
|
||||||
@ProtoNumber(104) var history: List<BackupAnimeHistory> = emptyList(),
|
@ProtoNumber(104) var history: List<BackupAnimeHistory> = emptyList(),
|
||||||
@ProtoNumber(105) var updateStrategy: UpdateStrategy = UpdateStrategy.ALWAYS_UPDATE,
|
@ProtoNumber(105) var updateStrategy: UpdateStrategy = UpdateStrategy.ALWAYS_UPDATE,
|
||||||
|
@ProtoNumber(106) var lastModifiedAt: Long = 0,
|
||||||
|
@ProtoNumber(107) var favoriteModifiedAt: Long? = null,
|
||||||
) {
|
) {
|
||||||
fun getAnimeImpl(): Anime {
|
fun getAnimeImpl(): Anime {
|
||||||
return Anime.create().copy(
|
return Anime.create().copy(
|
||||||
|
@ -54,6 +56,8 @@ data class BackupAnime(
|
||||||
viewerFlags = this@BackupAnime.viewer_flags.toLong(),
|
viewerFlags = this@BackupAnime.viewer_flags.toLong(),
|
||||||
episodeFlags = this@BackupAnime.episodeFlags.toLong(),
|
episodeFlags = this@BackupAnime.episodeFlags.toLong(),
|
||||||
updateStrategy = this@BackupAnime.updateStrategy,
|
updateStrategy = this@BackupAnime.updateStrategy,
|
||||||
|
lastModifiedAt = this@BackupAnime.lastModifiedAt,
|
||||||
|
favoriteModifiedAt = this@BackupAnime.favoriteModifiedAt,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,6 +90,8 @@ data class BackupAnime(
|
||||||
viewer_flags = anime.skipIntroLength,
|
viewer_flags = anime.skipIntroLength,
|
||||||
episodeFlags = anime.episodeFlags.toInt(),
|
episodeFlags = anime.episodeFlags.toInt(),
|
||||||
updateStrategy = anime.updateStrategy,
|
updateStrategy = anime.updateStrategy,
|
||||||
|
lastModifiedAt = anime.lastModifiedAt,
|
||||||
|
favoriteModifiedAt = anime.favoriteModifiedAt,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ data class BackupChapter(
|
||||||
// chapterNumber is called number is 1.x
|
// chapterNumber is called number is 1.x
|
||||||
@ProtoNumber(9) var chapterNumber: Float = 0F,
|
@ProtoNumber(9) var chapterNumber: Float = 0F,
|
||||||
@ProtoNumber(10) var sourceOrder: Long = 0,
|
@ProtoNumber(10) var sourceOrder: Long = 0,
|
||||||
|
@ProtoNumber(11) var lastModifiedAt: Long = 0,
|
||||||
) {
|
) {
|
||||||
fun toChapterImpl(): Chapter {
|
fun toChapterImpl(): Chapter {
|
||||||
return Chapter.create().copy(
|
return Chapter.create().copy(
|
||||||
|
@ -33,11 +34,13 @@ data class BackupChapter(
|
||||||
dateFetch = this@BackupChapter.dateFetch,
|
dateFetch = this@BackupChapter.dateFetch,
|
||||||
dateUpload = this@BackupChapter.dateUpload,
|
dateUpload = this@BackupChapter.dateUpload,
|
||||||
sourceOrder = this@BackupChapter.sourceOrder,
|
sourceOrder = this@BackupChapter.sourceOrder,
|
||||||
|
lastModifiedAt = this@BackupChapter.lastModifiedAt,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val backupChapterMapper = { _: Long, _: Long, url: String, name: String, scanlator: String?, read: Boolean, bookmark: Boolean, lastPageRead: Long, chapterNumber: Float, source_order: Long, dateFetch: Long, dateUpload: Long ->
|
val backupChapterMapper = { _: Long, _: Long, url: String, name: String, scanlator: String?, read: Boolean, bookmark:
|
||||||
|
Boolean, lastPageRead: Long, chapterNumber: Float, source_order: Long, dateFetch: Long, dateUpload: Long, lastModifiedAt: Long ->
|
||||||
BackupChapter(
|
BackupChapter(
|
||||||
url = url,
|
url = url,
|
||||||
name = name,
|
name = name,
|
||||||
|
@ -49,5 +52,6 @@ val backupChapterMapper = { _: Long, _: Long, url: String, name: String, scanlat
|
||||||
dateFetch = dateFetch,
|
dateFetch = dateFetch,
|
||||||
dateUpload = dateUpload,
|
dateUpload = dateUpload,
|
||||||
sourceOrder = source_order,
|
sourceOrder = source_order,
|
||||||
|
lastModifiedAt = lastModifiedAt,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ data class BackupEpisode(
|
||||||
// episodeNumber is called number is 1.x
|
// episodeNumber is called number is 1.x
|
||||||
@ProtoNumber(9) var episodeNumber: Float = 0F,
|
@ProtoNumber(9) var episodeNumber: Float = 0F,
|
||||||
@ProtoNumber(10) var sourceOrder: Long = 0,
|
@ProtoNumber(10) var sourceOrder: Long = 0,
|
||||||
|
@ProtoNumber(11) var lastModifiedAt: Long = 0,
|
||||||
) {
|
) {
|
||||||
fun toEpisodeImpl(): Episode {
|
fun toEpisodeImpl(): Episode {
|
||||||
return Episode.create().copy(
|
return Episode.create().copy(
|
||||||
|
@ -35,11 +36,13 @@ data class BackupEpisode(
|
||||||
dateFetch = this@BackupEpisode.dateFetch,
|
dateFetch = this@BackupEpisode.dateFetch,
|
||||||
dateUpload = this@BackupEpisode.dateUpload,
|
dateUpload = this@BackupEpisode.dateUpload,
|
||||||
sourceOrder = this@BackupEpisode.sourceOrder,
|
sourceOrder = this@BackupEpisode.sourceOrder,
|
||||||
|
lastModifiedAt = this@BackupEpisode.lastModifiedAt,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val backupEpisodeMapper = { _: Long, _: Long, url: String, name: String, scanlator: String?, seen: Boolean, bookmark: Boolean, lastSecondSeen: Long, totalSeconds: Long, episodeNumber: Float, source_order: Long, dateFetch: Long, dateUpload: Long ->
|
val backupEpisodeMapper = { _: Long, _: Long, url: String, name: String, scanlator: String?, seen: Boolean, bookmark:
|
||||||
|
Boolean, lastSecondSeen: Long, totalSeconds: Long, episodeNumber: Float, source_order: Long, dateFetch: Long, dateUpload: Long, lastModifiedAt: Long ->
|
||||||
BackupEpisode(
|
BackupEpisode(
|
||||||
url = url,
|
url = url,
|
||||||
name = name,
|
name = name,
|
||||||
|
@ -52,5 +55,6 @@ val backupEpisodeMapper = { _: Long, _: Long, url: String, name: String, scanlat
|
||||||
dateFetch = dateFetch,
|
dateFetch = dateFetch,
|
||||||
dateUpload = dateUpload,
|
dateUpload = dateUpload,
|
||||||
sourceOrder = source_order,
|
sourceOrder = source_order,
|
||||||
|
lastModifiedAt = lastModifiedAt,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,8 @@ data class BackupManga(
|
||||||
@ProtoNumber(103) var viewer_flags: Int? = null,
|
@ProtoNumber(103) var viewer_flags: Int? = null,
|
||||||
@ProtoNumber(104) var history: List<BackupHistory> = emptyList(),
|
@ProtoNumber(104) var history: List<BackupHistory> = emptyList(),
|
||||||
@ProtoNumber(105) var updateStrategy: UpdateStrategy = UpdateStrategy.ALWAYS_UPDATE,
|
@ProtoNumber(105) var updateStrategy: UpdateStrategy = UpdateStrategy.ALWAYS_UPDATE,
|
||||||
|
@ProtoNumber(106) var lastModifiedAt: Long = 0,
|
||||||
|
@ProtoNumber(107) var favoriteModifiedAt: Long? = null,
|
||||||
) {
|
) {
|
||||||
fun getMangaImpl(): Manga {
|
fun getMangaImpl(): Manga {
|
||||||
return Manga.create().copy(
|
return Manga.create().copy(
|
||||||
|
@ -56,6 +58,8 @@ data class BackupManga(
|
||||||
viewerFlags = (this@BackupManga.viewer_flags ?: this@BackupManga.viewer).toLong(),
|
viewerFlags = (this@BackupManga.viewer_flags ?: this@BackupManga.viewer).toLong(),
|
||||||
chapterFlags = this@BackupManga.chapterFlags.toLong(),
|
chapterFlags = this@BackupManga.chapterFlags.toLong(),
|
||||||
updateStrategy = this@BackupManga.updateStrategy,
|
updateStrategy = this@BackupManga.updateStrategy,
|
||||||
|
lastModifiedAt = this@BackupManga.lastModifiedAt,
|
||||||
|
favoriteModifiedAt = this@BackupManga.favoriteModifiedAt,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,6 +93,8 @@ data class BackupManga(
|
||||||
viewer_flags = manga.viewerFlags.toInt(),
|
viewer_flags = manga.viewerFlags.toInt(),
|
||||||
chapterFlags = manga.chapterFlags.toInt(),
|
chapterFlags = manga.chapterFlags.toInt(),
|
||||||
updateStrategy = manga.updateStrategy,
|
updateStrategy = manga.updateStrategy,
|
||||||
|
lastModifiedAt = manga.lastModifiedAt,
|
||||||
|
favoriteModifiedAt = manga.favoriteModifiedAt,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,8 @@ interface Episode : SEpisode, Serializable {
|
||||||
var date_fetch: Long
|
var date_fetch: Long
|
||||||
|
|
||||||
var source_order: Int
|
var source_order: Int
|
||||||
|
|
||||||
|
var last_modified: Long
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Episode.toDomainEpisode(): DomainEpisode? {
|
fun Episode.toDomainEpisode(): DomainEpisode? {
|
||||||
|
@ -39,5 +41,6 @@ fun Episode.toDomainEpisode(): DomainEpisode? {
|
||||||
dateUpload = date_upload,
|
dateUpload = date_upload,
|
||||||
episodeNumber = episode_number,
|
episodeNumber = episode_number,
|
||||||
scanlator = scanlator,
|
scanlator = scanlator,
|
||||||
|
lastModifiedAt = last_modified,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,8 @@ class EpisodeImpl : Episode {
|
||||||
|
|
||||||
override var source_order: Int = 0
|
override var source_order: Int = 0
|
||||||
|
|
||||||
|
override var last_modified: Long = 0
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean {
|
override fun equals(other: Any?): Boolean {
|
||||||
if (this === other) return true
|
if (this === other) return true
|
||||||
if (other == null || javaClass != other.javaClass) return false
|
if (other == null || javaClass != other.javaClass) return false
|
||||||
|
|
|
@ -19,6 +19,8 @@ interface Chapter : SChapter, Serializable {
|
||||||
var date_fetch: Long
|
var date_fetch: Long
|
||||||
|
|
||||||
var source_order: Int
|
var source_order: Int
|
||||||
|
|
||||||
|
var last_modified: Long
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Chapter.toDomainChapter(): DomainChapter? {
|
fun Chapter.toDomainChapter(): DomainChapter? {
|
||||||
|
@ -36,5 +38,6 @@ fun Chapter.toDomainChapter(): DomainChapter? {
|
||||||
dateUpload = date_upload,
|
dateUpload = date_upload,
|
||||||
chapterNumber = chapter_number,
|
chapterNumber = chapter_number,
|
||||||
scanlator = scanlator,
|
scanlator = scanlator,
|
||||||
|
lastModifiedAt = last_modified,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,8 @@ class ChapterImpl : Chapter {
|
||||||
|
|
||||||
override var source_order: Int = 0
|
override var source_order: Int = 0
|
||||||
|
|
||||||
|
override var last_modified: Long = 0
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean {
|
override fun equals(other: Any?): Boolean {
|
||||||
if (this === other) return true
|
if (this === other) return true
|
||||||
if (other == null || javaClass != other.javaClass) return false
|
if (other == null || javaClass != other.javaClass) return false
|
||||||
|
|
|
@ -5,6 +5,7 @@ import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.items
|
import androidx.compose.foundation.lazy.items
|
||||||
import androidx.compose.material3.Button
|
import androidx.compose.material3.Button
|
||||||
import androidx.compose.material3.Divider
|
import androidx.compose.material3.Divider
|
||||||
|
@ -26,7 +27,6 @@ import tachiyomi.domain.entries.TriStateFilter
|
||||||
import tachiyomi.presentation.core.components.CheckboxItem
|
import tachiyomi.presentation.core.components.CheckboxItem
|
||||||
import tachiyomi.presentation.core.components.CollapsibleBox
|
import tachiyomi.presentation.core.components.CollapsibleBox
|
||||||
import tachiyomi.presentation.core.components.HeadingItem
|
import tachiyomi.presentation.core.components.HeadingItem
|
||||||
import tachiyomi.presentation.core.components.LazyColumn
|
|
||||||
import tachiyomi.presentation.core.components.SortItem
|
import tachiyomi.presentation.core.components.SortItem
|
||||||
import tachiyomi.presentation.core.components.TextItem
|
import tachiyomi.presentation.core.components.TextItem
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.items
|
import androidx.compose.foundation.lazy.items
|
||||||
import androidx.compose.material3.LocalTextStyle
|
import androidx.compose.material3.LocalTextStyle
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
@ -24,7 +25,6 @@ import tachiyomi.domain.entries.TriStateFilter
|
||||||
import tachiyomi.presentation.core.components.CheckboxItem
|
import tachiyomi.presentation.core.components.CheckboxItem
|
||||||
import tachiyomi.presentation.core.components.CollapsibleBox
|
import tachiyomi.presentation.core.components.CollapsibleBox
|
||||||
import tachiyomi.presentation.core.components.HeadingItem
|
import tachiyomi.presentation.core.components.HeadingItem
|
||||||
import tachiyomi.presentation.core.components.LazyColumn
|
|
||||||
import tachiyomi.presentation.core.components.SortItem
|
import tachiyomi.presentation.core.components.SortItem
|
||||||
import tachiyomi.presentation.core.components.TextItem
|
import tachiyomi.presentation.core.components.TextItem
|
||||||
import tachiyomi.presentation.core.components.material.Button
|
import tachiyomi.presentation.core.components.material.Button
|
||||||
|
|
|
@ -9,6 +9,7 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.sizeIn
|
import androidx.compose.foundation.layout.sizeIn
|
||||||
import androidx.compose.foundation.layout.width
|
import androidx.compose.foundation.layout.width
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.items
|
import androidx.compose.foundation.lazy.items
|
||||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
|
@ -38,7 +39,6 @@ import eu.kanade.tachiyomi.data.database.models.anime.Episode
|
||||||
import eu.kanade.tachiyomi.ui.entries.anime.episodeDecimalFormat
|
import eu.kanade.tachiyomi.ui.entries.anime.episodeDecimalFormat
|
||||||
import eu.kanade.tachiyomi.util.lang.toRelativeString
|
import eu.kanade.tachiyomi.util.lang.toRelativeString
|
||||||
import tachiyomi.domain.entries.anime.model.Anime
|
import tachiyomi.domain.entries.anime.model.Anime
|
||||||
import tachiyomi.presentation.core.components.LazyColumn
|
|
||||||
import tachiyomi.presentation.core.components.VerticalFastScroller
|
import tachiyomi.presentation.core.components.VerticalFastScroller
|
||||||
import tachiyomi.presentation.core.components.material.ReadItemAlpha
|
import tachiyomi.presentation.core.components.material.ReadItemAlpha
|
||||||
import tachiyomi.presentation.core.components.material.padding
|
import tachiyomi.presentation.core.components.material.padding
|
||||||
|
|
|
@ -235,13 +235,18 @@ class ReaderActivity : BaseActivity() {
|
||||||
readingModeToast?.cancel()
|
readingModeToast?.cancel()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onPause() {
|
||||||
|
viewModel.flushReadTimer()
|
||||||
|
super.onPause()
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set menu visibility again on activity resume to apply immersive mode again if needed.
|
* Set menu visibility again on activity resume to apply immersive mode again if needed.
|
||||||
* Helps with rotations.
|
* Helps with rotations.
|
||||||
*/
|
*/
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
viewModel.setReadStartTime()
|
viewModel.restartReadTimer()
|
||||||
setMenuVisibility(viewModel.state.value.menuVisible, animate = false)
|
setMenuVisibility(viewModel.state.value.menuVisible, animate = false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -591,7 +596,7 @@ class ReaderActivity : BaseActivity() {
|
||||||
* Sets the visibility of the menu according to [visible] and with an optional parameter to
|
* Sets the visibility of the menu according to [visible] and with an optional parameter to
|
||||||
* [animate] the views.
|
* [animate] the views.
|
||||||
*/
|
*/
|
||||||
fun setMenuVisibility(visible: Boolean, animate: Boolean = true) {
|
private fun setMenuVisibility(visible: Boolean, animate: Boolean = true) {
|
||||||
viewModel.showMenus(visible)
|
viewModel.showMenus(visible)
|
||||||
if (visible) {
|
if (visible) {
|
||||||
windowInsetsController.show(WindowInsetsCompat.Type.systemBars())
|
windowInsetsController.show(WindowInsetsCompat.Type.systemBars())
|
||||||
|
@ -796,7 +801,6 @@ class ReaderActivity : BaseActivity() {
|
||||||
* Called from the viewer whenever a [page] is marked as active. It updates the values of the
|
* Called from the viewer whenever a [page] is marked as active. It updates the values of the
|
||||||
* bottom menu and delegates the change to the presenter.
|
* bottom menu and delegates the change to the presenter.
|
||||||
*/
|
*/
|
||||||
@SuppressLint("SetTextI18n")
|
|
||||||
fun onPageSelected(page: ReaderPage) {
|
fun onPageSelected(page: ReaderPage) {
|
||||||
viewModel.onPageSelected(page)
|
viewModel.onPageSelected(page)
|
||||||
}
|
}
|
||||||
|
@ -814,7 +818,7 @@ class ReaderActivity : BaseActivity() {
|
||||||
* the viewer is reaching the beginning or end of a chapter or the transition page is active.
|
* the viewer is reaching the beginning or end of a chapter or the transition page is active.
|
||||||
*/
|
*/
|
||||||
fun requestPreloadChapter(chapter: ReaderChapter) {
|
fun requestPreloadChapter(chapter: ReaderChapter) {
|
||||||
lifecycleScope.launchIO { viewModel.preloadChapter(chapter) }
|
lifecycleScope.launchIO { viewModel.preload(chapter) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -901,7 +905,7 @@ class ReaderActivity : BaseActivity() {
|
||||||
/**
|
/**
|
||||||
* Updates viewer inset depending on fullscreen reader preferences.
|
* Updates viewer inset depending on fullscreen reader preferences.
|
||||||
*/
|
*/
|
||||||
fun updateViewerInset(fullscreen: Boolean) {
|
private fun updateViewerInset(fullscreen: Boolean) {
|
||||||
viewModel.state.value.viewer?.getView()?.applyInsetter {
|
viewModel.state.value.viewer?.getView()?.applyInsetter {
|
||||||
if (!fullscreen) {
|
if (!fullscreen) {
|
||||||
type(navigationBars = true, statusBars = true) {
|
type(navigationBars = true, statusBars = true) {
|
||||||
|
|
|
@ -57,7 +57,6 @@ import kotlinx.coroutines.flow.map
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
import kotlinx.coroutines.flow.receiveAsFlow
|
import kotlinx.coroutines.flow.receiveAsFlow
|
||||||
import kotlinx.coroutines.flow.update
|
import kotlinx.coroutines.flow.update
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import logcat.LogPriority
|
import logcat.LogPriority
|
||||||
import tachiyomi.core.util.lang.launchIO
|
import tachiyomi.core.util.lang.launchIO
|
||||||
|
@ -314,12 +313,15 @@ class ReaderViewModel(
|
||||||
* Called when the user changed to the given [chapter] when changing pages from the viewer.
|
* Called when the user changed to the given [chapter] when changing pages from the viewer.
|
||||||
* It's used only to set this chapter as active.
|
* It's used only to set this chapter as active.
|
||||||
*/
|
*/
|
||||||
private suspend fun loadNewChapter(chapter: ReaderChapter) {
|
private fun loadNewChapter(chapter: ReaderChapter) {
|
||||||
val loader = loader ?: return
|
val loader = loader ?: return
|
||||||
|
|
||||||
logcat { "Loading ${chapter.chapter.url}" }
|
viewModelScope.launchIO {
|
||||||
|
logcat { "Loading ${chapter.chapter.url}" }
|
||||||
|
|
||||||
|
flushReadTimer()
|
||||||
|
restartReadTimer()
|
||||||
|
|
||||||
withIOContext {
|
|
||||||
try {
|
try {
|
||||||
loadChapter(loader, chapter)
|
loadChapter(loader, chapter)
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
|
@ -358,7 +360,7 @@ class ReaderViewModel(
|
||||||
* Called when the viewers decide it's a good time to preload a [chapter] and improve the UX so
|
* Called when the viewers decide it's a good time to preload a [chapter] and improve the UX so
|
||||||
* that the user doesn't have to wait too long to continue reading.
|
* that the user doesn't have to wait too long to continue reading.
|
||||||
*/
|
*/
|
||||||
private suspend fun preload(chapter: ReaderChapter) {
|
suspend fun preload(chapter: ReaderChapter) {
|
||||||
if (chapter.state is ReaderChapter.State.Loaded || chapter.state == ReaderChapter.State.Loading) {
|
if (chapter.state is ReaderChapter.State.Loaded || chapter.state == ReaderChapter.State.Loading) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -397,9 +399,7 @@ class ReaderViewModel(
|
||||||
|
|
||||||
fun onViewerLoaded(viewer: Viewer?) {
|
fun onViewerLoaded(viewer: Viewer?) {
|
||||||
mutableState.update {
|
mutableState.update {
|
||||||
it.copy(
|
it.copy(viewer = viewer)
|
||||||
viewer = viewer,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -414,31 +414,19 @@ class ReaderViewModel(
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val currentChapters = state.value.viewerChapters ?: return
|
|
||||||
val pages = page.chapter.pages ?: return
|
|
||||||
val selectedChapter = page.chapter
|
val selectedChapter = page.chapter
|
||||||
|
val pages = selectedChapter.pages ?: return
|
||||||
|
|
||||||
// Save last page read and mark as read if needed
|
// Save last page read and mark as read if needed
|
||||||
saveReadingProgress()
|
viewModelScope.launchNonCancellable {
|
||||||
mutableState.update {
|
updateChapterProgress(page.index)
|
||||||
it.copy(
|
|
||||||
currentPage = page.index + 1,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
if (!incognitoMode) {
|
|
||||||
selectedChapter.chapter.last_page_read = page.index
|
|
||||||
if (selectedChapter.pages?.lastIndex == page.index) {
|
|
||||||
selectedChapter.chapter.read = true
|
|
||||||
updateTrackChapterRead(selectedChapter)
|
|
||||||
deleteChapterIfNeeded(selectedChapter)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selectedChapter != currentChapters.currChapter) {
|
if (selectedChapter != getCurrentChapter()) {
|
||||||
logcat { "Setting ${selectedChapter.chapter.url} as active" }
|
logcat { "Setting ${selectedChapter.chapter.url} as active" }
|
||||||
setReadStartTime()
|
loadNewChapter(selectedChapter)
|
||||||
viewModelScope.launch { loadNewChapter(selectedChapter) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val inDownloadRange = page.number.toDouble() / pages.size > 0.25
|
val inDownloadRange = page.number.toDouble() / pages.size > 0.25
|
||||||
if (inDownloadRange) {
|
if (inDownloadRange) {
|
||||||
downloadNextChapters()
|
downloadNextChapters()
|
||||||
|
@ -508,42 +496,54 @@ class ReaderViewModel(
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when reader chapter is changed in reader or when activity is paused.
|
* Saves the chapter progress (last read page and whether it's read)
|
||||||
|
* if incognito mode isn't on.
|
||||||
*/
|
*/
|
||||||
private fun saveReadingProgress() {
|
private suspend fun updateChapterProgress(pageIndex: Int) {
|
||||||
getCurrentChapter()?.let {
|
val readerChapter = getCurrentChapter() ?: return
|
||||||
viewModelScope.launchNonCancellable {
|
|
||||||
saveChapterProgress(it)
|
mutableState.update {
|
||||||
saveChapterHistory(it)
|
it.copy(currentPage = pageIndex + 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!incognitoMode) {
|
||||||
|
readerChapter.requestedPage = pageIndex
|
||||||
|
readerChapter.chapter.last_page_read = pageIndex
|
||||||
|
|
||||||
|
if (readerChapter.pages?.lastIndex == pageIndex) {
|
||||||
|
readerChapter.chapter.read = true
|
||||||
|
updateTrackChapterRead(readerChapter)
|
||||||
|
deleteChapterIfNeeded(readerChapter)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateChapter.await(
|
||||||
|
ChapterUpdate(
|
||||||
|
id = readerChapter.chapter.id!!,
|
||||||
|
read = readerChapter.chapter.read,
|
||||||
|
bookmark = readerChapter.chapter.bookmark,
|
||||||
|
lastPageRead = readerChapter.chapter.last_page_read.toLong(),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun restartReadTimer() {
|
||||||
|
chapterReadStartTime = Date().time
|
||||||
|
}
|
||||||
|
|
||||||
|
fun flushReadTimer() {
|
||||||
|
viewModelScope.launchNonCancellable {
|
||||||
|
updateHistory()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Saves this [readerChapter] progress (last read page and whether it's read).
|
* Saves the chapter last read history if incognito mode isn't on.
|
||||||
* if incognito mode isn't on.
|
|
||||||
*/
|
*/
|
||||||
private suspend fun saveChapterProgress(readerChapter: ReaderChapter) {
|
private suspend fun updateHistory() {
|
||||||
if (!incognitoMode) return
|
|
||||||
|
|
||||||
val chapter = readerChapter.chapter
|
|
||||||
readerChapter.requestedPage = chapter.last_page_read
|
|
||||||
updateChapter.await(
|
|
||||||
ChapterUpdate(
|
|
||||||
id = chapter.id!!,
|
|
||||||
read = chapter.read,
|
|
||||||
bookmark = chapter.bookmark,
|
|
||||||
lastPageRead = chapter.last_page_read.toLong(),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Saves this [readerChapter] last read history if incognito mode isn't on.
|
|
||||||
*/
|
|
||||||
private suspend fun saveChapterHistory(readerChapter: ReaderChapter) {
|
|
||||||
if (incognitoMode) return
|
if (incognitoMode) return
|
||||||
|
|
||||||
|
val readerChapter = getCurrentChapter() ?: return
|
||||||
val chapterId = readerChapter.chapter.id!!
|
val chapterId = readerChapter.chapter.id!!
|
||||||
val readAt = Date()
|
val readAt = Date()
|
||||||
val sessionReadDuration = chapterReadStartTime?.let { readAt.time - it } ?: 0
|
val sessionReadDuration = chapterReadStartTime?.let { readAt.time - it } ?: 0
|
||||||
|
@ -552,17 +552,6 @@ class ReaderViewModel(
|
||||||
chapterReadStartTime = null
|
chapterReadStartTime = null
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setReadStartTime() {
|
|
||||||
chapterReadStartTime = Date().time
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called from the activity to preload the given [chapter].
|
|
||||||
*/
|
|
||||||
suspend fun preloadChapter(chapter: ReaderChapter) {
|
|
||||||
preload(chapter)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called from the activity to load and set the next chapter as active.
|
* Called from the activity to load and set the next chapter as active.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -4,8 +4,8 @@ import eu.kanade.tachiyomi.source.model.UpdateStrategy
|
||||||
import tachiyomi.domain.entries.anime.model.Anime
|
import tachiyomi.domain.entries.anime.model.Anime
|
||||||
import tachiyomi.domain.library.anime.LibraryAnime
|
import tachiyomi.domain.library.anime.LibraryAnime
|
||||||
|
|
||||||
val animeMapper: (Long, Long, String, String?, String?, String?, List<String>?, String, Long, String?, Boolean, Long?, Long?, Boolean, Long, Long, Long, Long, UpdateStrategy, Long) -> Anime =
|
val animeMapper: (Long, Long, String, String?, String?, String?, List<String>?, String, Long, String?, Boolean, Long?, Long?, Boolean, Long, Long, Long, Long, UpdateStrategy, Long, Long, Long?) -> Anime =
|
||||||
{ id, source, url, artist, author, description, genre, title, status, thumbnailUrl, favorite, lastUpdate, nextUpdate, initialized, viewerFlags, episodeFlags, coverLastModified, dateAdded, updateStrategy, calculateInterval ->
|
{ id, source, url, artist, author, description, genre, title, status, thumbnailUrl, favorite, lastUpdate, nextUpdate, initialized, viewerFlags, episodeFlags, coverLastModified, dateAdded, updateStrategy, calculateInterval, lastModifiedAt, favoriteModifiedAt ->
|
||||||
Anime(
|
Anime(
|
||||||
id = id,
|
id = id,
|
||||||
source = source,
|
source = source,
|
||||||
|
@ -27,11 +27,13 @@ val animeMapper: (Long, Long, String, String?, String?, String?, List<String>?,
|
||||||
thumbnailUrl = thumbnailUrl,
|
thumbnailUrl = thumbnailUrl,
|
||||||
updateStrategy = updateStrategy,
|
updateStrategy = updateStrategy,
|
||||||
initialized = initialized,
|
initialized = initialized,
|
||||||
|
lastModifiedAt = lastModifiedAt,
|
||||||
|
favoriteModifiedAt = favoriteModifiedAt,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val libraryAnime: (Long, Long, String, String?, String?, String?, List<String>?, String, Long, String?, Boolean, Long?, Long?, Boolean, Long, Long, Long, Long, UpdateStrategy, Long, Long, Long, Long, Long, Long, Long, Long) -> LibraryAnime =
|
val libraryAnime: (Long, Long, String, String?, String?, String?, List<String>?, String, Long, String?, Boolean, Long?, Long?, Boolean, Long, Long, Long, Long, UpdateStrategy, Long, Long, Long?, Long, Long, Long, Long, Long, Long, Long) -> LibraryAnime =
|
||||||
{ id, source, url, artist, author, description, genre, title, status, thumbnailUrl, favorite, lastUpdate, nextUpdate, initialized, viewerFlags, episodeFlags, coverLastModified, dateAdded, updateStrategy, calculateInterval, totalCount, seenCount, latestUpload, episodeFetchedAt, lastSeen, bookmarkCount, category ->
|
{ id, source, url, artist, author, description, genre, title, status, thumbnailUrl, favorite, lastUpdate, nextUpdate, initialized, viewerFlags, episodeFlags, coverLastModified, dateAdded, updateStrategy, calculateInterval, lastModifiedAt, favoriteModifiedAt, totalCount, seenCount, latestUpload, episodeFetchedAt, lastSeen, bookmarkCount, category ->
|
||||||
LibraryAnime(
|
LibraryAnime(
|
||||||
anime = animeMapper(
|
anime = animeMapper(
|
||||||
id,
|
id,
|
||||||
|
@ -54,6 +56,8 @@ val libraryAnime: (Long, Long, String, String?, String?, String?, List<String>?,
|
||||||
dateAdded,
|
dateAdded,
|
||||||
updateStrategy,
|
updateStrategy,
|
||||||
calculateInterval,
|
calculateInterval,
|
||||||
|
lastModifiedAt,
|
||||||
|
favoriteModifiedAt,
|
||||||
),
|
),
|
||||||
category = category,
|
category = category,
|
||||||
totalEpisodes = totalCount,
|
totalEpisodes = totalCount,
|
||||||
|
|
|
@ -4,8 +4,8 @@ import eu.kanade.tachiyomi.source.model.UpdateStrategy
|
||||||
import tachiyomi.domain.entries.manga.model.Manga
|
import tachiyomi.domain.entries.manga.model.Manga
|
||||||
import tachiyomi.domain.library.manga.LibraryManga
|
import tachiyomi.domain.library.manga.LibraryManga
|
||||||
|
|
||||||
val mangaMapper: (Long, Long, String, String?, String?, String?, List<String>?, String, Long, String?, Boolean, Long?, Long?, Boolean, Long, Long, Long, Long, UpdateStrategy, Long) -> Manga =
|
val mangaMapper: (Long, Long, String, String?, String?, String?, List<String>?, String, Long, String?, Boolean, Long?, Long?, Boolean, Long, Long, Long, Long, UpdateStrategy, Long, Long, Long?) -> Manga =
|
||||||
{ id, source, url, artist, author, description, genre, title, status, thumbnailUrl, favorite, lastUpdate, nextUpdate, initialized, viewerFlags, chapterFlags, coverLastModified, dateAdded, updateStrategy, calculateInterval ->
|
{ id, source, url, artist, author, description, genre, title, status, thumbnailUrl, favorite, lastUpdate, nextUpdate, initialized, viewerFlags, chapterFlags, coverLastModified, dateAdded, updateStrategy, calculateInterval, lastModifiedAt, favoriteModifiedAt ->
|
||||||
Manga(
|
Manga(
|
||||||
id = id,
|
id = id,
|
||||||
source = source,
|
source = source,
|
||||||
|
@ -27,11 +27,13 @@ val mangaMapper: (Long, Long, String, String?, String?, String?, List<String>?,
|
||||||
thumbnailUrl = thumbnailUrl,
|
thumbnailUrl = thumbnailUrl,
|
||||||
updateStrategy = updateStrategy,
|
updateStrategy = updateStrategy,
|
||||||
initialized = initialized,
|
initialized = initialized,
|
||||||
|
lastModifiedAt = lastModifiedAt,
|
||||||
|
favoriteModifiedAt = favoriteModifiedAt,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val libraryManga: (Long, Long, String, String?, String?, String?, List<String>?, String, Long, String?, Boolean, Long?, Long?, Boolean, Long, Long, Long, Long, UpdateStrategy, Long, Long, Long, Long, Long, Long, Long, Long) -> LibraryManga =
|
val libraryManga: (Long, Long, String, String?, String?, String?, List<String>?, String, Long, String?, Boolean, Long?, Long?, Boolean, Long, Long, Long, Long, UpdateStrategy, Long, Long, Long?, Long, Long, Long, Long, Long, Long, Long) -> LibraryManga =
|
||||||
{ id, source, url, artist, author, description, genre, title, status, thumbnailUrl, favorite, lastUpdate, nextUpdate, initialized, viewerFlags, chapterFlags, coverLastModified, dateAdded, updateStrategy, calculateInterval, totalCount, readCount, latestUpload, chapterFetchedAt, lastRead, bookmarkCount, category ->
|
{ id, source, url, artist, author, description, genre, title, status, thumbnailUrl, favorite, lastUpdate, nextUpdate, initialized, viewerFlags, chapterFlags, coverLastModified, dateAdded, updateStrategy, calculateInterval, lastModifiedAt, favoriteModifiedAt, totalCount, readCount, latestUpload, chapterFetchedAt, lastRead, bookmarkCount, category ->
|
||||||
LibraryManga(
|
LibraryManga(
|
||||||
manga = mangaMapper(
|
manga = mangaMapper(
|
||||||
id,
|
id,
|
||||||
|
@ -54,6 +56,8 @@ val libraryManga: (Long, Long, String, String?, String?, String?, List<String>?,
|
||||||
dateAdded,
|
dateAdded,
|
||||||
updateStrategy,
|
updateStrategy,
|
||||||
calculateInterval,
|
calculateInterval,
|
||||||
|
lastModifiedAt,
|
||||||
|
favoriteModifiedAt,
|
||||||
),
|
),
|
||||||
category = category,
|
category = category,
|
||||||
totalChapters = totalCount,
|
totalChapters = totalCount,
|
||||||
|
|
|
@ -2,8 +2,8 @@ package tachiyomi.data.items.chapter
|
||||||
|
|
||||||
import tachiyomi.domain.items.chapter.model.Chapter
|
import tachiyomi.domain.items.chapter.model.Chapter
|
||||||
|
|
||||||
val chapterMapper: (Long, Long, String, String, String?, Boolean, Boolean, Long, Float, Long, Long, Long) -> Chapter =
|
val chapterMapper: (Long, Long, String, String, String?, Boolean, Boolean, Long, Float, Long, Long, Long, Long) -> Chapter =
|
||||||
{ id, mangaId, url, name, scanlator, read, bookmark, lastPageRead, chapterNumber, sourceOrder, dateFetch, dateUpload ->
|
{ id, mangaId, url, name, scanlator, read, bookmark, lastPageRead, chapterNumber, sourceOrder, dateFetch, dateUpload, lastModifiedAt ->
|
||||||
Chapter(
|
Chapter(
|
||||||
id = id,
|
id = id,
|
||||||
mangaId = mangaId,
|
mangaId = mangaId,
|
||||||
|
@ -17,5 +17,6 @@ val chapterMapper: (Long, Long, String, String, String?, Boolean, Boolean, Long,
|
||||||
dateUpload = dateUpload,
|
dateUpload = dateUpload,
|
||||||
chapterNumber = chapterNumber,
|
chapterNumber = chapterNumber,
|
||||||
scanlator = scanlator,
|
scanlator = scanlator,
|
||||||
|
lastModifiedAt = lastModifiedAt,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,8 @@ package tachiyomi.data.items.episode
|
||||||
|
|
||||||
import tachiyomi.domain.items.episode.model.Episode
|
import tachiyomi.domain.items.episode.model.Episode
|
||||||
|
|
||||||
val episodeMapper: (Long, Long, String, String, String?, Boolean, Boolean, Long, Long, Float, Long, Long, Long) -> Episode =
|
val episodeMapper: (Long, Long, String, String, String?, Boolean, Boolean, Long, Long, Float, Long, Long, Long, Long) -> Episode =
|
||||||
{ id, animeId, url, name, scanlator, seen, bookmark, lastSecondSeen, totalSeconds, episodeNumber, sourceOrder, dateFetch, dateUpload ->
|
{ id, animeId, url, name, scanlator, seen, bookmark, lastSecondSeen, totalSeconds, episodeNumber, sourceOrder, dateFetch, dateUpload, lastModifiedAt ->
|
||||||
Episode(
|
Episode(
|
||||||
id = id,
|
id = id,
|
||||||
animeId = animeId,
|
animeId = animeId,
|
||||||
|
@ -18,5 +18,6 @@ val episodeMapper: (Long, Long, String, String, String?, Boolean, Boolean, Long,
|
||||||
dateUpload = dateUpload,
|
dateUpload = dateUpload,
|
||||||
episodeNumber = episodeNumber,
|
episodeNumber = episodeNumber,
|
||||||
scanlator = scanlator,
|
scanlator = scanlator,
|
||||||
|
lastModifiedAt = lastModifiedAt,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ CREATE TABLE chapters(
|
||||||
source_order INTEGER NOT NULL,
|
source_order INTEGER NOT NULL,
|
||||||
date_fetch INTEGER AS Long NOT NULL,
|
date_fetch INTEGER AS Long NOT NULL,
|
||||||
date_upload INTEGER AS Long NOT NULL,
|
date_upload INTEGER AS Long NOT NULL,
|
||||||
|
last_modified_at INTEGER AS Long NOT NULL,
|
||||||
FOREIGN KEY(manga_id) REFERENCES mangas (_id)
|
FOREIGN KEY(manga_id) REFERENCES mangas (_id)
|
||||||
ON DELETE CASCADE
|
ON DELETE CASCADE
|
||||||
);
|
);
|
||||||
|
@ -18,6 +19,15 @@ CREATE TABLE chapters(
|
||||||
CREATE INDEX chapters_manga_id_index ON chapters(manga_id);
|
CREATE INDEX chapters_manga_id_index ON chapters(manga_id);
|
||||||
CREATE INDEX chapters_unread_by_manga_index ON chapters(manga_id, read) WHERE read = 0;
|
CREATE INDEX chapters_unread_by_manga_index ON chapters(manga_id, read) WHERE read = 0;
|
||||||
|
|
||||||
|
CREATE TRIGGER update_last_modified_at_chapters
|
||||||
|
AFTER UPDATE ON chapters
|
||||||
|
FOR EACH ROW
|
||||||
|
BEGIN
|
||||||
|
UPDATE chapters
|
||||||
|
SET last_modified_at = strftime('%s', 'now')
|
||||||
|
WHERE _id = new._id;
|
||||||
|
END;
|
||||||
|
|
||||||
getChapterById:
|
getChapterById:
|
||||||
SELECT *
|
SELECT *
|
||||||
FROM chapters
|
FROM chapters
|
||||||
|
@ -50,8 +60,8 @@ DELETE FROM chapters
|
||||||
WHERE _id IN :chapterIds;
|
WHERE _id IN :chapterIds;
|
||||||
|
|
||||||
insert:
|
insert:
|
||||||
INSERT INTO chapters(manga_id,url,name,scanlator,read,bookmark,last_page_read,chapter_number,source_order,date_fetch,date_upload)
|
INSERT INTO chapters(manga_id, url, name, scanlator, read, bookmark, last_page_read, chapter_number, source_order,date_fetch, date_upload, last_modified_at)
|
||||||
VALUES (:mangaId,:url,:name,:scanlator,:read,:bookmark,:lastPageRead,:chapterNumber,:sourceOrder,:dateFetch,:dateUpload);
|
VALUES (:mangaId, :url, :name, :scanlator, :read, :bookmark, :lastPageRead, :chapterNumber, :sourceOrder, :dateFetch, :dateUpload, strftime('%s', 'now'));
|
||||||
|
|
||||||
update:
|
update:
|
||||||
UPDATE chapters
|
UPDATE chapters
|
||||||
|
|
|
@ -22,12 +22,31 @@ CREATE TABLE mangas(
|
||||||
cover_last_modified INTEGER AS Long NOT NULL,
|
cover_last_modified INTEGER AS Long NOT NULL,
|
||||||
date_added INTEGER AS Long NOT NULL,
|
date_added INTEGER AS Long NOT NULL,
|
||||||
update_strategy INTEGER AS UpdateStrategy NOT NULL DEFAULT 0,
|
update_strategy INTEGER AS UpdateStrategy NOT NULL DEFAULT 0,
|
||||||
calculate_interval INTEGER DEFAULT 0 NOT NULL
|
calculate_interval INTEGER DEFAULT 0 NOT NULL,
|
||||||
|
last_modified_at INTEGER AS Long NOT NULL,
|
||||||
|
favorite_modified_at INTEGER AS Long
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE INDEX library_favorite_index ON mangas(favorite) WHERE favorite = 1;
|
CREATE INDEX library_favorite_index ON mangas(favorite) WHERE favorite = 1;
|
||||||
CREATE INDEX mangas_url_index ON mangas(url);
|
CREATE INDEX mangas_url_index ON mangas(url);
|
||||||
|
|
||||||
|
CREATE TRIGGER update_favorite_modified_at_mangas
|
||||||
|
AFTER UPDATE OF favorite ON mangas
|
||||||
|
BEGIN
|
||||||
|
UPDATE mangas
|
||||||
|
SET favorite_modified_at = strftime('%s', 'now')
|
||||||
|
WHERE _id = new._id;
|
||||||
|
END;
|
||||||
|
|
||||||
|
CREATE TRIGGER update_last_modified_at_mangas
|
||||||
|
AFTER UPDATE ON mangas
|
||||||
|
FOR EACH ROW
|
||||||
|
BEGIN
|
||||||
|
UPDATE mangas
|
||||||
|
SET last_modified_at = strftime('%s', 'now')
|
||||||
|
WHERE _id = new._id;
|
||||||
|
END;
|
||||||
|
|
||||||
getMangaById:
|
getMangaById:
|
||||||
SELECT *
|
SELECT *
|
||||||
FROM mangas
|
FROM mangas
|
||||||
|
@ -45,6 +64,15 @@ SELECT *
|
||||||
FROM mangas
|
FROM mangas
|
||||||
WHERE favorite = 1;
|
WHERE favorite = 1;
|
||||||
|
|
||||||
|
getAllManga:
|
||||||
|
SELECT *
|
||||||
|
FROM mangas;
|
||||||
|
|
||||||
|
getMangasWithFavoriteTimestamp:
|
||||||
|
SELECT *
|
||||||
|
FROM mangas
|
||||||
|
WHERE favorite_modified_at IS NOT NULL;
|
||||||
|
|
||||||
getSourceIdWithFavoriteCount:
|
getSourceIdWithFavoriteCount:
|
||||||
SELECT
|
SELECT
|
||||||
source,
|
source,
|
||||||
|
@ -81,8 +109,8 @@ DELETE FROM mangas
|
||||||
WHERE favorite = 0 AND source IN :sourceIds;
|
WHERE favorite = 0 AND source IN :sourceIds;
|
||||||
|
|
||||||
insert:
|
insert:
|
||||||
INSERT INTO mangas(source,url,artist,author,description,genre,title,status,thumbnail_url,favorite,last_update,next_update,initialized,viewer,chapter_flags,cover_last_modified,date_added,update_strategy,calculate_interval)
|
INSERT INTO mangas(source, url, artist, author, description, genre, title, status, thumbnail_url, favorite, last_update, next_update, initialized, viewer, chapter_flags, cover_last_modified, date_added, update_strategy, calculate_interval, last_modified_at)
|
||||||
VALUES (:source,:url,:artist,:author,:description,:genre,:title,:status,:thumbnailUrl,:favorite,:lastUpdate,:nextUpdate,:initialized,:viewerFlags,:chapterFlags,:coverLastModified,:dateAdded,:updateStrategy,:calculateInterval);
|
VALUES (:source, :url, :artist, :author, :description, :genre, :title, :status, :thumbnailUrl, :favorite, :lastUpdate, :nextUpdate, :initialized, :viewerFlags, :chapterFlags, :coverLastModified, :dateAdded, :updateStrategy, :calculateInterval, strftime('%s', 'now'));
|
||||||
|
|
||||||
update:
|
update:
|
||||||
UPDATE mangas SET
|
UPDATE mangas SET
|
||||||
|
|
|
@ -2,15 +2,25 @@ CREATE TABLE mangas_categories(
|
||||||
_id INTEGER NOT NULL PRIMARY KEY,
|
_id INTEGER NOT NULL PRIMARY KEY,
|
||||||
manga_id INTEGER NOT NULL,
|
manga_id INTEGER NOT NULL,
|
||||||
category_id INTEGER NOT NULL,
|
category_id INTEGER NOT NULL,
|
||||||
|
last_modified_at INTEGER AS Long NOT NULL,
|
||||||
FOREIGN KEY(category_id) REFERENCES categories (_id)
|
FOREIGN KEY(category_id) REFERENCES categories (_id)
|
||||||
ON DELETE CASCADE,
|
ON DELETE CASCADE,
|
||||||
FOREIGN KEY(manga_id) REFERENCES mangas (_id)
|
FOREIGN KEY(manga_id) REFERENCES mangas (_id)
|
||||||
ON DELETE CASCADE
|
ON DELETE CASCADE
|
||||||
);
|
);
|
||||||
|
|
||||||
|
CREATE TRIGGER update_last_modified_at_mangas_categories
|
||||||
|
AFTER UPDATE ON mangas_categories
|
||||||
|
FOR EACH ROW
|
||||||
|
BEGIN
|
||||||
|
UPDATE mangas_categories
|
||||||
|
SET last_modified_at = strftime('%s', 'now')
|
||||||
|
WHERE _id = new._id;
|
||||||
|
END;
|
||||||
|
|
||||||
insert:
|
insert:
|
||||||
INSERT INTO mangas_categories(manga_id, category_id)
|
INSERT INTO mangas_categories(manga_id, category_id, last_modified_at)
|
||||||
VALUES (:mangaId, :categoryId);
|
VALUES (:mangaId, :categoryId, strftime('%s', 'now'));
|
||||||
|
|
||||||
deleteMangaCategoryByMangaId:
|
deleteMangaCategoryByMangaId:
|
||||||
DELETE FROM mangas_categories
|
DELETE FROM mangas_categories
|
||||||
|
|
49
data/src/main/sqldelight/migrations/26.sqm
Normal file
49
data/src/main/sqldelight/migrations/26.sqm
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
ALTER TABLE mangas ADD COLUMN last_modified_at INTEGER AS Long NOT NULL DEFAULT 0;
|
||||||
|
ALTER TABLE mangas ADD COLUMN favorite_modified_at INTEGER AS Long;
|
||||||
|
ALTER TABLE mangas_categories ADD COLUMN last_modified_at INTEGER AS Long NOT NULL DEFAULT 0;
|
||||||
|
ALTER TABLE chapters ADD COLUMN last_modified_at INTEGER AS Long NOT NULL DEFAULT 0;
|
||||||
|
|
||||||
|
UPDATE mangas SET last_modified_at = strftime('%s', 'now');
|
||||||
|
UPDATE mangas SET favorite_modified_at = strftime('%s', 'now') WHERE favorite = 1;
|
||||||
|
UPDATE mangas_categories SET last_modified_at = strftime('%s', 'now');
|
||||||
|
UPDATE chapters SET last_modified_at = strftime('%s', 'now');
|
||||||
|
|
||||||
|
-- Create triggers
|
||||||
|
DROP TRIGGER IF EXISTS update_last_modified_at_mangas;
|
||||||
|
CREATE TRIGGER update_last_modified_at_mangas
|
||||||
|
AFTER UPDATE ON mangas
|
||||||
|
FOR EACH ROW
|
||||||
|
BEGIN
|
||||||
|
UPDATE mangas
|
||||||
|
SET last_modified_at = strftime('%s', 'now')
|
||||||
|
WHERE _id = new._id;
|
||||||
|
END;
|
||||||
|
|
||||||
|
DROP TRIGGER IF EXISTS update_favorite_modified_at_mangas;
|
||||||
|
CREATE TRIGGER update_last_favorited_at_mangas
|
||||||
|
AFTER UPDATE OF favorite ON mangas
|
||||||
|
BEGIN
|
||||||
|
UPDATE mangas
|
||||||
|
SET favorite_modified_at = strftime('%s', 'now')
|
||||||
|
WHERE _id = new._id;
|
||||||
|
END;
|
||||||
|
|
||||||
|
DROP TRIGGER IF EXISTS update_last_modified_at_chapters;
|
||||||
|
CREATE TRIGGER update_last_modified_at_chapters
|
||||||
|
AFTER UPDATE ON chapters
|
||||||
|
FOR EACH ROW
|
||||||
|
BEGIN
|
||||||
|
UPDATE chapters
|
||||||
|
SET last_modified_at = strftime('%s', 'now')
|
||||||
|
WHERE _id = new._id;
|
||||||
|
END;
|
||||||
|
|
||||||
|
DROP TRIGGER IF EXISTS update_last_modified_at_mangas_categories;
|
||||||
|
CREATE TRIGGER update_last_modified_at_mangas_categories
|
||||||
|
AFTER UPDATE ON mangas_categories
|
||||||
|
FOR EACH ROW
|
||||||
|
BEGIN
|
||||||
|
UPDATE mangas_categories
|
||||||
|
SET last_modified_at = strftime('%s', 'now')
|
||||||
|
WHERE _id = new._id;
|
||||||
|
END;
|
|
@ -22,12 +22,31 @@ CREATE TABLE animes(
|
||||||
cover_last_modified INTEGER AS Long NOT NULL,
|
cover_last_modified INTEGER AS Long NOT NULL,
|
||||||
date_added INTEGER AS Long NOT NULL,
|
date_added INTEGER AS Long NOT NULL,
|
||||||
update_strategy INTEGER AS UpdateStrategy NOT NULL DEFAULT 0,
|
update_strategy INTEGER AS UpdateStrategy NOT NULL DEFAULT 0,
|
||||||
calculate_interval INTEGER DEFAULT 0 NOT NULL
|
calculate_interval INTEGER DEFAULT 0 NOT NULL,
|
||||||
|
last_modified_at INTEGER AS Long NOT NULL,
|
||||||
|
favorite_modified_at INTEGER AS Long
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE INDEX animelib_favorite_index ON animes(favorite) WHERE favorite = 1;
|
CREATE INDEX animelib_favorite_index ON animes(favorite) WHERE favorite = 1;
|
||||||
CREATE INDEX animes_url_index ON animes(url);
|
CREATE INDEX animes_url_index ON animes(url);
|
||||||
|
|
||||||
|
CREATE TRIGGER update_favorite_modified_at_animes
|
||||||
|
AFTER UPDATE OF favorite ON animes
|
||||||
|
BEGIN
|
||||||
|
UPDATE animes
|
||||||
|
SET favorite_modified_at = strftime('%s', 'now')
|
||||||
|
WHERE _id = new._id;
|
||||||
|
END;
|
||||||
|
|
||||||
|
CREATE TRIGGER update_last_modified_at_animes
|
||||||
|
AFTER UPDATE ON animes
|
||||||
|
FOR EACH ROW
|
||||||
|
BEGIN
|
||||||
|
UPDATE animes
|
||||||
|
SET last_modified_at = strftime('%s', 'now')
|
||||||
|
WHERE _id = new._id;
|
||||||
|
END;
|
||||||
|
|
||||||
getAnimeById:
|
getAnimeById:
|
||||||
SELECT *
|
SELECT *
|
||||||
FROM animes
|
FROM animes
|
||||||
|
@ -45,6 +64,15 @@ SELECT *
|
||||||
FROM animes
|
FROM animes
|
||||||
WHERE favorite = 1;
|
WHERE favorite = 1;
|
||||||
|
|
||||||
|
getAllAnime:
|
||||||
|
SELECT *
|
||||||
|
FROM animes;
|
||||||
|
|
||||||
|
getAnimesWithFavoriteTimestamp:
|
||||||
|
SELECT *
|
||||||
|
FROM animes
|
||||||
|
WHERE favorite_modified_at IS NOT NULL;
|
||||||
|
|
||||||
getAnimeSourceIdWithFavoriteCount:
|
getAnimeSourceIdWithFavoriteCount:
|
||||||
SELECT
|
SELECT
|
||||||
source,
|
source,
|
||||||
|
@ -81,8 +109,8 @@ DELETE FROM animes
|
||||||
WHERE favorite = 0 AND source IN :sourceIds;
|
WHERE favorite = 0 AND source IN :sourceIds;
|
||||||
|
|
||||||
insert:
|
insert:
|
||||||
INSERT INTO animes(source,url,artist,author,description,genre,title,status,thumbnail_url,favorite,last_update,next_update,initialized,viewer,episode_flags,cover_last_modified,date_added,update_strategy,calculate_interval)
|
INSERT INTO animes(source, url, artist, author, description, genre, title, status, thumbnail_url, favorite, last_update, next_update, initialized, viewer, episode_flags, cover_last_modified, date_added, update_strategy, calculate_interval, last_modified_at)
|
||||||
VALUES (:source,:url,:artist,:author,:description,:genre,:title,:status,:thumbnailUrl,:favorite,:lastUpdate,:nextUpdate,:initialized,:viewerFlags,:episodeFlags,:coverLastModified,:dateAdded,:updateStrategy,:calculateInterval);
|
VALUES (:source, :url, :artist, :author, :description, :genre, :title, :status, :thumbnailUrl, :favorite, :lastUpdate, :nextUpdate, :initialized, :viewerFlags, :episodeFlags, :coverLastModified, :dateAdded, :updateStrategy, :calculateInterval, strftime('%s', 'now'));
|
||||||
|
|
||||||
update:
|
update:
|
||||||
UPDATE animes SET
|
UPDATE animes SET
|
||||||
|
|
|
@ -2,15 +2,25 @@ CREATE TABLE animes_categories(
|
||||||
_id INTEGER NOT NULL PRIMARY KEY,
|
_id INTEGER NOT NULL PRIMARY KEY,
|
||||||
anime_id INTEGER NOT NULL,
|
anime_id INTEGER NOT NULL,
|
||||||
category_id INTEGER NOT NULL,
|
category_id INTEGER NOT NULL,
|
||||||
|
last_modified_at INTEGER AS Long NOT NULL,
|
||||||
FOREIGN KEY(category_id) REFERENCES categories (_id)
|
FOREIGN KEY(category_id) REFERENCES categories (_id)
|
||||||
ON DELETE CASCADE,
|
ON DELETE CASCADE,
|
||||||
FOREIGN KEY(anime_id) REFERENCES animes (_id)
|
FOREIGN KEY(anime_id) REFERENCES animes (_id)
|
||||||
ON DELETE CASCADE
|
ON DELETE CASCADE
|
||||||
);
|
);
|
||||||
|
|
||||||
|
CREATE TRIGGER update_last_modified_at_animes_categories
|
||||||
|
AFTER UPDATE ON animes_categories
|
||||||
|
FOR EACH ROW
|
||||||
|
BEGIN
|
||||||
|
UPDATE animes_categories
|
||||||
|
SET last_modified_at = strftime('%s', 'now')
|
||||||
|
WHERE _id = new._id;
|
||||||
|
END;
|
||||||
|
|
||||||
insert:
|
insert:
|
||||||
INSERT INTO animes_categories(anime_id, category_id)
|
INSERT INTO animes_categories(anime_id, category_id, last_modified_at)
|
||||||
VALUES (:animeId, :categoryId);
|
VALUES (:animeId, :categoryId, strftime('%s', 'now'));
|
||||||
|
|
||||||
deleteAnimeCategoryByAnimeId:
|
deleteAnimeCategoryByAnimeId:
|
||||||
DELETE FROM animes_categories
|
DELETE FROM animes_categories
|
||||||
|
|
|
@ -12,6 +12,7 @@ CREATE TABLE episodes(
|
||||||
source_order INTEGER NOT NULL,
|
source_order INTEGER NOT NULL,
|
||||||
date_fetch INTEGER AS Long NOT NULL,
|
date_fetch INTEGER AS Long NOT NULL,
|
||||||
date_upload INTEGER AS Long NOT NULL,
|
date_upload INTEGER AS Long NOT NULL,
|
||||||
|
last_modified_at INTEGER AS Long NOT NULL,
|
||||||
FOREIGN KEY(anime_id) REFERENCES animes (_id)
|
FOREIGN KEY(anime_id) REFERENCES animes (_id)
|
||||||
ON DELETE CASCADE
|
ON DELETE CASCADE
|
||||||
);
|
);
|
||||||
|
@ -19,6 +20,15 @@ CREATE TABLE episodes(
|
||||||
CREATE INDEX episodes_anime_id_index ON episodes(anime_id);
|
CREATE INDEX episodes_anime_id_index ON episodes(anime_id);
|
||||||
CREATE INDEX episodes_unseen_by_anime_index ON episodes(anime_id, seen) WHERE seen = 0;
|
CREATE INDEX episodes_unseen_by_anime_index ON episodes(anime_id, seen) WHERE seen = 0;
|
||||||
|
|
||||||
|
CREATE TRIGGER update_last_modified_at_episodes
|
||||||
|
AFTER UPDATE ON episodes
|
||||||
|
FOR EACH ROW
|
||||||
|
BEGIN
|
||||||
|
UPDATE episodes
|
||||||
|
SET last_modified_at = strftime('%s', 'now')
|
||||||
|
WHERE _id = new._id;
|
||||||
|
END;
|
||||||
|
|
||||||
getEpisodeById:
|
getEpisodeById:
|
||||||
SELECT *
|
SELECT *
|
||||||
FROM episodes
|
FROM episodes
|
||||||
|
@ -52,8 +62,8 @@ DELETE FROM episodes
|
||||||
WHERE _id IN :episodeIds;
|
WHERE _id IN :episodeIds;
|
||||||
|
|
||||||
insert:
|
insert:
|
||||||
INSERT INTO episodes(anime_id,url,name,scanlator,seen,bookmark,last_second_seen,total_seconds,episode_number,source_order,date_fetch,date_upload)
|
INSERT INTO episodes(anime_id, url, name, scanlator, seen, bookmark, last_second_seen, total_seconds, episode_number, source_order, date_fetch, date_upload, last_modified_at)
|
||||||
VALUES (:animeId,:url,:name,:scanlator,:seen,:bookmark,:lastSecondSeen,:totalSeconds,:episodeNumber,:sourceOrder,:dateFetch,:dateUpload);
|
VALUES (:animeId, :url, :name, :scanlator, :seen, :bookmark, :lastSecondSeen, :totalSeconds, :episodeNumber, :sourceOrder, :dateFetch, :dateUpload, strftime('%s', 'now'));
|
||||||
|
|
||||||
update:
|
update:
|
||||||
UPDATE episodes
|
UPDATE episodes
|
||||||
|
|
49
data/src/main/sqldelightanime/migrations/126.sqm
Normal file
49
data/src/main/sqldelightanime/migrations/126.sqm
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
ALTER TABLE animes ADD COLUMN last_modified_at INTEGER AS Long NOT NULL DEFAULT 0;
|
||||||
|
ALTER TABLE animes ADD COLUMN favorite_modified_at INTEGER AS Long;
|
||||||
|
ALTER TABLE animes_categories ADD COLUMN last_modified_at INTEGER AS Long NOT NULL DEFAULT 0;
|
||||||
|
ALTER TABLE episodes ADD COLUMN last_modified_at INTEGER AS Long NOT NULL DEFAULT 0;
|
||||||
|
|
||||||
|
UPDATE animes SET last_modified_at = strftime('%s', 'now');
|
||||||
|
UPDATE animes SET favorite_modified_at = strftime('%s', 'now') WHERE favorite = 1;
|
||||||
|
UPDATE animes_categories SET last_modified_at = strftime('%s', 'now');
|
||||||
|
UPDATE episodes SET last_modified_at = strftime('%s', 'now');
|
||||||
|
|
||||||
|
-- Create triggers
|
||||||
|
DROP TRIGGER IF EXISTS update_last_modified_at_mangas;
|
||||||
|
CREATE TRIGGER update_last_modified_at_mangas
|
||||||
|
AFTER UPDATE ON animes
|
||||||
|
FOR EACH ROW
|
||||||
|
BEGIN
|
||||||
|
UPDATE animes
|
||||||
|
SET last_modified_at = strftime('%s', 'now')
|
||||||
|
WHERE _id = new._id;
|
||||||
|
END;
|
||||||
|
|
||||||
|
DROP TRIGGER IF EXISTS update_favorite_modified_at_mangas;
|
||||||
|
CREATE TRIGGER update_last_favorited_at_mangas
|
||||||
|
AFTER UPDATE OF favorite ON animes
|
||||||
|
BEGIN
|
||||||
|
UPDATE animes
|
||||||
|
SET favorite_modified_at = strftime('%s', 'now')
|
||||||
|
WHERE _id = new._id;
|
||||||
|
END;
|
||||||
|
|
||||||
|
DROP TRIGGER IF EXISTS update_last_modified_at_chapters;
|
||||||
|
CREATE TRIGGER update_last_modified_at_chapters
|
||||||
|
AFTER UPDATE ON episodes
|
||||||
|
FOR EACH ROW
|
||||||
|
BEGIN
|
||||||
|
UPDATE episodes
|
||||||
|
SET last_modified_at = strftime('%s', 'now')
|
||||||
|
WHERE _id = new._id;
|
||||||
|
END;
|
||||||
|
|
||||||
|
DROP TRIGGER IF EXISTS update_last_modified_at_mangas_categories;
|
||||||
|
CREATE TRIGGER update_last_modified_at_mangas_categories
|
||||||
|
AFTER UPDATE ON animes_categories
|
||||||
|
FOR EACH ROW
|
||||||
|
BEGIN
|
||||||
|
UPDATE animes_categories
|
||||||
|
SET last_modified_at = strftime('%s', 'now')
|
||||||
|
WHERE _id = new._id;
|
||||||
|
END;
|
|
@ -26,6 +26,8 @@ data class Anime(
|
||||||
val thumbnailUrl: String?,
|
val thumbnailUrl: String?,
|
||||||
val updateStrategy: UpdateStrategy,
|
val updateStrategy: UpdateStrategy,
|
||||||
val initialized: Boolean,
|
val initialized: Boolean,
|
||||||
|
val lastModifiedAt: Long,
|
||||||
|
val favoriteModifiedAt: Long?,
|
||||||
) : Serializable {
|
) : Serializable {
|
||||||
|
|
||||||
val sorting: Long
|
val sorting: Long
|
||||||
|
@ -129,6 +131,8 @@ data class Anime(
|
||||||
thumbnailUrl = null,
|
thumbnailUrl = null,
|
||||||
updateStrategy = UpdateStrategy.ALWAYS_UPDATE,
|
updateStrategy = UpdateStrategy.ALWAYS_UPDATE,
|
||||||
initialized = false,
|
initialized = false,
|
||||||
|
lastModifiedAt = 0L,
|
||||||
|
favoriteModifiedAt = null,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,8 @@ data class Manga(
|
||||||
val thumbnailUrl: String?,
|
val thumbnailUrl: String?,
|
||||||
val updateStrategy: UpdateStrategy,
|
val updateStrategy: UpdateStrategy,
|
||||||
val initialized: Boolean,
|
val initialized: Boolean,
|
||||||
|
val lastModifiedAt: Long,
|
||||||
|
val favoriteModifiedAt: Long?,
|
||||||
) : Serializable {
|
) : Serializable {
|
||||||
|
|
||||||
val sorting: Long
|
val sorting: Long
|
||||||
|
@ -110,6 +112,8 @@ data class Manga(
|
||||||
thumbnailUrl = null,
|
thumbnailUrl = null,
|
||||||
updateStrategy = UpdateStrategy.ALWAYS_UPDATE,
|
updateStrategy = UpdateStrategy.ALWAYS_UPDATE,
|
||||||
initialized = false,
|
initialized = false,
|
||||||
|
lastModifiedAt = 0L,
|
||||||
|
favoriteModifiedAt = null,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ data class Chapter(
|
||||||
val dateUpload: Long,
|
val dateUpload: Long,
|
||||||
val chapterNumber: Float,
|
val chapterNumber: Float,
|
||||||
val scanlator: String?,
|
val scanlator: String?,
|
||||||
|
val lastModifiedAt: Long,
|
||||||
) {
|
) {
|
||||||
val isRecognizedNumber: Boolean
|
val isRecognizedNumber: Boolean
|
||||||
get() = chapterNumber >= 0f
|
get() = chapterNumber >= 0f
|
||||||
|
@ -31,6 +32,7 @@ data class Chapter(
|
||||||
dateUpload = -1,
|
dateUpload = -1,
|
||||||
chapterNumber = -1f,
|
chapterNumber = -1f,
|
||||||
scanlator = null,
|
scanlator = null,
|
||||||
|
lastModifiedAt = 0,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ data class Episode(
|
||||||
val dateUpload: Long,
|
val dateUpload: Long,
|
||||||
val episodeNumber: Float,
|
val episodeNumber: Float,
|
||||||
val scanlator: String?,
|
val scanlator: String?,
|
||||||
|
val lastModifiedAt: Long,
|
||||||
) {
|
) {
|
||||||
val isRecognizedNumber: Boolean
|
val isRecognizedNumber: Boolean
|
||||||
get() = episodeNumber >= 0f
|
get() = episodeNumber >= 0f
|
||||||
|
@ -33,6 +34,7 @@ data class Episode(
|
||||||
dateUpload = -1,
|
dateUpload = -1,
|
||||||
episodeNumber = -1f,
|
episodeNumber = -1f,
|
||||||
scanlator = null,
|
scanlator = null,
|
||||||
|
lastModifiedAt = 0,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
[versions]
|
[versions]
|
||||||
compiler = "1.4.8"
|
compiler = "1.4.8"
|
||||||
compose-bom = "2023.06.00-alpha01"
|
compose-bom = "2023.07.00-alpha01"
|
||||||
accompanist = "0.31.4-beta"
|
accompanist = "0.31.5-beta"
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
activity = "androidx.activity:activity-compose:1.7.2"
|
activity = "androidx.activity:activity-compose:1.7.2"
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
[versions]
|
[versions]
|
||||||
aboutlib_version = "10.8.0"
|
aboutlib_version = "10.8.2"
|
||||||
okhttp_version = "5.0.0-alpha.11"
|
okhttp_version = "5.0.0-alpha.11"
|
||||||
shizuku_version = "12.2.0"
|
shizuku_version = "12.2.0"
|
||||||
sqlite = "2.3.1"
|
sqlite = "2.3.1"
|
||||||
|
@ -57,7 +57,7 @@ flexible-adapter-core = "com.github.arkon.FlexibleAdapter:flexible-adapter:c8013
|
||||||
photoview = "com.github.chrisbanes:PhotoView:2.3.0"
|
photoview = "com.github.chrisbanes:PhotoView:2.3.0"
|
||||||
directionalviewpager = "com.github.tachiyomiorg:DirectionalViewPager:1.0.0"
|
directionalviewpager = "com.github.tachiyomiorg:DirectionalViewPager:1.0.0"
|
||||||
insetter = "dev.chrisbanes.insetter:insetter:0.6.1"
|
insetter = "dev.chrisbanes.insetter:insetter:0.6.1"
|
||||||
compose-materialmotion = "io.github.fornewid:material-motion-compose-core:1.0.3"
|
compose-materialmotion = "io.github.fornewid:material-motion-compose-core:1.0.4"
|
||||||
compose-simpleicons = "br.com.devsrsouza.compose.icons.android:simple-icons:1.0.0"
|
compose-simpleicons = "br.com.devsrsouza.compose.icons.android:simple-icons:1.0.0"
|
||||||
|
|
||||||
swipe = "me.saket.swipe:swipe:1.2.0"
|
swipe = "me.saket.swipe:swipe:1.2.0"
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package tachiyomi.presentation.core.components
|
package tachiyomi.presentation.core.components
|
||||||
|
|
||||||
import androidx.compose.foundation.gestures.FlingBehavior
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.PaddingValues
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
import androidx.compose.foundation.lazy.grid.GridCells
|
import androidx.compose.foundation.lazy.grid.GridCells
|
||||||
|
@ -14,7 +13,6 @@ import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.unit.Dp
|
import androidx.compose.ui.unit.Dp
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import tachiyomi.presentation.core.util.flingBehaviorIgnoringMotionScale
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun FastScrollLazyVerticalGrid(
|
fun FastScrollLazyVerticalGrid(
|
||||||
|
@ -31,7 +29,6 @@ fun FastScrollLazyVerticalGrid(
|
||||||
verticalArrangement: Arrangement.Vertical =
|
verticalArrangement: Arrangement.Vertical =
|
||||||
if (!reverseLayout) Arrangement.Top else Arrangement.Bottom,
|
if (!reverseLayout) Arrangement.Top else Arrangement.Bottom,
|
||||||
horizontalArrangement: Arrangement.Horizontal = Arrangement.Start,
|
horizontalArrangement: Arrangement.Horizontal = Arrangement.Start,
|
||||||
flingBehavior: FlingBehavior = flingBehaviorIgnoringMotionScale(),
|
|
||||||
userScrollEnabled: Boolean = true,
|
userScrollEnabled: Boolean = true,
|
||||||
content: LazyGridScope.() -> Unit,
|
content: LazyGridScope.() -> Unit,
|
||||||
) {
|
) {
|
||||||
|
@ -54,7 +51,6 @@ fun FastScrollLazyVerticalGrid(
|
||||||
reverseLayout = reverseLayout,
|
reverseLayout = reverseLayout,
|
||||||
verticalArrangement = verticalArrangement,
|
verticalArrangement = verticalArrangement,
|
||||||
horizontalArrangement = horizontalArrangement,
|
horizontalArrangement = horizontalArrangement,
|
||||||
flingBehavior = flingBehavior,
|
|
||||||
userScrollEnabled = userScrollEnabled,
|
userScrollEnabled = userScrollEnabled,
|
||||||
content = content,
|
content = content,
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
package tachiyomi.presentation.core.components
|
package tachiyomi.presentation.core.components
|
||||||
|
|
||||||
import androidx.compose.foundation.gestures.FlingBehavior
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.PaddingValues
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
import androidx.compose.foundation.layout.calculateEndPadding
|
import androidx.compose.foundation.layout.calculateEndPadding
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.LazyListScope
|
import androidx.compose.foundation.lazy.LazyListScope
|
||||||
import androidx.compose.foundation.lazy.LazyListState
|
import androidx.compose.foundation.lazy.LazyListState
|
||||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||||
|
@ -15,38 +15,6 @@ import androidx.compose.ui.platform.LocalDensity
|
||||||
import androidx.compose.ui.platform.LocalLayoutDirection
|
import androidx.compose.ui.platform.LocalLayoutDirection
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import tachiyomi.presentation.core.util.drawVerticalScrollbar
|
import tachiyomi.presentation.core.util.drawVerticalScrollbar
|
||||||
import tachiyomi.presentation.core.util.flingBehaviorIgnoringMotionScale
|
|
||||||
|
|
||||||
/**
|
|
||||||
* LazyColumn with fling animation fix
|
|
||||||
*
|
|
||||||
* @see flingBehaviorIgnoringMotionScale
|
|
||||||
*/
|
|
||||||
@Composable
|
|
||||||
fun LazyColumn(
|
|
||||||
modifier: Modifier = Modifier,
|
|
||||||
state: LazyListState = rememberLazyListState(),
|
|
||||||
contentPadding: PaddingValues = PaddingValues(0.dp),
|
|
||||||
reverseLayout: Boolean = false,
|
|
||||||
verticalArrangement: Arrangement.Vertical =
|
|
||||||
if (!reverseLayout) Arrangement.Top else Arrangement.Bottom,
|
|
||||||
horizontalAlignment: Alignment.Horizontal = Alignment.Start,
|
|
||||||
flingBehavior: FlingBehavior = flingBehaviorIgnoringMotionScale(),
|
|
||||||
userScrollEnabled: Boolean = true,
|
|
||||||
content: LazyListScope.() -> Unit,
|
|
||||||
) {
|
|
||||||
androidx.compose.foundation.lazy.LazyColumn(
|
|
||||||
modifier = modifier,
|
|
||||||
state = state,
|
|
||||||
contentPadding = contentPadding,
|
|
||||||
reverseLayout = reverseLayout,
|
|
||||||
verticalArrangement = verticalArrangement,
|
|
||||||
horizontalAlignment = horizontalAlignment,
|
|
||||||
flingBehavior = flingBehavior,
|
|
||||||
userScrollEnabled = userScrollEnabled,
|
|
||||||
content = content,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* LazyColumn with scrollbar.
|
* LazyColumn with scrollbar.
|
||||||
|
@ -60,7 +28,6 @@ fun ScrollbarLazyColumn(
|
||||||
verticalArrangement: Arrangement.Vertical =
|
verticalArrangement: Arrangement.Vertical =
|
||||||
if (!reverseLayout) Arrangement.Top else Arrangement.Bottom,
|
if (!reverseLayout) Arrangement.Top else Arrangement.Bottom,
|
||||||
horizontalAlignment: Alignment.Horizontal = Alignment.Start,
|
horizontalAlignment: Alignment.Horizontal = Alignment.Start,
|
||||||
flingBehavior: FlingBehavior = flingBehaviorIgnoringMotionScale(),
|
|
||||||
userScrollEnabled: Boolean = true,
|
userScrollEnabled: Boolean = true,
|
||||||
content: LazyListScope.() -> Unit,
|
content: LazyListScope.() -> Unit,
|
||||||
) {
|
) {
|
||||||
|
@ -81,7 +48,6 @@ fun ScrollbarLazyColumn(
|
||||||
reverseLayout = reverseLayout,
|
reverseLayout = reverseLayout,
|
||||||
verticalArrangement = verticalArrangement,
|
verticalArrangement = verticalArrangement,
|
||||||
horizontalAlignment = horizontalAlignment,
|
horizontalAlignment = horizontalAlignment,
|
||||||
flingBehavior = flingBehavior,
|
|
||||||
userScrollEnabled = userScrollEnabled,
|
userScrollEnabled = userScrollEnabled,
|
||||||
content = content,
|
content = content,
|
||||||
)
|
)
|
||||||
|
@ -99,7 +65,6 @@ fun FastScrollLazyColumn(
|
||||||
verticalArrangement: Arrangement.Vertical =
|
verticalArrangement: Arrangement.Vertical =
|
||||||
if (!reverseLayout) Arrangement.Top else Arrangement.Bottom,
|
if (!reverseLayout) Arrangement.Top else Arrangement.Bottom,
|
||||||
horizontalAlignment: Alignment.Horizontal = Alignment.Start,
|
horizontalAlignment: Alignment.Horizontal = Alignment.Start,
|
||||||
flingBehavior: FlingBehavior = flingBehaviorIgnoringMotionScale(),
|
|
||||||
userScrollEnabled: Boolean = true,
|
userScrollEnabled: Boolean = true,
|
||||||
content: LazyListScope.() -> Unit,
|
content: LazyListScope.() -> Unit,
|
||||||
) {
|
) {
|
||||||
|
@ -115,7 +80,6 @@ fun FastScrollLazyColumn(
|
||||||
reverseLayout = reverseLayout,
|
reverseLayout = reverseLayout,
|
||||||
verticalArrangement = verticalArrangement,
|
verticalArrangement = verticalArrangement,
|
||||||
horizontalAlignment = horizontalAlignment,
|
horizontalAlignment = horizontalAlignment,
|
||||||
flingBehavior = flingBehavior,
|
|
||||||
userScrollEnabled = userScrollEnabled,
|
userScrollEnabled = userScrollEnabled,
|
||||||
content = content,
|
content = content,
|
||||||
)
|
)
|
||||||
|
|
|
@ -7,6 +7,7 @@ import androidx.compose.foundation.layout.PaddingValues
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.layout.width
|
import androidx.compose.foundation.layout.width
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.LazyItemScope
|
import androidx.compose.foundation.lazy.LazyItemScope
|
||||||
import androidx.compose.foundation.lazy.LazyListItemInfo
|
import androidx.compose.foundation.lazy.LazyListItemInfo
|
||||||
import androidx.compose.foundation.lazy.LazyListState
|
import androidx.compose.foundation.lazy.LazyListState
|
||||||
|
|
|
@ -1,60 +0,0 @@
|
||||||
package tachiyomi.presentation.core.util
|
|
||||||
|
|
||||||
import androidx.compose.animation.core.AnimationState
|
|
||||||
import androidx.compose.animation.core.DecayAnimationSpec
|
|
||||||
import androidx.compose.animation.core.animateDecay
|
|
||||||
import androidx.compose.animation.rememberSplineBasedDecay
|
|
||||||
import androidx.compose.foundation.gestures.FlingBehavior
|
|
||||||
import androidx.compose.foundation.gestures.ScrollScope
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.runtime.remember
|
|
||||||
import androidx.compose.ui.MotionDurationScale
|
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
import kotlin.math.abs
|
|
||||||
|
|
||||||
/**
|
|
||||||
* FlingBehavior that always uses the default motion scale.
|
|
||||||
*
|
|
||||||
* This makes the scrolling animation works like View's lists
|
|
||||||
* when "Remove animation" settings is on.
|
|
||||||
*/
|
|
||||||
@Composable
|
|
||||||
fun flingBehaviorIgnoringMotionScale(): FlingBehavior {
|
|
||||||
val flingSpec = rememberSplineBasedDecay<Float>()
|
|
||||||
return remember(flingSpec) {
|
|
||||||
DefaultFlingBehavior(flingSpec)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private val DefaultMotionDurationScale = object : MotionDurationScale {
|
|
||||||
// Use default motion scale factor
|
|
||||||
override val scaleFactor: Float = 1f
|
|
||||||
}
|
|
||||||
|
|
||||||
private class DefaultFlingBehavior(
|
|
||||||
private val flingDecay: DecayAnimationSpec<Float>,
|
|
||||||
) : FlingBehavior {
|
|
||||||
override suspend fun ScrollScope.performFling(initialVelocity: Float): Float {
|
|
||||||
// come up with the better threshold, but we need it since spline curve gives us NaNs
|
|
||||||
return if (abs(initialVelocity) > 1f) {
|
|
||||||
var velocityLeft = initialVelocity
|
|
||||||
var lastValue = 0f
|
|
||||||
withContext(DefaultMotionDurationScale) {
|
|
||||||
AnimationState(
|
|
||||||
initialValue = 0f,
|
|
||||||
initialVelocity = initialVelocity,
|
|
||||||
).animateDecay(flingDecay) {
|
|
||||||
val delta = value - lastValue
|
|
||||||
val consumed = scrollBy(delta)
|
|
||||||
lastValue = value
|
|
||||||
velocityLeft = this.velocity
|
|
||||||
// avoid rounding errors and stop if anything is unconsumed
|
|
||||||
if (abs(delta - consumed) > 0.5f) this.cancelAnimation()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
velocityLeft
|
|
||||||
} else {
|
|
||||||
initialVelocity
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in a new issue