feat(store): set up a preliminary implementation for newest posts

This commit is contained in:
Harsh Shandilya 2023-08-03 18:22:22 +05:30 committed by GitHub
parent 14007c6e8f
commit 45701f414b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 165 additions and 12 deletions

View file

@ -19,8 +19,13 @@ anvil { generateDaggerFactories.set(true) }
dependencies {
api(projects.database)
api(projects.model)
api(projects.core)
implementation(projects.api)
implementation(libs.dagger)
implementation(libs.javax.inject)
implementation(libs.kotlinx.atomicfu)
implementation(libs.kotlinx.coroutines.core)
implementation(libs.sqldelight.extensions.coroutines)
implementation(libs.store5)
}

4
store/lint-baseline.xml Normal file
View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<issues format="6" by="lint 8.2.0-alpha15" type="baseline" client="gradle" dependencies="true" name="AGP (8.2.0-alpha15)" variant="all" version="8.2.0-alpha15">
</issues>

View file

@ -1,4 +1,9 @@
<?xml version="1.0" encoding="utf-8" ?>
<!--
~ Copyright © 2021-2023 Harsh Shandilya.
~ Use of this source code is governed by an MIT-style
~ license that can be found in the LICENSE file or at
~ https://opensource.org/licenses/MIT.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />

View file

@ -0,0 +1,68 @@
/*
* Copyright © 2023 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/
package dev.msfjarvis.claw.store
import app.cash.sqldelight.coroutines.asFlow
import app.cash.sqldelight.coroutines.mapToList
import com.slack.eithernet.ApiResult
import dev.msfjarvis.claw.api.LobstersApi
import dev.msfjarvis.claw.core.injection.DatabaseDispatcher
import dev.msfjarvis.claw.core.injection.IODispatcher
import dev.msfjarvis.claw.database.LobstersDatabase
import dev.msfjarvis.claw.database.local.CachedNewestPost
import dev.msfjarvis.claw.model.LobstersPost
import dev.msfjarvis.claw.store.utils.toCachedNewest
import java.io.IOException
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.withContext
import org.mobilenativefoundation.store.store5.Fetcher
import org.mobilenativefoundation.store.store5.SourceOfTruth
import org.mobilenativefoundation.store.store5.Store
import org.mobilenativefoundation.store.store5.StoreBuilder
class NewestPostsStore
@Inject
constructor(
private val api: LobstersApi,
private val database: LobstersDatabase,
@IODispatcher private val ioDispatcher: CoroutineDispatcher,
@DatabaseDispatcher private val dbDispatcher: CoroutineDispatcher,
) :
Store<Int, List<CachedNewestPost>> by StoreBuilder.from<
Int, List<LobstersPost>, List<CachedNewestPost>
>(
fetcher =
Fetcher.of { key ->
withContext(ioDispatcher) {
when (val result = api.getNewestPosts(key)) {
is ApiResult.Success -> result.value
is ApiResult.Failure.NetworkFailure -> throw result.error
is ApiResult.Failure.UnknownFailure -> throw result.error
is ApiResult.Failure.HttpFailure,
is ApiResult.Failure.ApiFailure ->
throw IOException("API returned an invalid response")
}
}
},
sourceOfTruth =
SourceOfTruth.of(
reader = { page ->
database.cachedNewestPostQueries.getPage(page).asFlow().mapToList(dbDispatcher)
},
writer = { page, items ->
database.transaction {
items
.map { it.toCachedNewest(page) }
.forEach { database.cachedNewestPostQueries.insertPost(it) }
}
},
delete = { page -> database.cachedNewestPostQueries.clearPage(page) },
deleteAll = { database.cachedNewestPostQueries.deleteAll() },
),
)
.build()

View file

@ -0,0 +1,23 @@
/*
* Copyright © 2023 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/
package dev.msfjarvis.claw.store.utils
import dev.msfjarvis.claw.database.local.CachedNewestPost
import dev.msfjarvis.claw.model.LobstersPost
internal fun LobstersPost.toCachedNewest(page: Int): CachedNewestPost {
return CachedNewestPost(
pageNumber = page,
shortId = shortId,
title = title,
url = url,
description = description,
commentCount = commentCount,
commentsUrl = commentsUrl,
tags = tags,
)
}