Skip to content

Commit

Permalink
完成书架的数据导出功能,完成数据格式序列化相关类
Browse files Browse the repository at this point in the history
修复内容页错误的下边距
修复过长章节名称的章节指示器显示
  • Loading branch information
dmzz-yyhyy committed Oct 4, 2024
1 parent 0ae4fd6 commit c79cc16
Show file tree
Hide file tree
Showing 28 changed files with 982 additions and 153 deletions.
4 changes: 2 additions & 2 deletions .idea/deploymentTargetSelector.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,8 @@ import javax.inject.Singleton

@Singleton
class UserDataRepository @Inject constructor(
private val userDataDao: UserDataDao)
{

private val userDataDao: UserDataDao
) {
fun stringUserData(path: String): StringUserData = StringUserData(path, userDataDao)
fun floatUserData(path: String): FloatUserData = FloatUserData(path, userDataDao)
fun booleanUserData(path: String): BooleanUserData = BooleanUserData(path, userDataDao)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,23 @@
package indi.dmzz_yyhyy.lightnovelreader.data.bookshelf

import android.net.Uri
import androidx.work.ExistingWorkPolicy
import androidx.work.OneTimeWorkRequest
import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.WorkManager
import androidx.work.workDataOf
import com.google.gson.JsonSyntaxException
import indi.dmzz_yyhyy.lightnovelreader.data.book.BookInformation
import indi.dmzz_yyhyy.lightnovelreader.data.json.AppUserDataJson
import indi.dmzz_yyhyy.lightnovelreader.data.json.AppUserDataJsonBuilder
import indi.dmzz_yyhyy.lightnovelreader.data.json.toJsonData
import indi.dmzz_yyhyy.lightnovelreader.data.loacltion.room.converter.LocalDataTimeConverter.dateToString
import indi.dmzz_yyhyy.lightnovelreader.data.local.room.converter.ListConverter.intListToString
import indi.dmzz_yyhyy.lightnovelreader.data.local.room.dao.BookshelfDao
import indi.dmzz_yyhyy.lightnovelreader.data.local.room.entity.BookshelfEntity
import indi.dmzz_yyhyy.lightnovelreader.data.web.WebBookDataSource
import indi.dmzz_yyhyy.lightnovelreader.data.work.CacheBookWork
import indi.dmzz_yyhyy.lightnovelreader.data.work.SaveBookshelfWork
import java.time.Instant
import java.time.LocalDateTime
import javax.inject.Inject
Expand All @@ -20,7 +28,8 @@ import kotlinx.coroutines.flow.map
@Singleton
class BookshelfRepository @Inject constructor(
private val bookshelfDao: BookshelfDao,
private val workManager: WorkManager
private val workManager: WorkManager,
private val webBookDataSource: WebBookDataSource
) {
fun getAllBookshelfIds(): List<Int> = bookshelfDao.getAllBookshelfIds()

Expand Down Expand Up @@ -86,7 +95,7 @@ class BookshelfRepository @Inject constructor(
val bookshelf = bookshelfDao.getBookShelf(bookshelfId) ?: return
bookshelfDao.addBookshelfMetadata(
id = bookInformation.id,
lastUpdate = dateToString(bookInformation.lastUpdated) ?: "",
lastUpdate = bookInformation.lastUpdated,
bookshelfIds = listOf(bookshelfId)
)
if (bookshelf.autoCache && bookshelf.allBookIds.contains(bookInformation.id)) {
Expand Down Expand Up @@ -212,4 +221,81 @@ class BookshelfRepository @Inject constructor(
intListToString(bookshelfDao.getBookshelfBookMetadata(bookId)?.bookShelfIds!!)
)
}

fun exportAllBookshelvesJson(): String = AppUserDataJsonBuilder()
.data {
webDataSourceId(webBookDataSource.id)
getAllBookshelfIds()
.mapNotNull { (getBookshelf(it)) }
.map { (it as Bookshelf).toJsonData() }
.forEach (::bookshelf)
getAllBookshelfBooksMetadata()
.map(BookshelfBookMetadata::toJsonData)
.forEach(::bookshelfBookMetaData)
}
.build()
.toJson()

fun exportBookshelvesJson(id: Int): String = AppUserDataJsonBuilder()
.data {
webDataSourceId(webBookDataSource.id)
getBookshelf(id)?.toJsonData()?.let { bookshelf(it) }
getBookshelf(id)?.allBookIds
?.mapNotNull(::getBookshelfBookMetadata)
?.map { BookshelfBookMetadata(id = it.id, lastUpdate = it.lastUpdate, bookShelfIds = listOf(id)) }
?.map(BookshelfBookMetadata::toJsonData)
?.forEach(::bookshelfBookMetaData)
}
.build()
.toJson()

fun saveBookshelfJsonData(bookshelfId: Int, uri: Uri): OneTimeWorkRequest {
val workRequest = OneTimeWorkRequestBuilder<SaveBookshelfWork>()
.setInputData(workDataOf(
"bookshelfId" to bookshelfId,
"uri" to uri.toString(),
))
.build()
workManager.enqueueUniqueWork(
uri.toString(),
ExistingWorkPolicy.KEEP,
workRequest
)
return workRequest
}

fun importBookshelfFromJsonData(stringJson: String): Boolean {
try {
val appUserDataJson = AppUserDataJson.fromJson(stringJson)
val data =
appUserDataJson.data.firstOrNull { it.webDataSourceId == webBookDataSource.id }
?: return false
val bookshelfDataList = data.bookshelf ?: return false
val bookshelfBookMetadataList = data.bookShelfBookMetadata ?: return false
val allBookshelfIds = getAllBookshelfIds()
bookshelfDataList.forEach { bookshelf ->
if (allBookshelfIds.contains(bookshelf.id)) return@forEach
bookshelfDao.createBookshelf(
BookshelfEntity(
id = bookshelf.id,
name = bookshelf.name,
sortType = bookshelf.sortType.key,
autoCache = bookshelf.autoCache,
systemUpdateReminder = bookshelf.systemUpdateReminder,
allBookIds = bookshelf.allBookIds,
pinnedBookIds = bookshelf.pinnedBookIds,
updatedBookIds = bookshelf.updatedBookIds,
)
)
}
bookshelfBookMetadataList.forEach {
bookshelfDao.addBookshelfMetadata(it.id, it.lastUpdate, it.bookShelfIds)
}
}
catch (e: JsonSyntaxException) {
e.printStackTrace()
return false
}
return true
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,8 @@ package indi.dmzz_yyhyy.lightnovelreader.data.bookshelf

enum class BookshelfSortType(val key: String) {
Default("default"),
Latest("latest"),
Latest("latest");
companion object {
fun map(key: String): BookshelfSortType = BookshelfSortType.entries.first { it.key == key }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package indi.dmzz_yyhyy.lightnovelreader.data.json

import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.google.gson.annotations.SerializedName
import indi.dmzz_yyhyy.lightnovelreader.data.bookshelf.BookshelfSortType
import java.time.LocalDateTime

data class AppUserDataJson(
val id: Int? = null,
val data: List<AppUserDataContent>
) {
companion object {
val gson: Gson = GsonBuilder()
.registerTypeAdapter(LocalDateTime::class.java, LocalTimeDataTypeAdapter)
.registerTypeAdapter(BookshelfSortType::class.java, BookshelfSortTypeTypeAdapter)
.create()

fun fromJson(json: String): AppUserDataJson = gson.fromJson(json, AppUserDataJson::class.java)
}

fun toJson(): String = gson.toJson(this)
}

data class AppUserDataContent(
@SerializedName("web_data_source_id")
val webDataSourceId: Int,
@SerializedName("book_user_data")
val bookUserData: List<BookUserData>? = null,
@SerializedName("book_shelf")
val bookshelf: List<BookshelfData>? = null,
@SerializedName("book_shelf_book_metadata")
val bookShelfBookMetadata: List<BookShelfBookMetadataData>? = null,
@SerializedName("user_data")
val userData: List<UserDataData>? = null,
)

class AppUserDataJsonBuilder() {
private var id: Int? = null
private var data: MutableList<AppUserDataContent> = mutableListOf()

fun build(): AppUserDataJson = AppUserDataJson(
id = id,
data = data
)

fun data(data: AppUserDataContentBuilder.() -> Unit): AppUserDataJsonBuilder {
this.data.add(
AppUserDataContentBuilder()
.let {
data.invoke(it)
it.build()
}
)
return this
}
}

class AppUserDataContentBuilder() {
private var webDataSourceId: Int? = null
private var bookUserData: MutableList<BookUserData> = mutableListOf()
private var bookshelf: MutableList<BookshelfData> = mutableListOf()
private var bookShelfBookMetadata: MutableList<BookShelfBookMetadataData> = mutableListOf()
private var userData: MutableList<UserDataData> = mutableListOf()

fun build(): AppUserDataContent {
if (webDataSourceId == null) {
throw NullPointerException("webDataSourceId can not be null")
}
return AppUserDataContent(
webDataSourceId = webDataSourceId!!,
bookUserData = bookUserData.ifEmpty { null },
bookshelf = bookshelf.ifEmpty { null },
bookShelfBookMetadata = bookShelfBookMetadata.ifEmpty { null },
userData = userData.ifEmpty { null },
)
}

fun webDataSourceId(webDataSourceId: Int): AppUserDataContentBuilder {
this.webDataSourceId = webDataSourceId
return this
}

fun bookUserData(bookUserData: BookUserData): AppUserDataContentBuilder {
this.bookUserData.add(bookUserData)
return this
}

fun bookshelf(bookshelf: BookshelfData): AppUserDataContentBuilder {
this.bookshelf.add(bookshelf)
return this
}

fun bookshelfBookMetaData(bookshelfBookMetadata: BookShelfBookMetadataData): AppUserDataContentBuilder {
this.bookShelfBookMetadata.add(bookshelfBookMetadata)
return this
}

fun userData(userData: UserDataData): AppUserDataContentBuilder {
this.userData.add(userData)
return this
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package indi.dmzz_yyhyy.lightnovelreader.data.json

import com.google.gson.annotations.SerializedName
import indi.dmzz_yyhyy.lightnovelreader.data.bookshelf.BookshelfBookMetadata
import java.time.LocalDateTime

data class BookShelfBookMetadataData(
val id: Int,
@SerializedName("last_update")
val lastUpdate: LocalDateTime,
@SerializedName("book_shelf_ids")
val bookShelfIds: List<Int>,
)

fun BookshelfBookMetadata.toJsonData() =
BookShelfBookMetadataData(
id = id,
lastUpdate = lastUpdate,
bookShelfIds = bookShelfIds,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package indi.dmzz_yyhyy.lightnovelreader.data.json

import com.google.gson.annotations.SerializedName
import java.time.LocalDateTime

data class BookUserData(
val id: Int,
@SerializedName("last_read_time")
val lastReadTime: LocalDateTime,
@SerializedName("total_read_time")
val totalReadTime: Int,
@SerializedName("reading_progress")
val readingProgress: Float,
@SerializedName("last_read_chapter_id")
val lastReadChapterId: Int,
@SerializedName("last_read_chapter_title")
val lastReadChapterTitle: String,
@SerializedName("last_read_chapter_progress")
val lastReadChapterProgress: Float,
@SerializedName("read_completed_chapter_ids")
val readCompletedChapterIds: List<Int>,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package indi.dmzz_yyhyy.lightnovelreader.data.json

import com.google.gson.annotations.SerializedName
import indi.dmzz_yyhyy.lightnovelreader.data.bookshelf.Bookshelf
import indi.dmzz_yyhyy.lightnovelreader.data.bookshelf.BookshelfSortType

data class BookshelfData(
val id: Int,
val name: String,
@SerializedName("sort_type")
val sortType: BookshelfSortType,
@SerializedName("auto_cache")
val autoCache: Boolean,
@SerializedName("system_update_reminder")
val systemUpdateReminder: Boolean,
@SerializedName("all_book_ids")
val allBookIds: List<Int>,
@SerializedName("pinned_book_ids")
val pinnedBookIds: List<Int>,
@SerializedName("updatedBookIds")
val updatedBookIds: List<Int>,
)

fun Bookshelf.toJsonData(): BookshelfData =
BookshelfData(
id = id,
name = name,
sortType = sortType,
autoCache = autoCache,
systemUpdateReminder = systemUpdateReminder,
allBookIds = allBookIds,
pinnedBookIds = pinnedBookIds,
updatedBookIds = updatedBookIds,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package indi.dmzz_yyhyy.lightnovelreader.data.json

import com.google.gson.TypeAdapter
import com.google.gson.stream.JsonReader
import com.google.gson.stream.JsonWriter
import indi.dmzz_yyhyy.lightnovelreader.data.bookshelf.BookshelfSortType

object BookshelfSortTypeTypeAdapter : TypeAdapter<BookshelfSortType>() {
override fun write(out: JsonWriter?, value: BookshelfSortType?) {
out?.value(value?.key)
}

override fun read(`in`: JsonReader?): BookshelfSortType {
return `in`?.nextString()?.let { BookshelfSortType.map(it) } ?: BookshelfSortType.Default
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package indi.dmzz_yyhyy.lightnovelreader.data.json

import com.google.gson.TypeAdapter
import com.google.gson.stream.JsonReader
import com.google.gson.stream.JsonWriter
import java.time.LocalDateTime

object LocalTimeDataTypeAdapter : TypeAdapter<LocalDateTime>() {
override fun write(out: JsonWriter?, value: LocalDateTime?) {
out?.value(value.toString())
}

override fun read(`in`: JsonReader?): LocalDateTime {
return LocalDateTime.parse(`in`?.nextString())
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package indi.dmzz_yyhyy.lightnovelreader.data.json

data class UserDataData(
val path: String,
val group: String,
val type: String,
val value: String
)
Loading

0 comments on commit c79cc16

Please sign in to comment.