feat(cache): Cache users

This commit is contained in:
sweetbread 2024-03-28 00:03:48 +03:00 committed by Sweetbread
parent dd88d4a81a
commit 172f997af6
8 changed files with 161 additions and 13 deletions

View File

@ -5,7 +5,7 @@ plugins {
alias(libs.plugins.androidApplication)
alias(libs.plugins.jetbrainsKotlinAndroid)
id("com.google.android.libraries.mapsplatform.secrets-gradle-plugin")
id("com.google.devtools.ksp")
}
secrets {
@ -110,4 +110,8 @@ dependencies {
implementation(libs.kefirbb)
implementation(libs.acra.http)
implementation(libs.androidx.room.runtime)
implementation(libs.androidx.room.ktx)
ksp(libs.androidx.room.compiler)
}

View File

@ -1,13 +1,18 @@
package ru.sweetbread.unn
import android.util.Log
import io.ktor.client.request.forms.submitForm
import io.ktor.client.request.get
import io.ktor.client.request.header
import io.ktor.client.request.parameter
import io.ktor.client.statement.bodyAsText
import io.ktor.http.parameters
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import org.json.JSONArray
import org.json.JSONObject
import ru.sweetbread.unn.db.cacheUser
import ru.sweetbread.unn.db.loadUserByBitrixId
import ru.sweetbread.unn.ui.layout.LoginData
import ru.sweetbread.unn.ui.layout.client
import java.time.LocalDate
@ -28,7 +33,8 @@ enum class Type(val s: String) {
Student("student"),
Group("group"),
Lecturer("lecturer"),
Auditorium("auditorium")
Auditorium("auditorium"),
Employee("employee")
}
enum class LecturerRank(val id: Int) {
@ -94,7 +100,7 @@ class User(
val nameEn: String,
val isMale: Boolean,
val birthday: LocalDate,
val avatar: ImageSet
val avatar: AvatarSet
)
class Post(
@ -107,7 +113,7 @@ class Post(
val content: String
)
class ImageSet(
class AvatarSet(
val original: String,
val thumbnail: String,
val small: String
@ -177,7 +183,7 @@ private suspend fun getMyself(login: String) {
DateTimeFormatter.ofPattern("yyyy-MM-dd")
),
avatar = user.getJSONObject("photo").let {
ImageSet(
AvatarSet(
it.getString("orig"),
it.getString("thumbnail"),
it.getString("small"),
@ -304,10 +310,22 @@ suspend fun getBlogposts(): ArrayList<Post> {
}
suspend fun getUserByBitrixId(id: Int): User {
var user: User?
withContext(Dispatchers.IO) {
user = loadUserByBitrixId(id)
}
user?.let { return user as User }
val userId = JSONObject(client.get("$vuzapiURL/user/bx/$id") {
header("Cookie", "PHPSESSID=$PHPSESSID")
}.bodyAsText()).getInt("id")
return getUser(userId)
getUser(userId).let { user ->
withContext(Dispatchers.IO) {
cacheUser(user)
}
return user
}
}
suspend fun getUser(id: Int): User {
@ -317,14 +335,15 @@ suspend fun getUser(id: Int): User {
}.bodyAsText()
)
Log.d("type", json.getJSONArray("profiles").getJSONObject(0).getString("type"))
return User(
unnId = null,
bitrixId = json.getInt("bitrix_id"),
userId = json.getInt("id"),
type = when (json.getJSONArray("profiles").getJSONObject(0).getString("type")) {
"lecturer" -> Type.Lecturer // ig,,,
else -> Type.Student
},
type = if (json.getJSONArray("profiles").getJSONObject(0)
.getString("type") == "employee"
) Type.Employee else Type.Student,
email = json.getString("email"),
nameRu = json.getString("fullname"),
nameEn = json.getString("fullname_en"),
@ -334,7 +353,7 @@ suspend fun getUser(id: Int): User {
DateTimeFormatter.ofPattern("yyyy-MM-dd")
),
avatar = json.getJSONObject("photo").let {
ImageSet(
AvatarSet(
it.getString("orig"),
it.getString("thumbnail"),
it.getString("small"),

View File

@ -0,0 +1,9 @@
package ru.sweetbread.unn.db
import androidx.room.Database
import androidx.room.RoomDatabase
@Database(entities = [UserDB::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
abstract fun userDao(): UserDao
}

View File

@ -0,0 +1,101 @@
package ru.sweetbread.unn.db
import android.util.Log
import androidx.room.ColumnInfo
import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Entity
import androidx.room.Insert
import androidx.room.PrimaryKey
import androidx.room.Query
import ru.sweetbread.unn.AvatarSet
import ru.sweetbread.unn.Type
import ru.sweetbread.unn.User
import ru.sweetbread.unn.ui.layout.db
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
@Entity
data class UserDB(
@PrimaryKey val userId: Int,
@ColumnInfo val unnId: Int?,
@ColumnInfo val bitrixId: Int,
@ColumnInfo val type: Type,
@ColumnInfo val email: String,
@ColumnInfo val nameRu: String,
@ColumnInfo val nameEn: String,
@ColumnInfo val isMale: Boolean,
@ColumnInfo val birthday: String,
@ColumnInfo val origAvatar: String,
@ColumnInfo val thumbAvatar: String,
@ColumnInfo val smallAvatar: String,
@ColumnInfo val expiredAt: String
)
@Dao
interface UserDao {
@Query("SELECT * FROM userDB WHERE bitrixId = :bitrixId LIMIT 1")
fun getUserByBitrix(bitrixId: Int): UserDB?
@Insert
fun insert(user: UserDB)
@Delete
fun delete(user: UserDB)
}
fun cacheUser(user: User) {
try {
db.userDao().insert(
UserDB(
user.userId,
user.unnId,
user.bitrixId,
user.type,
user.email,
user.nameRu,
user.nameEn,
user.isMale,
user.birthday.format(DateTimeFormatter.ISO_LOCAL_DATE),
user.avatar.original,
user.avatar.thumbnail,
user.avatar.small,
LocalDateTime.now().plusDays(1).format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
)
)
} catch (_: android.database.sqlite.SQLiteConstraintException) {
}
}
fun loadUserByBitrixId(bitrixId: Int): User? {
val user = db.userDao().getUserByBitrix(bitrixId)
Log.d("UserDB", user?.nameEn ?: "None")
if (user == null) return null
if (LocalDateTime.parse(
user.expiredAt,
DateTimeFormatter.ISO_LOCAL_DATE_TIME
) < LocalDateTime.now()
) {
db.userDao().delete(user)
return null
} else {
return User(
user.unnId,
user.bitrixId,
user.userId,
user.type,
user.email,
user.nameRu,
user.nameEn,
user.isMale,
LocalDate.parse(user.birthday, DateTimeFormatter.ISO_LOCAL_DATE),
AvatarSet(
user.origAvatar,
user.thumbAvatar,
user.smallAvatar
)
)
}
}

View File

@ -48,7 +48,7 @@ import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import org.kefirsf.bb.BBProcessorFactory
import org.kefirsf.bb.TextProcessor
import ru.sweetbread.unn.ImageSet
import ru.sweetbread.unn.AvatarSet
import ru.sweetbread.unn.Post
import ru.sweetbread.unn.R
import ru.sweetbread.unn.Type
@ -73,7 +73,7 @@ val defUser = User(
"Jon Sigma Omega",
true,
LocalDate.now(),
ImageSet(
AvatarSet(
"https://upload.wikimedia.org/wikipedia/ru/thumb/9/94/%D0%93%D0%B8%D0%B3%D0%B0%D1%87%D0%B0%D0%B4.jpg/500px-%D0%93%D0%B8%D0%B3%D0%B0%D1%87%D0%B0%D0%B4.jpg",
"https://upload.wikimedia.org/wikipedia/ru/thumb/9/94/%D0%93%D0%B8%D0%B3%D0%B0%D1%87%D0%B0%D0%B4.jpg/500px-%D0%93%D0%B8%D0%B3%D0%B0%D1%87%D0%B0%D0%B4.jpg",
"https://upload.wikimedia.org/wikipedia/ru/thumb/9/94/%D0%93%D0%B8%D0%B3%D0%B0%D1%87%D0%B0%D0%B4.jpg/500px-%D0%93%D0%B8%D0%B3%D0%B0%D1%87%D0%B0%D0%B4.jpg"

View File

@ -25,6 +25,7 @@ import androidx.compose.ui.Modifier
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import androidx.room.Room
import io.ktor.client.HttpClient
import io.ktor.client.plugins.HttpRequestRetry
import io.ktor.client.plugins.HttpTimeout
@ -32,6 +33,7 @@ import io.ktor.client.plugins.cache.HttpCache
import io.ktor.client.plugins.logging.LogLevel
import io.ktor.client.plugins.logging.Logger
import io.ktor.client.plugins.logging.Logging
import ru.sweetbread.unn.db.AppDatabase
import ru.sweetbread.unn.ui.composes.Blogposts
import ru.sweetbread.unn.ui.composes.Schedule
import ru.sweetbread.unn.ui.theme.UNNTheme
@ -59,10 +61,18 @@ val client = HttpClient {
}
}
lateinit var db: AppDatabase
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
db = Room.databaseBuilder(
applicationContext,
AppDatabase::class.java, "database"
).build()
setContent {
UNNTheme {
Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background) {

View File

@ -2,6 +2,7 @@
plugins {
alias(libs.plugins.androidApplication) apply false
alias(libs.plugins.jetbrainsKotlinAndroid) apply false
id("com.google.devtools.ksp") version "1.9.0-1.0.13" apply false
}
buildscript {

View File

@ -24,6 +24,7 @@ lifecycleLivedataKtx = "2.7.0"
lifecycleViewmodelKtx = "2.7.0"
activity = "1.8.2"
navigationCompose = "2.7.7"
roomRuntime = "2.6.1"
secretsGradlePlugin = "2.0.1"
splittiesFunPackAndroidBaseWithViewsDsl = "3.0.0"
kefirbb = "1.5"
@ -34,6 +35,9 @@ androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref =
androidx-core-splashscreen = { module = "androidx.core:core-splashscreen", version.ref = "coreSplashscreen" }
androidx-datastore-preferences = { module = "androidx.datastore:datastore-preferences", version.ref = "datastorePreferences" }
androidx-navigation-compose = { module = "androidx.navigation:navigation-compose", version.ref = "navigationCompose" }
androidx-room-compiler = { module = "androidx.room:room-compiler", version.ref = "roomRuntime" }
androidx-room-ktx = { module = "androidx.room:room-ktx", version.ref = "roomRuntime" }
androidx-room-runtime = { module = "androidx.room:room-runtime", version.ref = "roomRuntime" }
coil-compose = { module = "io.coil-kt:coil-compose", version.ref = "coilCompose" }
compose = { module = "com.kizitonwose.calendar:compose", version.ref = "compose" }
desugar_jdk_libs = { module = "com.android.tools:desugar_jdk_libs", version.ref = "desugar_jdk_libs" }