Properly handle update / insert and delete in the adventure database.
This commit is contained in:
parent
7400799efd
commit
2b03ffd1ac
7 changed files with 230 additions and 211 deletions
|
|
@ -2,7 +2,7 @@
|
|||
"formatVersion": 1,
|
||||
"database": {
|
||||
"version": 2,
|
||||
"identityHash": "95cb578b3b61a022ab4dda676d2e4645",
|
||||
"identityHash": "f1496aa4aa95e44822a7b0650065c53e",
|
||||
"entities": [
|
||||
{
|
||||
"tableName": "lexicon",
|
||||
|
|
@ -353,7 +353,7 @@
|
|||
},
|
||||
{
|
||||
"tableName": "AdventureStory",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`title` TEXT NOT NULL, `category` TEXT, `background` TEXT, `revision` INTEGER NOT NULL, `index` INTEGER NOT NULL, `documentId` TEXT NOT NULL, PRIMARY KEY(`title`, `documentId`), FOREIGN KEY(`documentId`) REFERENCES `AdventureBooks`(`documentId`) ON UPDATE NO ACTION ON DELETE NO ACTION )",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`title` TEXT NOT NULL, `category` TEXT, `background` TEXT, `revision` INTEGER NOT NULL, `index` INTEGER NOT NULL, `documentId` TEXT NOT NULL, PRIMARY KEY(`title`, `documentId`), FOREIGN KEY(`documentId`) REFERENCES `AdventureBooks`(`documentId`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "title",
|
||||
|
|
@ -403,7 +403,7 @@
|
|||
"foreignKeys": [
|
||||
{
|
||||
"table": "AdventureBooks",
|
||||
"onDelete": "NO ACTION",
|
||||
"onDelete": "CASCADE",
|
||||
"onUpdate": "NO ACTION",
|
||||
"columns": [
|
||||
"documentId"
|
||||
|
|
@ -478,7 +478,7 @@
|
|||
"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, '95cb578b3b61a022ab4dda676d2e4645')"
|
||||
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'f1496aa4aa95e44822a7b0650065c53e')"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -6,6 +6,7 @@ import androidx.room.Insert
|
|||
import androidx.room.OnConflictStrategy
|
||||
import androidx.room.Query
|
||||
import androidx.room.Transaction
|
||||
import androidx.room.Update
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
@Dao
|
||||
|
|
@ -21,64 +22,70 @@ interface AdventureDao {
|
|||
fun getStoryLinesFlow(): Flow<List<AdventureLineDbo>>
|
||||
|
||||
@Query("SELECT * from ${AdventureBookDbo.TABLE}")
|
||||
fun findBooks(): List<AdventureBookDbo>
|
||||
fun fetchAdventureBooks(): List<AdventureBookDbo>
|
||||
|
||||
@Query("SELECT * from ${AdventureStoryDbo.TABLE}")
|
||||
fun findStories(): List<AdventureStoryDbo>
|
||||
fun fetchAdventureStories(): List<AdventureStoryDbo>
|
||||
|
||||
@Query("SELECT * from ${AdventureStoryDbo.TABLE} where documentId = :documentId")
|
||||
fun findStories(documentId: String): List<AdventureStoryDbo>
|
||||
fun fetchAdventureStories(documentId: String): List<AdventureStoryDbo>
|
||||
|
||||
@Query("SELECT * from ${AdventureStoryDbo.TABLE} where documentId = :documentId AND title = :title")
|
||||
fun findStory(documentId: String, title: String): AdventureStoryDbo?
|
||||
fun fetchAdventureStory(documentId: String, title: String): AdventureStoryDbo?
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.IGNORE)
|
||||
@Query("SELECT * from ${AdventureLineDbo.TABLE} where documentId = :documentId AND title = :storyTitle")
|
||||
fun fetchAdventureLine(documentId: String, storyTitle: String): List<AdventureLineDbo>
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
fun insertBook(book: AdventureBookDbo)
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
fun insertStory(story: AdventureStoryDbo)
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
fun insertLines(line: AdventureLineDbo)
|
||||
@Update
|
||||
fun updateBook(book: AdventureBookDbo)
|
||||
|
||||
@Delete(entity = AdventureBookDbo::class)
|
||||
fun deleteBook(id: AdventureBookDbo.BookId)
|
||||
|
||||
@Delete(entity = AdventureStoryDbo::class)
|
||||
fun deleteStory(id: AdventureBookDbo.BookId)
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
fun insertStory(story: AdventureStoryDbo)
|
||||
|
||||
@Update
|
||||
fun updateStory(story: AdventureStoryDbo)
|
||||
|
||||
@Delete(entity = AdventureStoryDbo::class)
|
||||
fun deleteStory(id: AdventureStoryDbo.StoryId)
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
fun insertLine(line: AdventureLineDbo)
|
||||
|
||||
@Update
|
||||
fun updateLine(line: AdventureLineDbo)
|
||||
|
||||
@Delete(entity = AdventureLineDbo::class)
|
||||
fun deleteLines(id: AdventureLineDbo.LineId)
|
||||
|
||||
@Transaction
|
||||
fun update(
|
||||
books: List<AdventureBookDbo>,
|
||||
booksToInsert: List<AdventureBookDbo>,
|
||||
booksToUpdate: List<AdventureBookDbo>,
|
||||
booksToRemove: List<AdventureBookDbo.BookId>,
|
||||
stories: List<AdventureStoryDbo>,
|
||||
storiesToInsert: List<AdventureStoryDbo>,
|
||||
storiesToUpdate: List<AdventureStoryDbo>,
|
||||
storiesToRemove: List<AdventureStoryDbo.StoryId>,
|
||||
lines: List<AdventureLineDbo>,
|
||||
linesToInsert: List<AdventureLineDbo>,
|
||||
linesToUpdate: List<AdventureLineDbo>,
|
||||
linesToRemove: List<AdventureLineDbo.LineId>,
|
||||
) {
|
||||
// First clean the database from old unused data.
|
||||
booksToRemove.forEach {
|
||||
deleteStory(id = it)
|
||||
deleteBook(id = it)
|
||||
}
|
||||
// StoryLineDbo are remove with cascading foreign key from StoryBdo.
|
||||
storiesToRemove.forEach { deleteStory(id = it) }
|
||||
// First remove the stuff
|
||||
linesToRemove.forEach { deleteLines(id = it) }
|
||||
|
||||
books.forEach { book ->
|
||||
insertBook(book = book)
|
||||
}
|
||||
stories.forEach { story ->
|
||||
insertStory(story = story)
|
||||
}
|
||||
lines.forEach { line ->
|
||||
insertLines(line = line)
|
||||
}
|
||||
storiesToRemove.forEach { deleteStory(id = it) }
|
||||
booksToRemove.forEach { deleteBook(id = it) }
|
||||
// then insert the stuff
|
||||
booksToInsert.forEach { insertBook(book = it) }
|
||||
storiesToInsert.forEach { insertStory(story = it) }
|
||||
linesToInsert.forEach { insertLine(line = it) }
|
||||
// and update the stuff
|
||||
booksToUpdate.forEach { updateBook(book = it) }
|
||||
storiesToUpdate.forEach { updateStory(story = it) }
|
||||
linesToUpdate.forEach { updateLine(line = it) }
|
||||
}
|
||||
}
|
||||
|
|
@ -44,7 +44,7 @@ data class AdventureBookDbo(
|
|||
entity = AdventureBookDbo::class,
|
||||
parentColumns = [AdventureBookDbo.DOCUMENT_ID],
|
||||
childColumns = [AdventureStoryDbo.FK_DOCUMENT_ID],
|
||||
onDelete = ForeignKey.NO_ACTION,
|
||||
onDelete = ForeignKey.CASCADE,
|
||||
)
|
||||
],
|
||||
)
|
||||
|
|
|
|||
|
|
@ -5,9 +5,6 @@ import com.pixelized.rplexicon.data.database.adventure.AdventureBookDbo
|
|||
import com.pixelized.rplexicon.data.database.adventure.AdventureLineDbo
|
||||
import com.pixelized.rplexicon.data.database.adventure.AdventureStoryDbo
|
||||
import com.pixelized.rplexicon.data.model.adventure.Adventure
|
||||
import com.pixelized.rplexicon.data.model.adventure.AdventureBook
|
||||
import com.pixelized.rplexicon.data.model.adventure.AdventureLine
|
||||
import com.pixelized.rplexicon.data.model.adventure.AdventureStory
|
||||
import com.pixelized.rplexicon.data.parser.adventure.AdventureBookParser
|
||||
import com.pixelized.rplexicon.data.parser.adventure.AdventureStoryLineParser
|
||||
import com.pixelized.rplexicon.data.parser.adventure.AdventureStoryParser
|
||||
|
|
@ -17,24 +14,30 @@ import com.pixelized.rplexicon.utilitary.exceptions.IncompatibleSheetStructure
|
|||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.NonCancellable
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.withContext
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
import kotlin.math.min
|
||||
|
||||
@Singleton
|
||||
class AdventureRepository @Inject constructor(
|
||||
private val googleRepository: GoogleSheetServiceRepository,
|
||||
private val database: CompanionDatabase,
|
||||
private val adventureBookParser: AdventureBookParser,
|
||||
private val adventureStoryParser: AdventureStoryParser,
|
||||
private val adventureStoryLineParser: AdventureStoryLineParser,
|
||||
private val adventureDboFactory: AdventureDboFactory,
|
||||
companionDatabase: CompanionDatabase,
|
||||
) {
|
||||
private val adventures = database.adventureDao().let { database ->
|
||||
private val database = companionDatabase.adventureDao()
|
||||
private val service = Service()
|
||||
|
||||
private val adventures = database.let { database ->
|
||||
combine(
|
||||
database.getBooksFlow(),
|
||||
database.getStoriesFlow(),
|
||||
|
|
@ -56,9 +59,7 @@ class AdventureRepository @Inject constructor(
|
|||
return adventures
|
||||
}
|
||||
|
||||
fun storyFlow(
|
||||
bookTitle: String,
|
||||
): Flow<List<Adventure>> {
|
||||
fun storyFlow(bookTitle: String): Flow<List<Adventure>> {
|
||||
return adventures.map { adventures ->
|
||||
adventures.filter { adventure ->
|
||||
adventure.bookTitle == bookTitle
|
||||
|
|
@ -66,10 +67,7 @@ class AdventureRepository @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
fun adventureFlow(
|
||||
documentId: String,
|
||||
adventureTitle: String,
|
||||
): Flow<Adventure?> {
|
||||
fun adventureFlow(documentId: String, adventureTitle: String): Flow<Adventure?> {
|
||||
return adventures.map { adventures ->
|
||||
adventures.firstOrNull { adventure ->
|
||||
adventure.documentId == documentId && adventure.storyTitle == adventureTitle
|
||||
|
|
@ -78,188 +76,201 @@ class AdventureRepository @Inject constructor(
|
|||
}
|
||||
|
||||
@Throws(IncompatibleSheetStructure::class, Exception::class)
|
||||
suspend fun fetchBooks() {
|
||||
val database = database.adventureDao()
|
||||
suspend fun fetchBooks() = update {
|
||||
fetchAndCompareBooks()
|
||||
|
||||
val booksToRemove = database.findBooks()
|
||||
.map { it.id }
|
||||
.toMutableList()
|
||||
|
||||
val books: List<AdventureBookDbo> = fetchAdventureBooks().map { book ->
|
||||
// convert to BookDbo.
|
||||
adventureDboFactory.convertToDbo(book = book).also {
|
||||
// Flag this book to not delete it
|
||||
booksToRemove.remove(element = it.id)
|
||||
}
|
||||
(booksToInsert + booksToUpdate).forEach { book ->
|
||||
fetchAndCompareStories(documentId = book.documentId)
|
||||
}
|
||||
|
||||
val storiesToRemove = books
|
||||
.flatMap { book -> database.findStories(documentId = book.documentId) }
|
||||
.map { it.id }
|
||||
.toMutableList()
|
||||
|
||||
val stories: List<AdventureStoryDbo> = books.flatMap { book ->
|
||||
fetchAdventureStory(documentId = book.documentId)
|
||||
.mapIndexed { index, story ->
|
||||
// convert to StoryBdo
|
||||
val update = adventureDboFactory.convertToDbo(
|
||||
story = story,
|
||||
index = index,
|
||||
documentId = book.documentId,
|
||||
).also {
|
||||
// Flag this story to not delete it
|
||||
storiesToRemove.remove(element = it.id)
|
||||
}
|
||||
val cache = database.findStory(
|
||||
documentId = book.documentId,
|
||||
title = story.title,
|
||||
)
|
||||
when {
|
||||
cache == null -> update
|
||||
cache.revision < update.revision -> update
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
.mapNotNull { it }
|
||||
(storiesToInsert + storiesToUpdate).forEach { story ->
|
||||
fetchAndCompareLines(documentId = story.documentId, storyTitle = story.title)
|
||||
}
|
||||
|
||||
val lines: List<AdventureLineDbo> = stories.flatMap { story ->
|
||||
fetchAdventureLine(
|
||||
documentId = story.documentId,
|
||||
storyTitle = story.title,
|
||||
).mapIndexed { index, line ->
|
||||
adventureDboFactory.convertToDbo(
|
||||
adventureLine = line,
|
||||
index = index,
|
||||
documentId = story.documentId,
|
||||
storyTitle = story.title,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
database.update(
|
||||
booksToRemove = booksToRemove,
|
||||
storiesToRemove = storiesToRemove,
|
||||
linesToRemove = lines.groupBy { it.id }.keys.toList(),
|
||||
books = books,
|
||||
stories = stories,
|
||||
lines = lines,
|
||||
)
|
||||
}
|
||||
|
||||
@Throws(IncompatibleSheetStructure::class, Exception::class)
|
||||
suspend fun fetchStories(
|
||||
documentId: String,
|
||||
) {
|
||||
val database = database.adventureDao()
|
||||
) = update {
|
||||
fetchAndCompareStories(documentId = documentId)
|
||||
|
||||
val storiesToRemove = database.findStories(documentId = documentId)
|
||||
.map { it.id }
|
||||
.toMutableList()
|
||||
|
||||
val stories: List<AdventureStoryDbo> = fetchAdventureStory(documentId = documentId)
|
||||
.mapIndexed { index, story ->
|
||||
// convert to StoryBdo
|
||||
val update = adventureDboFactory.convertToDbo(
|
||||
story = story,
|
||||
index = index,
|
||||
documentId = documentId,
|
||||
).also {
|
||||
// Flag this story to not delete it
|
||||
storiesToRemove.remove(element = it.id)
|
||||
}
|
||||
val cache = database.findStory(
|
||||
documentId = documentId,
|
||||
title = story.title,
|
||||
)
|
||||
when {
|
||||
cache == null -> update
|
||||
cache.revision < update.revision -> update
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
.mapNotNull { it }
|
||||
|
||||
val lines: List<AdventureLineDbo> = stories.flatMap { story ->
|
||||
fetchAdventureLine(
|
||||
documentId = story.documentId,
|
||||
storyTitle = story.title,
|
||||
).mapIndexed { index, line ->
|
||||
adventureDboFactory.convertToDbo(
|
||||
adventureLine = line,
|
||||
index = index,
|
||||
documentId = story.documentId,
|
||||
storyTitle = story.title,
|
||||
)
|
||||
}
|
||||
(storiesToInsert + storiesToUpdate).forEach { story ->
|
||||
fetchAndCompareLines(documentId = story.documentId, storyTitle = story.title)
|
||||
}
|
||||
|
||||
database.update(
|
||||
booksToRemove = emptyList(),
|
||||
storiesToRemove = storiesToRemove,
|
||||
linesToRemove = lines.groupBy { it.id }.keys.toList(),
|
||||
books = emptyList(),
|
||||
stories = stories,
|
||||
lines = lines,
|
||||
)
|
||||
}
|
||||
|
||||
@Throws(IncompatibleSheetStructure::class, Exception::class)
|
||||
suspend fun fetchAdventure(
|
||||
documentId: String,
|
||||
storyTitle: String,
|
||||
) {
|
||||
val database = database.adventureDao()
|
||||
|
||||
val lines = fetchAdventureLine(
|
||||
) = update {
|
||||
// specific case for adventure fetching, need to update the story too as the background is stored there.
|
||||
service.fetchAdventureStories(
|
||||
documentId = documentId,
|
||||
storyTitle = storyTitle,
|
||||
).mapIndexed { index, line ->
|
||||
adventureDboFactory.convertToDbo(
|
||||
adventureLine = line,
|
||||
index = index,
|
||||
documentId = documentId,
|
||||
storyTitle = storyTitle,
|
||||
)
|
||||
).firstOrNull { story ->
|
||||
story.documentId == documentId && story.title == storyTitle
|
||||
}?.let { story ->
|
||||
storiesToUpdate.add(story)
|
||||
}
|
||||
|
||||
fetchAndCompareLines(documentId = documentId, storyTitle = storyTitle)
|
||||
}
|
||||
|
||||
private suspend fun DatabaseUpdateScope.fetchAndCompareBooks() {
|
||||
val cache = database.fetchAdventureBooks()
|
||||
val update = service.fetchAdventureBooks()
|
||||
|
||||
val toRemove = cache.map { it.id }.toMutableList()
|
||||
val toInsert = mutableListOf<AdventureBookDbo>()
|
||||
val toUpdate = mutableListOf<AdventureBookDbo>()
|
||||
|
||||
update.forEach { item ->
|
||||
when (toRemove.remove(item.id)) {
|
||||
true -> toUpdate.add(item)
|
||||
else -> toInsert.add(item)
|
||||
}
|
||||
}
|
||||
|
||||
booksToInsert.addAll(elements = toInsert)
|
||||
booksToUpdate.addAll(elements = toUpdate)
|
||||
booksToRemove.addAll(elements = toRemove)
|
||||
}
|
||||
|
||||
private suspend fun DatabaseUpdateScope.fetchAndCompareStories(
|
||||
documentId: String,
|
||||
) {
|
||||
val cache = database.fetchAdventureStories(
|
||||
documentId = documentId,
|
||||
).associateBy {
|
||||
it.id
|
||||
}
|
||||
val update = service.fetchAdventureStories(
|
||||
documentId = documentId,
|
||||
)
|
||||
|
||||
val toRemove = cache.keys.toMutableList()
|
||||
val toInsert = mutableListOf<AdventureStoryDbo>()
|
||||
val toUpdate = mutableListOf<AdventureStoryDbo>()
|
||||
|
||||
update.forEach { item ->
|
||||
when (toRemove.remove(item.id)) {
|
||||
true -> if ((cache[item.id]?.revision ?: 0) < item.revision) toUpdate.add(item)
|
||||
else -> toInsert.add(item)
|
||||
}
|
||||
}
|
||||
|
||||
storiesToInsert.addAll(elements = toInsert)
|
||||
storiesToUpdate.addAll(elements = toUpdate)
|
||||
storiesToRemove.addAll(elements = toRemove)
|
||||
}
|
||||
|
||||
private suspend fun DatabaseUpdateScope.fetchAndCompareLines(
|
||||
documentId: String,
|
||||
storyTitle: String,
|
||||
) {
|
||||
val cache = database.fetchAdventureLine(
|
||||
documentId = documentId,
|
||||
storyTitle = storyTitle,
|
||||
)
|
||||
val update = service.fetchAdventureLine(
|
||||
documentId = documentId,
|
||||
storyTitle = storyTitle,
|
||||
)
|
||||
// if cache is smaller than the update we need to insert
|
||||
if (cache.size < update.size) {
|
||||
(cache.size until update.size).forEach {
|
||||
linesToInsert.add(update[it])
|
||||
}
|
||||
}
|
||||
// if cache is bigger than the update we need to delete
|
||||
if (update.size < cache.size) {
|
||||
(update.size until cache.size).forEach {
|
||||
linesToRemove.add(cache[it].id)
|
||||
}
|
||||
}
|
||||
// then we update the rest
|
||||
(0 until min(cache.size, update.size)).forEach {
|
||||
linesToUpdate.add(update[it])
|
||||
}
|
||||
}
|
||||
|
||||
private suspend inline fun update(
|
||||
crossinline lambda: suspend DatabaseUpdateScope.() -> Unit,
|
||||
) = withContext(Dispatchers.IO + NonCancellable) {
|
||||
val update = DatabaseUpdateScope()
|
||||
|
||||
lambda.invoke(update)
|
||||
|
||||
database.update(
|
||||
booksToRemove = emptyList(),
|
||||
storiesToRemove = emptyList(),
|
||||
linesToRemove = emptyList(),
|
||||
books = emptyList(),
|
||||
stories = emptyList(),
|
||||
lines = lines,
|
||||
booksToInsert = update.booksToInsert,
|
||||
booksToUpdate = update.booksToUpdate,
|
||||
booksToRemove = update.booksToRemove,
|
||||
storiesToInsert = update.storiesToInsert,
|
||||
storiesToUpdate = update.storiesToUpdate,
|
||||
storiesToRemove = update.storiesToRemove,
|
||||
linesToInsert = update.linesToInsert,
|
||||
linesToUpdate = update.linesToUpdate,
|
||||
linesToRemove = update.linesToRemove,
|
||||
)
|
||||
}
|
||||
|
||||
@Throws(IncompatibleSheetStructure::class, Exception::class)
|
||||
private suspend fun fetchAdventureBooks(): List<AdventureBook> {
|
||||
return googleRepository.fetch { sheet ->
|
||||
val request = sheet.get(Adventures.ID, Adventures.ADVENTURES)
|
||||
adventureBookParser.parse(sheet = request.execute())
|
||||
}
|
||||
}
|
||||
private data class DatabaseUpdateScope(
|
||||
val booksToInsert: MutableList<AdventureBookDbo> = mutableListOf(),
|
||||
val booksToUpdate: MutableList<AdventureBookDbo> = mutableListOf(),
|
||||
val booksToRemove: MutableList<AdventureBookDbo.BookId> = mutableListOf(),
|
||||
val storiesToInsert: MutableList<AdventureStoryDbo> = mutableListOf(),
|
||||
val storiesToUpdate: MutableList<AdventureStoryDbo> = mutableListOf(),
|
||||
val storiesToRemove: MutableList<AdventureStoryDbo.StoryId> = mutableListOf(),
|
||||
val linesToInsert: MutableList<AdventureLineDbo> = mutableListOf(),
|
||||
val linesToUpdate: MutableList<AdventureLineDbo> = mutableListOf(),
|
||||
val linesToRemove: MutableList<AdventureLineDbo.LineId> = mutableListOf(),
|
||||
)
|
||||
|
||||
@Throws(IncompatibleSheetStructure::class, Exception::class)
|
||||
private suspend fun fetchAdventureStory(documentId: String): List<AdventureStory> {
|
||||
return googleRepository.fetch { sheet ->
|
||||
val request = sheet.get(documentId, Adventures.ADVENTURES)
|
||||
adventureStoryParser.parse(sheet = request.execute())
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun fetchAdventureLine(
|
||||
documentId: String,
|
||||
storyTitle: String,
|
||||
): List<AdventureLine> {
|
||||
return try {
|
||||
googleRepository.fetch { sheet ->
|
||||
val request = sheet.get(documentId, storyTitle)
|
||||
adventureStoryLineParser.parse(sheet = request.execute())
|
||||
private inner class Service {
|
||||
@Throws(IncompatibleSheetStructure::class, Exception::class)
|
||||
suspend fun fetchAdventureBooks(): List<AdventureBookDbo> {
|
||||
return googleRepository.fetch { sheet ->
|
||||
val request = sheet.get(Adventures.ID, Adventures.ADVENTURES)
|
||||
adventureBookParser.parse(sheet = request.execute())
|
||||
}.map { book ->
|
||||
adventureDboFactory.convertToDbo(book = book)
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(IncompatibleSheetStructure::class, Exception::class)
|
||||
suspend fun fetchAdventureStories(documentId: String): List<AdventureStoryDbo> {
|
||||
return googleRepository.fetch { sheet ->
|
||||
val request = sheet.get(documentId, Adventures.ADVENTURES)
|
||||
adventureStoryParser.parse(sheet = request.execute())
|
||||
}.mapIndexed { index, story ->
|
||||
adventureDboFactory.convertToDbo(
|
||||
story = story,
|
||||
index = index,
|
||||
documentId = documentId,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(Exception::class)
|
||||
suspend fun fetchAdventureLine(
|
||||
documentId: String,
|
||||
storyTitle: String,
|
||||
): List<AdventureLineDbo> {
|
||||
return try {
|
||||
googleRepository.fetch { sheet ->
|
||||
val request = sheet.get(documentId, storyTitle)
|
||||
adventureStoryLineParser.parse(sheet = request.execute())
|
||||
}
|
||||
} catch (exception: Exception) {
|
||||
emptyList()
|
||||
}.mapIndexed { index, line ->
|
||||
adventureDboFactory.convertToDbo(
|
||||
adventureLine = line,
|
||||
index = index,
|
||||
documentId = documentId,
|
||||
storyTitle = storyTitle,
|
||||
)
|
||||
}
|
||||
} catch (exception: Exception) {
|
||||
emptyList()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -21,8 +21,8 @@ import androidx.compose.ui.layout.ContentScale
|
|||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.pixelized.rplexicon.ui.composable.images.AsyncImage
|
||||
import com.pixelized.rplexicon.ui.composable.images.BackgroundImage
|
||||
import com.pixelized.rplexicon.ui.composable.images.rememberBackgroundGradient
|
||||
import com.pixelized.rplexicon.ui.theme.LexiconTheme
|
||||
import com.pixelized.rplexicon.utilitary.annotateWithDropCap
|
||||
import com.pixelized.rplexicon.utilitary.extentions.lexicon
|
||||
|
|
@ -53,6 +53,7 @@ fun AdventureBook(
|
|||
.matchParentSize()
|
||||
.align(alignment = Alignment.TopCenter),
|
||||
colorFilter = null,
|
||||
background = rememberBackgroundGradient(0.2f, 1.0f),
|
||||
contentScale = ContentScale.FillWidth,
|
||||
alignment = Alignment.TopCenter,
|
||||
model = item.bookIcon,
|
||||
|
|
|
|||
|
|
@ -122,7 +122,10 @@ private fun AdventureListContent(
|
|||
horizontalArrangement = Arrangement.spacedBy(space = 8.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(space = 8.dp),
|
||||
) {
|
||||
items(items = items.value) {
|
||||
items(
|
||||
items = items.value,
|
||||
key = { it.documentId },
|
||||
) {
|
||||
AdventureBook(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
|
|
|
|||
|
|
@ -194,10 +194,7 @@ private fun AdventureDetailContent(
|
|||
style = MaterialTheme.lexicon.typography.base.titleLarge,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
maxLines = 1,
|
||||
text = annotateMajWithDropCap(
|
||||
text = title.value ?: "",
|
||||
style = MaterialTheme.lexicon.typography.dropCap.titleLarge
|
||||
),
|
||||
text = title.value ?: "",
|
||||
)
|
||||
},
|
||||
actions = {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue