Move reading progress to database
In this way cbz archives can be read without SpiderInfo.
This commit is contained in:
1 parent
9a7cabb221
commit
5f0be5ae43
14 files changed
+672
-151
No files matched your search
@@ -0,0 +1,471 @@
|
||||
{
|
||||
"formatVersion": 1,
|
||||
"database": {
|
||||
"version": 17,
|
||||
"identityHash": "d6375317a9298b7feae5925a23272bb9",
|
||||
"entities": [
|
||||
{
|
||||
"tableName": "GALLERIES",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`GID` INTEGER NOT NULL, `TOKEN` TEXT, `TITLE` TEXT, `TITLE_JPN` TEXT, `THUMB` TEXT, `CATEGORY` INTEGER NOT NULL, `POSTED` TEXT, `UPLOADER` TEXT, `RATING` REAL NOT NULL, `SIMPLE_LANGUAGE` TEXT, `FAVORITE_SLOT` INTEGER NOT NULL, PRIMARY KEY(`GID`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "gid",
|
||||
"columnName": "GID",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "token",
|
||||
"columnName": "TOKEN",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "title",
|
||||
"columnName": "TITLE",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "titleJpn",
|
||||
"columnName": "TITLE_JPN",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "thumbKey",
|
||||
"columnName": "THUMB",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "category",
|
||||
"columnName": "CATEGORY",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "posted",
|
||||
"columnName": "POSTED",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "uploader",
|
||||
"columnName": "UPLOADER",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "rating",
|
||||
"columnName": "RATING",
|
||||
"affinity": "REAL",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "simpleLanguage",
|
||||
"columnName": "SIMPLE_LANGUAGE",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "favoriteSlot",
|
||||
"columnName": "FAVORITE_SLOT",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"GID"
|
||||
]
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
},
|
||||
{
|
||||
"tableName": "DOWNLOAD_LABELS",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`LABEL` TEXT NOT NULL, `POSITION` INTEGER NOT NULL, `_id` INTEGER, PRIMARY KEY(`_id`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "label",
|
||||
"columnName": "LABEL",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "position",
|
||||
"columnName": "POSITION",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "_id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"_id"
|
||||
]
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_DOWNLOAD_LABELS_LABEL",
|
||||
"unique": true,
|
||||
"columnNames": [
|
||||
"LABEL"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_DOWNLOAD_LABELS_LABEL` ON `${TABLE_NAME}` (`LABEL`)"
|
||||
}
|
||||
],
|
||||
"foreignKeys": []
|
||||
},
|
||||
{
|
||||
"tableName": "DOWNLOADS",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`GID` INTEGER NOT NULL, `STATE` INTEGER NOT NULL, `LEGACY` INTEGER NOT NULL, `TIME` INTEGER NOT NULL, `LABEL` TEXT, `POSITION` INTEGER NOT NULL, PRIMARY KEY(`GID`), FOREIGN KEY(`GID`) REFERENCES `GALLERIES`(`GID`) ON UPDATE NO ACTION ON DELETE NO ACTION , FOREIGN KEY(`LABEL`) REFERENCES `DOWNLOAD_LABELS`(`LABEL`) ON UPDATE CASCADE ON DELETE SET NULL )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "gid",
|
||||
"columnName": "GID",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "state",
|
||||
"columnName": "STATE",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "legacy",
|
||||
"columnName": "LEGACY",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "time",
|
||||
"columnName": "TIME",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "label",
|
||||
"columnName": "LABEL",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "position",
|
||||
"columnName": "POSITION",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"GID"
|
||||
]
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_DOWNLOADS_LABEL",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"LABEL"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_DOWNLOADS_LABEL` ON `${TABLE_NAME}` (`LABEL`)"
|
||||
}
|
||||
],
|
||||
"foreignKeys": [
|
||||
{
|
||||
"table": "GALLERIES",
|
||||
"onDelete": "NO ACTION",
|
||||
"onUpdate": "NO ACTION",
|
||||
"columns": [
|
||||
"GID"
|
||||
],
|
||||
"referencedColumns": [
|
||||
"GID"
|
||||
]
|
||||
},
|
||||
{
|
||||
"table": "DOWNLOAD_LABELS",
|
||||
"onDelete": "SET NULL",
|
||||
"onUpdate": "CASCADE",
|
||||
"columns": [
|
||||
"LABEL"
|
||||
],
|
||||
"referencedColumns": [
|
||||
"LABEL"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tableName": "DOWNLOAD_DIRNAME",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`GID` INTEGER NOT NULL, `DIRNAME` TEXT NOT NULL, PRIMARY KEY(`GID`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "gid",
|
||||
"columnName": "GID",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "dirname",
|
||||
"columnName": "DIRNAME",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"GID"
|
||||
]
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
},
|
||||
{
|
||||
"tableName": "FILTER",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`MODE` INTEGER NOT NULL, `TEXT` TEXT NOT NULL, `ENABLE` INTEGER NOT NULL, `_id` INTEGER, PRIMARY KEY(`_id`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "mode",
|
||||
"columnName": "MODE",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "text",
|
||||
"columnName": "TEXT",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "enable",
|
||||
"columnName": "ENABLE",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "_id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"_id"
|
||||
]
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
},
|
||||
{
|
||||
"tableName": "HISTORY",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`GID` INTEGER NOT NULL, `TIME` INTEGER NOT NULL, PRIMARY KEY(`GID`), FOREIGN KEY(`GID`) REFERENCES `GALLERIES`(`GID`) ON UPDATE NO ACTION ON DELETE NO ACTION )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "gid",
|
||||
"columnName": "GID",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "time",
|
||||
"columnName": "TIME",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"GID"
|
||||
]
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": [
|
||||
{
|
||||
"table": "GALLERIES",
|
||||
"onDelete": "NO ACTION",
|
||||
"onUpdate": "NO ACTION",
|
||||
"columns": [
|
||||
"GID"
|
||||
],
|
||||
"referencedColumns": [
|
||||
"GID"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tableName": "LOCAL_FAVORITES",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`GID` INTEGER NOT NULL, `TIME` INTEGER NOT NULL, PRIMARY KEY(`GID`), FOREIGN KEY(`GID`) REFERENCES `GALLERIES`(`GID`) ON UPDATE NO ACTION ON DELETE NO ACTION )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "gid",
|
||||
"columnName": "GID",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "time",
|
||||
"columnName": "TIME",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"GID"
|
||||
]
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": [
|
||||
{
|
||||
"table": "GALLERIES",
|
||||
"onDelete": "NO ACTION",
|
||||
"onUpdate": "NO ACTION",
|
||||
"columns": [
|
||||
"GID"
|
||||
],
|
||||
"referencedColumns": [
|
||||
"GID"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tableName": "PROGRESS",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`GID` INTEGER NOT NULL, `PAGE` INTEGER NOT NULL, PRIMARY KEY(`GID`), FOREIGN KEY(`GID`) REFERENCES `GALLERIES`(`GID`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "gid",
|
||||
"columnName": "GID",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "page",
|
||||
"columnName": "PAGE",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"GID"
|
||||
]
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": [
|
||||
{
|
||||
"table": "GALLERIES",
|
||||
"onDelete": "CASCADE",
|
||||
"onUpdate": "NO ACTION",
|
||||
"columns": [
|
||||
"GID"
|
||||
],
|
||||
"referencedColumns": [
|
||||
"GID"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tableName": "QUICK_SEARCH",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`_id` INTEGER, `NAME` TEXT NOT NULL, `MODE` INTEGER NOT NULL, `CATEGORY` INTEGER NOT NULL, `KEYWORD` TEXT, `ADVANCE_SEARCH` INTEGER NOT NULL, `MIN_RATING` INTEGER NOT NULL, `PAGE_FROM` INTEGER NOT NULL, `PAGE_TO` INTEGER NOT NULL, `POSITION` INTEGER NOT NULL, PRIMARY KEY(`_id`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "_id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "name",
|
||||
"columnName": "NAME",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "mode",
|
||||
"columnName": "MODE",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "category",
|
||||
"columnName": "CATEGORY",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "keyword",
|
||||
"columnName": "KEYWORD",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "advanceSearch",
|
||||
"columnName": "ADVANCE_SEARCH",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "minRating",
|
||||
"columnName": "MIN_RATING",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "pageFrom",
|
||||
"columnName": "PAGE_FROM",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "pageTo",
|
||||
"columnName": "PAGE_TO",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "position",
|
||||
"columnName": "POSITION",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"_id"
|
||||
]
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
}
|
||||
],
|
||||
"views": [],
|
||||
"setupQueries": [
|
||||
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
||||
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'd6375317a9298b7feae5925a23272bb9')"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,7 @@ import com.hippo.ehviewer.dao.EhDatabase
|
||||
import com.hippo.ehviewer.dao.Filter
|
||||
import com.hippo.ehviewer.dao.HistoryInfo
|
||||
import com.hippo.ehviewer.dao.LocalFavoriteInfo
|
||||
import com.hippo.ehviewer.dao.ProgressInfo
|
||||
import com.hippo.ehviewer.dao.QuickSearch
|
||||
import com.hippo.ehviewer.download.DownloadManager
|
||||
import com.hippo.ehviewer.util.sendTo
|
||||
@@ -45,6 +46,11 @@ object EhDB {
|
||||
runCatching { db.galleryDao().delete(galleryInfo) }
|
||||
}
|
||||
|
||||
fun getReadProgressFlow(gid: Long) = db.progressDao().getPageFlow(gid)
|
||||
suspend fun getReadProgress(gid: Long) = db.progressDao().getPage(gid)
|
||||
suspend fun putReadProgress(gid: Long, page: Int) = db.progressDao().upsert(ProgressInfo(gid, page))
|
||||
suspend fun clearProgressInfo() = db.progressDao().deleteAll()
|
||||
|
||||
suspend fun getAllDownloadInfo() = db.downloadsDao().joinList().onEach {
|
||||
if (it.state == DownloadInfo.STATE_WAIT || it.state == DownloadInfo.STATE_DOWNLOAD) {
|
||||
it.state = DownloadInfo.STATE_NONE
|
||||
@@ -251,6 +257,7 @@ object EhDB {
|
||||
context.deleteDatabase(ehExportName)
|
||||
} use { newDb ->
|
||||
db.galleryDao().list().let { newDb.galleryDao().insertOrIgnore(it) }
|
||||
db.progressDao().list().let { newDb.progressDao().insertOrIgnore(it) }
|
||||
db.downloadLabelDao().list().let { newDb.downloadLabelDao().insert(it) }
|
||||
db.downloadDirnameDao().list().let { newDb.downloadDirnameDao().insertOrIgnore(it) }
|
||||
db.downloadsDao().list().let { newDb.downloadsDao().insert(it) }
|
||||
@@ -276,6 +283,9 @@ object EhDB {
|
||||
runCatching {
|
||||
db.galleryDao().insertOrIgnore(oldDB.galleryDao().list())
|
||||
}
|
||||
runCatching {
|
||||
db.progressDao().insertOrIgnore(oldDB.progressDao().list())
|
||||
}
|
||||
runCatching {
|
||||
val downloadLabelList = oldDB.downloadLabelDao().list()
|
||||
DownloadManager.addDownloadLabel(downloadLabelList)
|
||||
|
||||
@@ -108,8 +108,11 @@ class ThumbKeyMigration : AutoMigrationSpec {
|
||||
}
|
||||
|
||||
@Database(
|
||||
entities = [BaseGalleryInfo::class, DownloadLabel::class, DownloadEntity::class, DownloadDirname::class, Filter::class, HistoryInfo::class, LocalFavoriteInfo::class, QuickSearch::class],
|
||||
version = 16,
|
||||
entities = [
|
||||
BaseGalleryInfo::class, DownloadLabel::class, DownloadEntity::class, DownloadDirname::class,
|
||||
Filter::class, HistoryInfo::class, LocalFavoriteInfo::class, ProgressInfo::class, QuickSearch::class,
|
||||
],
|
||||
version = 17,
|
||||
exportSchema = true,
|
||||
autoMigrations = [
|
||||
AutoMigration(
|
||||
@@ -167,6 +170,10 @@ class ThumbKeyMigration : AutoMigrationSpec {
|
||||
from = 15,
|
||||
to = 16,
|
||||
),
|
||||
AutoMigration(
|
||||
from = 16,
|
||||
to = 17,
|
||||
),
|
||||
],
|
||||
)
|
||||
@TypeConverters(FilterModeConverter::class)
|
||||
@@ -178,6 +185,7 @@ abstract class EhDatabase : RoomDatabase() {
|
||||
abstract fun filterDao(): FilterDao
|
||||
abstract fun historyDao(): HistoryDao
|
||||
abstract fun localFavoritesDao(): LocalFavoritesDao
|
||||
abstract fun progressDao(): ProgressDao
|
||||
abstract fun quickSearchDao(): QuickSearchDao
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.hippo.ehviewer.dao
|
||||
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Insert
|
||||
import androidx.room.OnConflictStrategy
|
||||
import androidx.room.Query
|
||||
import androidx.room.Upsert
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
@Dao
|
||||
interface ProgressDao {
|
||||
@Query("SELECT IFNULL(PAGE, 0) FROM PROGRESS WHERE GID = :gid")
|
||||
suspend fun getPage(gid: Long): Int
|
||||
|
||||
@Query("SELECT IFNULL(PAGE, 0) FROM PROGRESS WHERE GID = :gid")
|
||||
fun getPageFlow(gid: Long): Flow<Int>
|
||||
|
||||
@Query("SELECT * FROM PROGRESS")
|
||||
suspend fun list(): List<ProgressInfo>
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.IGNORE)
|
||||
suspend fun insertOrIgnore(progress: List<ProgressInfo>)
|
||||
|
||||
@Upsert
|
||||
suspend fun upsert(progress: ProgressInfo)
|
||||
|
||||
@Query("DELETE FROM PROGRESS")
|
||||
suspend fun deleteAll()
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.hippo.ehviewer.dao
|
||||
|
||||
import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import androidx.room.ForeignKey
|
||||
import androidx.room.PrimaryKey
|
||||
import com.hippo.ehviewer.client.data.BaseGalleryInfo
|
||||
|
||||
@Entity(
|
||||
tableName = "PROGRESS",
|
||||
foreignKeys = [
|
||||
ForeignKey(BaseGalleryInfo::class, ["GID"], ["GID"], onDelete = ForeignKey.CASCADE),
|
||||
],
|
||||
)
|
||||
class ProgressInfo(
|
||||
@PrimaryKey
|
||||
@ColumnInfo(name = "GID")
|
||||
val gid: Long,
|
||||
|
||||
@ColumnInfo(name = "PAGE")
|
||||
val page: Int,
|
||||
)
|
||||
@@ -37,8 +37,6 @@ import com.hippo.ehviewer.image.Image
|
||||
import com.hippo.ehviewer.spider.SpiderQueen
|
||||
import com.hippo.ehviewer.spider.SpiderQueen.OnSpiderListener
|
||||
import com.hippo.ehviewer.spider.putToDownloadDir
|
||||
import com.hippo.ehviewer.spider.readCompatFromUniFile
|
||||
import com.hippo.ehviewer.spider.write
|
||||
import com.hippo.ehviewer.util.AppConfig
|
||||
import com.hippo.ehviewer.util.ConcurrentPool
|
||||
import com.hippo.ehviewer.util.SimpleHandler
|
||||
@@ -49,11 +47,9 @@ import com.hippo.unifile.UniFile
|
||||
import com.hippo.unifile.asUniFile
|
||||
import com.hippo.unifile.asUniFileOrNull
|
||||
import eu.kanade.tachiyomi.util.lang.launchIO
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.asSharedFlow
|
||||
import kotlinx.coroutines.flow.transform
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
import splitties.preferences.edit
|
||||
@@ -457,26 +453,9 @@ object DownloadManager : OnSpiderListener {
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun resetAllReadingProgress() = coroutineScope {
|
||||
allInfoList.forEach { info ->
|
||||
launch {
|
||||
runCatching {
|
||||
resetReadingProgress(info)
|
||||
Log.d(TAG, "Current thread: ${Thread.currentThread().name}")
|
||||
}.onFailure {
|
||||
Log.e(TAG, "Can't write SpiderInfo", it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun resetReadingProgress(info: DownloadInfo) {
|
||||
val downloadDir = info.downloadDir ?: return
|
||||
val file = downloadDir.findFile(SpiderQueen.SPIDER_INFO_FILENAME) ?: return
|
||||
val spiderInfo = readCompatFromUniFile(file) ?: return
|
||||
spiderInfo.startPage = 0
|
||||
spiderInfo.write(file)
|
||||
}
|
||||
suspend fun resetAllReadingProgress() = runCatching {
|
||||
EhDB.clearProgressInfo()
|
||||
}.onFailure { it.printStackTrace() }
|
||||
|
||||
// Update in DB
|
||||
// Update listener
|
||||
|
||||
@@ -31,11 +31,8 @@ import com.hippo.ehviewer.jni.releaseByteBuffer
|
||||
import com.hippo.ehviewer.util.FileUtils
|
||||
import com.hippo.unifile.UniFile
|
||||
import java.nio.ByteBuffer
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.CoroutineStart
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.cancel
|
||||
import kotlinx.coroutines.currentCoroutineContext
|
||||
import kotlinx.coroutines.ensureActive
|
||||
import kotlinx.coroutines.launch
|
||||
@@ -47,8 +44,12 @@ import moe.tarsin.coroutines.withLock
|
||||
typealias PasswdInvalidator = (String) -> Boolean
|
||||
typealias PasswdProvider = suspend (PasswdInvalidator) -> String
|
||||
|
||||
class ArchivePageLoader(private val file: UniFile, passwdProvider: PasswdProvider? = null) : PageLoader2(), CoroutineScope {
|
||||
override val coroutineContext = Dispatchers.IO + Job()
|
||||
class ArchivePageLoader(
|
||||
private val file: UniFile,
|
||||
gid: Long = 0,
|
||||
startPage: Int = 0,
|
||||
passwdProvider: PasswdProvider? = null,
|
||||
) : PageLoader2(gid, startPage) {
|
||||
private lateinit var pfd: ParcelFileDescriptor
|
||||
private val hostJob = launch(start = CoroutineStart.LAZY) {
|
||||
Log.d(DEBUG_TAG, "Open archive ${file.uri}")
|
||||
@@ -76,11 +77,10 @@ class ArchivePageLoader(private val file: UniFile, passwdProvider: PasswdProvide
|
||||
}
|
||||
|
||||
override fun stop() {
|
||||
cancel()
|
||||
super.stop()
|
||||
closeArchive()
|
||||
pfd.close()
|
||||
Log.d(DEBUG_TAG, "Close archive ${file.uri} successfully!")
|
||||
super.stop()
|
||||
}
|
||||
|
||||
private val mJobMap = hashMapOf<Int, Job>()
|
||||
@@ -135,7 +135,7 @@ class ArchivePageLoader(private val file: UniFile, passwdProvider: PasswdProvide
|
||||
|
||||
override suspend fun awaitReady(): Boolean {
|
||||
hostJob.join()
|
||||
return size != 0
|
||||
return super.awaitReady() && size != 0
|
||||
}
|
||||
|
||||
override val isReady: Boolean
|
||||
|
||||
@@ -22,10 +22,10 @@ import com.hippo.ehviewer.spider.SpiderQueen
|
||||
import com.hippo.ehviewer.spider.SpiderQueen.Companion.obtainSpiderQueen
|
||||
import com.hippo.ehviewer.spider.SpiderQueen.Companion.releaseSpiderQueen
|
||||
import com.hippo.ehviewer.spider.SpiderQueen.OnSpiderListener
|
||||
import com.hippo.ehviewer.util.SimpleHandler
|
||||
import com.hippo.unifile.UniFile
|
||||
|
||||
class EhPageLoader(private val mGalleryInfo: GalleryInfo) : PageLoader2(), OnSpiderListener {
|
||||
class EhPageLoader(private val mGalleryInfo: GalleryInfo, startPage: Int) :
|
||||
PageLoader2(mGalleryInfo.gid, startPage), OnSpiderListener {
|
||||
private lateinit var mSpiderQueen: SpiderQueen
|
||||
override fun start() {
|
||||
super.start()
|
||||
@@ -38,13 +38,9 @@ class EhPageLoader(private val mGalleryInfo: GalleryInfo) : PageLoader2(), OnSpi
|
||||
override fun stop() {
|
||||
super.stop()
|
||||
mSpiderQueen.removeOnSpiderListener(this)
|
||||
// Activity recreate may called, so wait 0.5s
|
||||
SimpleHandler.postDelayed(ReleaseTask(mSpiderQueen), 500)
|
||||
releaseSpiderQueen(mSpiderQueen, SpiderQueen.MODE_READ)
|
||||
}
|
||||
|
||||
override val startPage
|
||||
get() = mSpiderQueen.startPage
|
||||
|
||||
override val title by lazy {
|
||||
EhUtils.getSuitableTitle(mGalleryInfo)
|
||||
}
|
||||
@@ -57,10 +53,6 @@ class EhPageLoader(private val mGalleryInfo: GalleryInfo) : PageLoader2(), OnSpi
|
||||
return mSpiderQueen.save(index, file)
|
||||
}
|
||||
|
||||
override fun putStartPage(page: Int) {
|
||||
mSpiderQueen.putStartPage(page)
|
||||
}
|
||||
|
||||
override val size: Int
|
||||
get() = mSpiderQueen.size
|
||||
|
||||
@@ -73,7 +65,7 @@ class EhPageLoader(private val mGalleryInfo: GalleryInfo) : PageLoader2(), OnSpi
|
||||
}
|
||||
|
||||
override suspend fun awaitReady(): Boolean {
|
||||
return mSpiderQueen.awaitReady()
|
||||
return super.awaitReady() && mSpiderQueen.awaitReady()
|
||||
}
|
||||
|
||||
override val isReady: Boolean
|
||||
@@ -121,11 +113,4 @@ class EhPageLoader(private val mGalleryInfo: GalleryInfo) : PageLoader2(), OnSpi
|
||||
override fun preloadPages(pages: List<Int>, pair: Pair<Int, Int>) {
|
||||
mSpiderQueen.preloadPages(pages, pair)
|
||||
}
|
||||
|
||||
private class ReleaseTask(private var mSpiderQueen: SpiderQueen?) : Runnable {
|
||||
override fun run() {
|
||||
mSpiderQueen?.let { releaseSpiderQueen(it, SpiderQueen.MODE_READ) }
|
||||
mSpiderQueen = null
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,14 +15,47 @@
|
||||
*/
|
||||
package com.hippo.ehviewer.gallery
|
||||
|
||||
import androidx.annotation.CallSuper
|
||||
import com.hippo.ehviewer.EhDB
|
||||
import com.hippo.unifile.UniFile
|
||||
import eu.kanade.tachiyomi.ui.reader.loader.PageLoader
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.CoroutineStart
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.cancel
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
abstract class PageLoader2 : PageLoader() {
|
||||
open val startPage: Int
|
||||
get() = 0
|
||||
abstract class PageLoader2(private val gid: Long, var startPage: Int) : PageLoader(), CoroutineScope {
|
||||
override val coroutineContext = Dispatchers.IO + Job()
|
||||
private val progressJob = launch(start = CoroutineStart.LAZY) {
|
||||
if (startPage == -1) {
|
||||
startPage = EhDB.getReadProgress(gid)
|
||||
}
|
||||
}
|
||||
|
||||
open fun putStartPage(page: Int) {}
|
||||
override fun start() {
|
||||
super.start()
|
||||
progressJob.start()
|
||||
}
|
||||
|
||||
@CallSuper
|
||||
override suspend fun awaitReady(): Boolean {
|
||||
progressJob.join()
|
||||
return startPage != -1
|
||||
}
|
||||
|
||||
override fun stop() {
|
||||
super.stop()
|
||||
if (gid != 0L) {
|
||||
launch {
|
||||
EhDB.putReadProgress(gid, startPage)
|
||||
this@PageLoader2.cancel()
|
||||
}
|
||||
} else {
|
||||
cancel()
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract val title: String
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ fun readLegacySpiderInfo(inputStream: InputStream): SpiderInfo {
|
||||
val previewPerPage = readInt()
|
||||
val pages = read().toInt()
|
||||
val pTokenMap = hashMapOf<Int, String>()
|
||||
val info = SpiderInfo(gid, pages, pTokenMap, 0, token, previewPages, previewPerPage)
|
||||
val info = SpiderInfo(gid, token, pages, pTokenMap, previewPages, previewPerPage)
|
||||
runCatching {
|
||||
while (true) {
|
||||
val line = read()
|
||||
|
||||
@@ -19,29 +19,31 @@ import splitties.init.appCtx
|
||||
class SpiderInfo(
|
||||
val gid: Long,
|
||||
|
||||
val token: String,
|
||||
|
||||
val pages: Int,
|
||||
|
||||
val pTokenMap: MutableMap<Int, String> = hashMapOf(),
|
||||
|
||||
var startPage: Int = 0,
|
||||
|
||||
var token: String? = null,
|
||||
|
||||
var previewPages: Int = -1,
|
||||
|
||||
var previewPerPage: Int = -1,
|
||||
)
|
||||
|
||||
private val cbor = Cbor {
|
||||
ignoreUnknownKeys = true
|
||||
}
|
||||
|
||||
fun SpiderInfo.write(file: UniFile) {
|
||||
file.openOutputStream().use {
|
||||
it.write(Cbor.encodeToByteArray(this))
|
||||
it.write(cbor.encodeToByteArray(this))
|
||||
}
|
||||
}
|
||||
|
||||
fun SpiderInfo.saveToCache() {
|
||||
runSuspendCatching {
|
||||
spiderInfoCache.edit(gid.toString()) {
|
||||
data.toFile().writeBytes(Cbor.encodeToByteArray(this@saveToCache))
|
||||
data.toFile().writeBytes(cbor.encodeToByteArray(this@saveToCache))
|
||||
}
|
||||
}.onFailure {
|
||||
it.printStackTrace()
|
||||
@@ -58,7 +60,7 @@ private val spiderInfoCache by lazy {
|
||||
fun readFromCache(gid: Long): SpiderInfo? {
|
||||
return spiderInfoCache.read(gid.toString()) {
|
||||
runCatching {
|
||||
Cbor.decodeFromByteArray<SpiderInfo>(data.toFile().readBytes())
|
||||
cbor.decodeFromByteArray<SpiderInfo>(data.toFile().readBytes())
|
||||
}.onFailure {
|
||||
it.printStackTrace()
|
||||
}.getOrNull()
|
||||
@@ -68,7 +70,7 @@ fun readFromCache(gid: Long): SpiderInfo? {
|
||||
fun readCompatFromUniFile(file: UniFile): SpiderInfo? {
|
||||
return runCatching {
|
||||
file.openInputStream().use {
|
||||
Cbor.decodeFromByteArray<SpiderInfo>(it.readBytes())
|
||||
cbor.decodeFromByteArray<SpiderInfo>(it.readBytes())
|
||||
}
|
||||
}.getOrNull() ?: runCatching {
|
||||
file.openInputStream().use { readLegacySpiderInfo(it) }
|
||||
|
||||
@@ -237,12 +237,6 @@ class SpiderQueen private constructor(val galleryInfo: GalleryInfo) : CoroutineS
|
||||
return isReady
|
||||
}
|
||||
|
||||
suspend fun awaitStartPage(): Int {
|
||||
prepareJob.join()
|
||||
if (!isReady) return 0
|
||||
return mSpiderInfo.startPage
|
||||
}
|
||||
|
||||
private fun stop() {
|
||||
val queenScope = this
|
||||
launchIO {
|
||||
@@ -317,13 +311,6 @@ class SpiderQueen private constructor(val galleryInfo: GalleryInfo) : CoroutineS
|
||||
}
|
||||
}
|
||||
|
||||
val startPage: Int
|
||||
get() = mSpiderInfo.startPage
|
||||
|
||||
fun putStartPage(page: Int) {
|
||||
mSpiderInfo.startPage = page
|
||||
}
|
||||
|
||||
private fun readSpiderInfoFromLocal(): SpiderInfo? {
|
||||
return mSpiderDen.downloadDir?.run {
|
||||
findFile(SPIDER_INFO_FILENAME)?.let { file ->
|
||||
@@ -360,7 +347,7 @@ class SpiderQueen private constructor(val galleryInfo: GalleryInfo) : CoroutineS
|
||||
referer,
|
||||
).fetchUsingAsText {
|
||||
val pages = parsePages(this)
|
||||
val spiderInfo = SpiderInfo(galleryInfo.gid, pages, token = galleryInfo.token)
|
||||
val spiderInfo = SpiderInfo(galleryInfo.gid, galleryInfo.token!!, pages)
|
||||
readPreviews(this, 0, spiderInfo)
|
||||
spiderInfo
|
||||
}
|
||||
@@ -632,12 +619,12 @@ class SpiderQueen private constructor(val galleryInfo: GalleryInfo) : CoroutineS
|
||||
showKeyLock.withLock {
|
||||
localShowKey = showKey
|
||||
if (localShowKey == null || forceHtml) {
|
||||
var pageUrl = EhUrl.getPageUrl(mSpiderInfo.gid, index, pToken)
|
||||
var pageUrl = EhUrl.getPageUrl(galleryInfo.gid, index, pToken)
|
||||
// Skipping H@H costs 50 points, only use it as last resort
|
||||
if (skipHathKey != null) {
|
||||
pageUrl += "?nl=$skipHathKey"
|
||||
}
|
||||
EhEngine.getGalleryPage(pageUrl, mSpiderInfo.gid, mSpiderInfo.token)
|
||||
EhEngine.getGalleryPage(pageUrl, galleryInfo.gid, galleryInfo.token)
|
||||
.let { result ->
|
||||
check509(result.imageUrl)
|
||||
imageUrl = result.imageUrl
|
||||
|
||||
@@ -61,6 +61,7 @@ import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass
|
||||
import androidx.compose.material3.windowsizeclass.calculateWindowSizeClass
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableFloatStateOf
|
||||
import androidx.compose.runtime.mutableIntStateOf
|
||||
@@ -120,8 +121,6 @@ import com.hippo.ehviewer.databinding.DialogTorrentListBinding
|
||||
import com.hippo.ehviewer.download.DownloadManager as EhDownloadManager
|
||||
import com.hippo.ehviewer.ktbuilder.imageRequest
|
||||
import com.hippo.ehviewer.spider.SpiderDen
|
||||
import com.hippo.ehviewer.spider.SpiderQueen
|
||||
import com.hippo.ehviewer.spider.SpiderQueen.Companion.MODE_READ
|
||||
import com.hippo.ehviewer.ui.GalleryInfoBottomSheet
|
||||
import com.hippo.ehviewer.ui.LocalSnackbarHostState
|
||||
import com.hippo.ehviewer.ui.LockDrawer
|
||||
@@ -150,6 +149,7 @@ import com.hippo.ehviewer.ui.tools.FilledTertiaryIconToggleButton
|
||||
import com.hippo.ehviewer.ui.tools.GalleryDetailRating
|
||||
import com.hippo.ehviewer.ui.tools.GalleryRatingBar
|
||||
import com.hippo.ehviewer.ui.tools.LocalDialogState
|
||||
import com.hippo.ehviewer.ui.tools.rememberInVM
|
||||
import com.hippo.ehviewer.ui.tools.rememberLambda
|
||||
import com.hippo.ehviewer.util.AppHelper
|
||||
import com.hippo.ehviewer.util.ExceptionUtils
|
||||
@@ -905,13 +905,13 @@ fun GalleryDetailScreen(args: GalleryDetailScreenArgs, navigator: DestinationsNa
|
||||
val windowSizeClass = calculateWindowSizeClass(activity)
|
||||
val thumbColumns by Settings.thumbColumns.collectAsState()
|
||||
val readText = stringResource(R.string.read)
|
||||
val startPage by rememberInVM {
|
||||
EhDB.getReadProgressFlow(galleryInfo.gid)
|
||||
}.collectAsState(0)
|
||||
var readButtonText by rememberSaveable { mutableStateOf(readText) }
|
||||
LifecycleResumeEffect(Unit) {
|
||||
coroutineScope.launchIO {
|
||||
runSuspendCatching {
|
||||
val queen = SpiderQueen.obtainSpiderQueen(galleryInfo, MODE_READ)
|
||||
val startPage = queen.awaitStartPage()
|
||||
SpiderQueen.releaseSpiderQueen(queen, MODE_READ)
|
||||
readButtonText = if (startPage == 0) {
|
||||
readText
|
||||
} else {
|
||||
@@ -931,7 +931,7 @@ fun GalleryDetailScreen(args: GalleryDetailScreenArgs, navigator: DestinationsNa
|
||||
DownloadInfo.STATE_FAILED -> stringResource(R.string.download_state_failed)
|
||||
else -> error("Invalid DownloadState!!!")
|
||||
}
|
||||
fun onReadButtonClick() = context.navToReader(galleryInfo.findBaseInfo())
|
||||
fun onReadButtonClick() = context.navToReader(galleryInfo.findBaseInfo(), startPage)
|
||||
fun onCategoryChipClick() {
|
||||
val category = galleryInfo.category
|
||||
if (category == EhUtils.NONE || category == EhUtils.PRIVATE || category == EhUtils.UNKNOWN) {
|
||||
|
||||
@@ -133,10 +133,9 @@ class GalleryModel : ViewModel() {
|
||||
class ReaderActivity : EhActivity() {
|
||||
lateinit var binding: ReaderActivityBinding
|
||||
private var mAction: String? = null
|
||||
private var mFilename: String? = null
|
||||
private var mUri: Uri? = null
|
||||
private var mGalleryInfo: BaseGalleryInfo? = null
|
||||
private var mPage: Int = 0
|
||||
private var mPage: Int = -1
|
||||
private val vm: GalleryModel by viewModels()
|
||||
private val dialogState = DialogState()
|
||||
|
||||
@@ -145,7 +144,11 @@ class ReaderActivity : EhActivity() {
|
||||
*/
|
||||
var menuVisible by mutableStateOf(false)
|
||||
private var mGalleryProvider by lazyMut { vm::galleryProvider }
|
||||
private var mCurrentIndex: Int = 0
|
||||
private var mCurrentIndex: Int
|
||||
get() = mGalleryProvider!!.startPage
|
||||
set(value) {
|
||||
mGalleryProvider!!.startPage = value
|
||||
}
|
||||
|
||||
private val galleryDetailUrl: String?
|
||||
get() {
|
||||
@@ -160,56 +163,56 @@ class ReaderActivity : EhActivity() {
|
||||
return EhUrl.getGalleryDetailUrl(gid, token, 0, false)
|
||||
}
|
||||
|
||||
private fun buildProvider(replace: Boolean = false) {
|
||||
if (mGalleryProvider != null) {
|
||||
if (replace) mGalleryProvider!!.stop() else return
|
||||
private suspend fun buildProvider(replace: Boolean = false): PageLoader2? {
|
||||
mGalleryProvider?.let {
|
||||
if (replace) it.stop() else return it
|
||||
}
|
||||
|
||||
if (ACTION_EH == mAction) {
|
||||
mGalleryInfo?.let {
|
||||
mGalleryProvider = DownloadManager.getDownloadInfo(it.gid)?.downloadDir
|
||||
?.findFile("${it.gid}.cbz")
|
||||
?.let { file -> ArchivePageLoader(file) }
|
||||
?: EhPageLoader(it)
|
||||
}
|
||||
} else if (Intent.ACTION_VIEW == mAction) {
|
||||
if (mUri != null) {
|
||||
try {
|
||||
grantUriPermission(
|
||||
BuildConfig.APPLICATION_ID,
|
||||
mUri,
|
||||
Intent.FLAG_GRANT_READ_URI_PERMISSION,
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
Toast.makeText(this, R.string.error_reading_failed, Toast.LENGTH_SHORT).show()
|
||||
val provider = when (mAction) {
|
||||
ACTION_EH -> {
|
||||
mGalleryInfo?.let {
|
||||
DownloadManager.getDownloadInfo(it.gid)?.downloadDir
|
||||
?.findFile("${it.gid}.cbz")
|
||||
?.let { file -> ArchivePageLoader(file, it.gid, mPage) }
|
||||
?: EhPageLoader(it, mPage)
|
||||
}
|
||||
}
|
||||
|
||||
mGalleryProvider = ArchivePageLoader(mUri!!.asUniFile()) { invalidator ->
|
||||
runCatching {
|
||||
dialogState.awaitInputText(
|
||||
title = getString(R.string.archive_need_passwd),
|
||||
hint = getString(R.string.archive_passwd),
|
||||
) {
|
||||
if (it.isBlank()) {
|
||||
getString(R.string.passwd_cannot_be_empty)
|
||||
} else if (invalidator(it)) {
|
||||
null
|
||||
} else {
|
||||
getString(R.string.passwd_wrong)
|
||||
Intent.ACTION_VIEW -> {
|
||||
mUri?.run {
|
||||
ArchivePageLoader(asUniFile()) { invalidator ->
|
||||
runCatching {
|
||||
dialogState.awaitInputText(
|
||||
title = getString(R.string.archive_need_passwd),
|
||||
hint = getString(R.string.archive_passwd),
|
||||
) {
|
||||
if (it.isBlank()) {
|
||||
getString(R.string.passwd_cannot_be_empty)
|
||||
} else if (invalidator(it)) {
|
||||
null
|
||||
} else {
|
||||
getString(R.string.passwd_wrong)
|
||||
}
|
||||
}
|
||||
}
|
||||
}.onFailure {
|
||||
finish()
|
||||
}.getOrThrow()
|
||||
}.onFailure {
|
||||
finish()
|
||||
}.getOrThrow()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else -> null
|
||||
}
|
||||
if (provider == null) {
|
||||
makeToast(R.string.error_reading_failed)
|
||||
finish()
|
||||
}
|
||||
return provider
|
||||
}
|
||||
|
||||
private fun handleIntent(intent: Intent?) {
|
||||
intent ?: return
|
||||
mAction = intent.action
|
||||
mFilename = intent.getStringExtra(KEY_FILENAME)
|
||||
mUri = intent.data
|
||||
mGalleryInfo = intent.getParcelableExtraCompat(KEY_GALLERY_INFO)
|
||||
mPage = intent.getIntExtra(KEY_PAGE, -1)
|
||||
@@ -221,19 +224,17 @@ class ReaderActivity : EhActivity() {
|
||||
|
||||
private fun onRestore(savedInstanceState: Bundle) {
|
||||
mAction = savedInstanceState.getString(KEY_ACTION)
|
||||
mFilename = savedInstanceState.getString(KEY_FILENAME)
|
||||
mUri = savedInstanceState.getParcelableCompat(KEY_URI)
|
||||
mGalleryInfo = savedInstanceState.getParcelableCompat(KEY_GALLERY_INFO)
|
||||
mPage = savedInstanceState.getInt(KEY_PAGE, -1)
|
||||
mCurrentIndex = savedInstanceState.getInt(KEY_CURRENT_INDEX)
|
||||
}
|
||||
|
||||
override fun onNewIntent(intent: Intent?) {
|
||||
super.onNewIntent(intent)
|
||||
handleIntent(intent)
|
||||
buildProvider(true)
|
||||
mGalleryProvider?.let {
|
||||
lifecycleScope.launchIO {
|
||||
lifecycleScope.launchIO {
|
||||
buildProvider(true)?.let {
|
||||
mGalleryProvider = it
|
||||
it.start()
|
||||
if (it.awaitReady()) {
|
||||
withUIContext {
|
||||
@@ -241,6 +242,9 @@ class ReaderActivity : EhActivity() {
|
||||
viewer?.setGalleryProvider(it)
|
||||
moveToPageIndex(0)
|
||||
}
|
||||
} else {
|
||||
makeToast(R.string.error_reading_failed)
|
||||
finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -249,13 +253,11 @@ class ReaderActivity : EhActivity() {
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
super.onSaveInstanceState(outState)
|
||||
outState.putString(KEY_ACTION, mAction)
|
||||
outState.putString(KEY_FILENAME, mFilename)
|
||||
outState.putParcelable(KEY_URI, mUri)
|
||||
if (mGalleryInfo != null) {
|
||||
outState.putParcelable(KEY_GALLERY_INFO, mGalleryInfo)
|
||||
}
|
||||
outState.putInt(KEY_PAGE, mPage)
|
||||
outState.putInt(KEY_CURRENT_INDEX, mCurrentIndex)
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
@@ -272,7 +274,6 @@ class ReaderActivity : EhActivity() {
|
||||
} else {
|
||||
onRestore(savedInstanceState)
|
||||
}
|
||||
buildProvider()
|
||||
binding = ReaderActivityBinding.inflate(layoutInflater)
|
||||
binding.dialogStub.setMD3Content {
|
||||
val brightness by Settings.customBrightness.collectAsState()
|
||||
@@ -319,14 +320,16 @@ class ReaderActivity : EhActivity() {
|
||||
)
|
||||
}
|
||||
setContentView(binding.root)
|
||||
mGalleryProvider.let {
|
||||
if (it == null) {
|
||||
finish()
|
||||
return
|
||||
}
|
||||
lifecycleScope.launchIO {
|
||||
lifecycleScope.launchIO {
|
||||
buildProvider()?.let {
|
||||
mGalleryProvider = it
|
||||
it.start()
|
||||
if (it.awaitReady()) withUIContext { setGallery() }
|
||||
if (it.awaitReady()) {
|
||||
withUIContext { setGallery() }
|
||||
} else {
|
||||
makeToast(R.string.error_reading_failed)
|
||||
finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -348,10 +351,6 @@ class ReaderActivity : EhActivity() {
|
||||
private fun setGallery() {
|
||||
if (mGalleryProvider?.isReady != true) return
|
||||
|
||||
// Get start page
|
||||
if (mCurrentIndex == 0) {
|
||||
mCurrentIndex = if (mPage >= 0) mPage else mGalleryProvider!!.startPage
|
||||
}
|
||||
totalPage = mGalleryProvider!!.size
|
||||
viewer?.destroy()
|
||||
viewer = ReadingModeType.toViewer(ReaderPreferences.defaultReadingMode().get(), this)
|
||||
@@ -503,11 +502,9 @@ class ReaderActivity : EhActivity() {
|
||||
companion object {
|
||||
const val ACTION_EH = "eh"
|
||||
const val KEY_ACTION = "action"
|
||||
const val KEY_FILENAME = "filename"
|
||||
const val KEY_URI = "uri"
|
||||
const val KEY_GALLERY_INFO = "gallery_info"
|
||||
const val KEY_PAGE = "page"
|
||||
const val KEY_CURRENT_INDEX = "current_index"
|
||||
}
|
||||
|
||||
// Tachiyomi funcs
|
||||
@@ -637,13 +634,11 @@ class ReaderActivity : EhActivity() {
|
||||
* 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.
|
||||
*/
|
||||
@SuppressLint("SetTextI18n")
|
||||
fun onPageSelected(page: ReaderPage) {
|
||||
// Set bottom page number
|
||||
currentPage = page.number
|
||||
|
||||
mCurrentIndex = page.index
|
||||
mGalleryProvider?.putStartPage(mCurrentIndex)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in new issue
Block a user