ref: removing api calls to separate functions
This commit is contained in:
parent
654acf1b77
commit
1286860d55
99
app/src/main/java/ru/sweetbread/unn/api/API.kt
Normal file
99
app/src/main/java/ru/sweetbread/unn/api/API.kt
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
/*
|
||||||
|
* Created by sweetbread
|
||||||
|
* Copyright (c) 2025. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package ru.sweetbread.unn.api
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.async
|
||||||
|
import kotlinx.coroutines.coroutineScope
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
import ru.sweetbread.unn.db.cacheSchedule
|
||||||
|
import ru.sweetbread.unn.db.loadSchedule
|
||||||
|
import ru.sweetbread.unn.ui.layout.LoginData
|
||||||
|
import java.time.LocalDate
|
||||||
|
|
||||||
|
|
||||||
|
lateinit var PHPSESSID: String
|
||||||
|
lateinit var CSRF: String
|
||||||
|
lateinit var ME: User
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Authorize user by [login] and [password]
|
||||||
|
*
|
||||||
|
* Also defines local vars [PHPSESSID] and [ME]
|
||||||
|
*/
|
||||||
|
suspend fun auth(
|
||||||
|
login: String = LoginData.login,
|
||||||
|
password: String = LoginData.password,
|
||||||
|
forced: Boolean = false
|
||||||
|
): Boolean {
|
||||||
|
if (!forced) {
|
||||||
|
if (::PHPSESSID.isInitialized and ::ME.isInitialized)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
val id = getToken(login, password)
|
||||||
|
if (id != null) {
|
||||||
|
PHPSESSID = id
|
||||||
|
getMyself(login)
|
||||||
|
getCSRF()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save info about current [User] in memory
|
||||||
|
*/
|
||||||
|
private suspend fun getMyself(login: String) = coroutineScope {
|
||||||
|
val idDeferred = async { getId(login) }
|
||||||
|
val userDeferred = async { getUser() }
|
||||||
|
|
||||||
|
val id = idDeferred.await()
|
||||||
|
val user = userDeferred.await()
|
||||||
|
|
||||||
|
ME = User(
|
||||||
|
unnId = id,
|
||||||
|
userId = user.userId,
|
||||||
|
type = Type.student,
|
||||||
|
email = user.email,
|
||||||
|
nameRu = user.nameRu,
|
||||||
|
nameEn = user.nameEn,
|
||||||
|
isMale = user.isMale,
|
||||||
|
birthday = user.birthday,
|
||||||
|
avatar = user.avatar
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun getScheduleDay(
|
||||||
|
type: Type = ME.type,
|
||||||
|
id: Int = ME.unnId!!,
|
||||||
|
date: LocalDate
|
||||||
|
): ArrayList<ScheduleUnit> {
|
||||||
|
|
||||||
|
if ((type == ME.type) and (id == ME.unnId!!)) {
|
||||||
|
val schedule = withContext(Dispatchers.IO) { loadSchedule(date) }
|
||||||
|
Log.d("Schedule", schedule.joinToString())
|
||||||
|
if (schedule.isNotEmpty())
|
||||||
|
return schedule
|
||||||
|
}
|
||||||
|
|
||||||
|
return getSchedule(type, id, date, date)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun getSchedule(
|
||||||
|
type: Type = ME.type,
|
||||||
|
id: Int = ME.unnId!!,
|
||||||
|
start: LocalDate,
|
||||||
|
finish: LocalDate
|
||||||
|
): ArrayList<ScheduleUnit> {
|
||||||
|
val schedule = downloadSchedule(type, id, start, finish)
|
||||||
|
|
||||||
|
if ((type == ME.type) and (id == ME.unnId!!))
|
||||||
|
cacheSchedule(schedule)
|
||||||
|
|
||||||
|
return schedule
|
||||||
|
}
|
@ -3,9 +3,17 @@
|
|||||||
* Copyright (c) 2025. All rights reserved.
|
* Copyright (c) 2025. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.sweetbread.unn
|
package ru.sweetbread.unn.api
|
||||||
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
import io.ktor.client.HttpClient
|
||||||
|
import io.ktor.client.engine.android.Android
|
||||||
|
import io.ktor.client.plugins.HttpRequestRetry
|
||||||
|
import io.ktor.client.plugins.HttpTimeout
|
||||||
|
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 io.ktor.client.request.forms.submitForm
|
import io.ktor.client.request.forms.submitForm
|
||||||
import io.ktor.client.request.get
|
import io.ktor.client.request.get
|
||||||
import io.ktor.client.request.header
|
import io.ktor.client.request.header
|
||||||
@ -16,13 +24,8 @@ import kotlinx.coroutines.Dispatchers
|
|||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import org.json.JSONArray
|
import org.json.JSONArray
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
import ru.sweetbread.unn.db.cacheSchedule
|
|
||||||
import ru.sweetbread.unn.db.cacheUser
|
import ru.sweetbread.unn.db.cacheUser
|
||||||
import ru.sweetbread.unn.db.loadSchedule
|
|
||||||
import ru.sweetbread.unn.db.loadUserByBitrixId
|
import ru.sweetbread.unn.db.loadUserByBitrixId
|
||||||
import ru.sweetbread.unn.ui.layout.LoginData
|
|
||||||
import ru.sweetbread.unn.ui.layout.client
|
|
||||||
import splitties.resources.appStr
|
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
import java.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
@ -31,10 +34,6 @@ import java.time.ZoneId
|
|||||||
import java.time.format.DateTimeFormatter
|
import java.time.format.DateTimeFormatter
|
||||||
|
|
||||||
|
|
||||||
private lateinit var PHPSESSID: String
|
|
||||||
private lateinit var CSRF: String
|
|
||||||
lateinit var ME: User
|
|
||||||
|
|
||||||
const val portalURL = "https://portal.unn.ru"
|
const val portalURL = "https://portal.unn.ru"
|
||||||
const val ruzapiURL = "$portalURL/ruzapi"
|
const val ruzapiURL = "$portalURL/ruzapi"
|
||||||
const val vuzapiURL = "$portalURL/bitrix/vuz/api"
|
const val vuzapiURL = "$portalURL/bitrix/vuz/api"
|
||||||
@ -42,110 +41,29 @@ const val prtl2URL = "$portalURL/portal2/api"
|
|||||||
const val restURL = "$portalURL/rest"
|
const val restURL = "$portalURL/rest"
|
||||||
|
|
||||||
|
|
||||||
enum class Type(val s: String) {
|
val client = HttpClient(Android) {
|
||||||
Student(appStr(R.string.student)),
|
install(HttpCache)
|
||||||
Group("group"),
|
install(Logging) {
|
||||||
Lecturer(appStr(R.string.lecturer)),
|
logger = object : Logger {
|
||||||
Auditorium("auditorium"),
|
override fun log(message: String) {
|
||||||
Employee(appStr(R.string.employee))
|
Log.i("Ktor", message)
|
||||||
}
|
|
||||||
|
|
||||||
enum class LecturerRank(val id: Int) {
|
|
||||||
Assistant(R.string.assistant),
|
|
||||||
Lecturer(R.string.lecturer),
|
|
||||||
SLecturer(R.string.slecturer),
|
|
||||||
AProfessor(R.string.aprofessor)
|
|
||||||
}
|
|
||||||
|
|
||||||
class ScheduleUnit(
|
|
||||||
val oid: Int,
|
|
||||||
val auditorium: Auditorium,
|
|
||||||
val date: LocalDate,
|
|
||||||
val discipline: Discipline,
|
|
||||||
val kindOfWork: KindOfWork,
|
|
||||||
val lecturers: ArrayList<Lecturer>,
|
|
||||||
val stream: String,
|
|
||||||
val begin: LocalTime,
|
|
||||||
val end: LocalTime
|
|
||||||
)
|
|
||||||
|
|
||||||
class Auditorium(
|
|
||||||
val name: String,
|
|
||||||
val oid: Int,
|
|
||||||
val floor: Int,
|
|
||||||
val building: Building
|
|
||||||
)
|
|
||||||
|
|
||||||
class Building(
|
|
||||||
val name: String,
|
|
||||||
val gid: Int,
|
|
||||||
val oid: Int
|
|
||||||
)
|
|
||||||
|
|
||||||
class Discipline(
|
|
||||||
val name: String,
|
|
||||||
val oid: Int,
|
|
||||||
val type: Int
|
|
||||||
)
|
|
||||||
|
|
||||||
class KindOfWork(
|
|
||||||
val name: String,
|
|
||||||
val oid: Int,
|
|
||||||
val uid: String,
|
|
||||||
val complexity: Int
|
|
||||||
)
|
|
||||||
|
|
||||||
class Lecturer(
|
|
||||||
val name: String,
|
|
||||||
val rank: LecturerRank,
|
|
||||||
val email: String,
|
|
||||||
val unnId: Int,
|
|
||||||
val uid: String
|
|
||||||
)
|
|
||||||
|
|
||||||
class User(
|
|
||||||
val unnId: Int?,
|
|
||||||
val bitrixId: Int,
|
|
||||||
val userId: Int,
|
|
||||||
val type: Type,
|
|
||||||
val email: String,
|
|
||||||
val nameRu: String,
|
|
||||||
val nameEn: String,
|
|
||||||
val isMale: Boolean,
|
|
||||||
val birthday: LocalDate,
|
|
||||||
val avatar: AvatarSet
|
|
||||||
)
|
|
||||||
|
|
||||||
class Post(
|
|
||||||
val id: Int,
|
|
||||||
val authorId: Int,
|
|
||||||
val enableComments: Boolean,
|
|
||||||
val numComments: Int,
|
|
||||||
val date: LocalDateTime,
|
|
||||||
val content: String
|
|
||||||
)
|
|
||||||
|
|
||||||
class AvatarSet(
|
|
||||||
val original: String,
|
|
||||||
val thumbnail: String,
|
|
||||||
val small: String
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Authorize user by [login] and [password]
|
|
||||||
*
|
|
||||||
* Also defines local vars [PHPSESSID] and [ME]
|
|
||||||
*/
|
|
||||||
suspend fun auth(
|
|
||||||
login: String = LoginData.login,
|
|
||||||
password: String = LoginData.password,
|
|
||||||
forced: Boolean = false
|
|
||||||
): Boolean {
|
|
||||||
if (!forced) {
|
|
||||||
if (::PHPSESSID.isInitialized and ::ME.isInitialized)
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
level = LogLevel.ALL
|
||||||
|
}
|
||||||
|
install(HttpTimeout) {
|
||||||
|
connectTimeoutMillis = 5000
|
||||||
|
}
|
||||||
|
install(HttpRequestRetry) {
|
||||||
|
retryOnException(maxRetries = 3, retryOnTimeout = true)
|
||||||
|
exponentialDelay()
|
||||||
|
modifyRequest { request ->
|
||||||
|
request.headers.append("x-retry-count", retryCount.toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun getToken(login: String, password: String): String? {
|
||||||
val r = client.submitForm("$portalURL/auth/?login=yes",
|
val r = client.submitForm("$portalURL/auth/?login=yes",
|
||||||
formParameters = parameters {
|
formParameters = parameters {
|
||||||
append("AUTH_FORM", "Y")
|
append("AUTH_FORM", "Y")
|
||||||
@ -155,52 +73,43 @@ suspend fun auth(
|
|||||||
append("USER_PASSWORD", password)
|
append("USER_PASSWORD", password)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
if (r.status.value == 302) {
|
|
||||||
PHPSESSID =
|
if (r.status.value == 302)
|
||||||
"""PHPSESSID=([\w\d]+)""".toRegex().find(r.headers["Set-Cookie"]!!)!!.groupValues[1]
|
return """PHPSESSID=([\w\d]+)""".toRegex().find(r.headers["Set-Cookie"]!!)!!.groupValues[1]
|
||||||
getMyself(login)
|
return null
|
||||||
getCSRF()
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
suspend fun getId(login: String): Int {
|
||||||
* Save info about current [User] in memory
|
return JSONObject(client.get("$ruzapiURL/studentinfo/") {
|
||||||
*/
|
|
||||||
private suspend fun getMyself(login: String) {
|
|
||||||
// WARNING: trailing / is important, 'cuz API devs are eating shit
|
|
||||||
// TODO: make up another way to get unnId: this is not useful for lectures
|
|
||||||
val studentinfo = JSONObject(client.get("$ruzapiURL/studentinfo/") {
|
|
||||||
header("Cookie", "PHPSESSID=$PHPSESSID")
|
header("Cookie", "PHPSESSID=$PHPSESSID")
|
||||||
parameter("uns", login.drop(1))
|
parameter("uns", login.drop(1))
|
||||||
}.bodyAsText())
|
}.bodyAsText()).getString("id").toInt()
|
||||||
|
}
|
||||||
|
|
||||||
val user = JSONObject(
|
suspend fun getUser(userId: Int? = null): User {
|
||||||
client.get("$vuzapiURL/user") {
|
// WARNING: trailing / is important, 'cuz API devs are eating shit
|
||||||
|
// TODO: make up another way to get unnId: this is not useful for lectures
|
||||||
|
val json = JSONObject(
|
||||||
|
client.get("$vuzapiURL/user/${userId ?: ""}") {
|
||||||
header("Cookie", "PHPSESSID=$PHPSESSID")
|
header("Cookie", "PHPSESSID=$PHPSESSID")
|
||||||
}.bodyAsText()
|
}.bodyAsText()
|
||||||
)
|
)
|
||||||
|
|
||||||
Log.d("studentInfo", studentinfo.toString(2))
|
return User(
|
||||||
|
unnId = null,
|
||||||
ME = User(
|
userId = json.getInt("id"),
|
||||||
unnId = studentinfo.getString("id").toInt(),
|
type = if (json.getJSONArray("profiles").getJSONObject(0)
|
||||||
bitrixId = user.getInt("bitrix_id"), // TODO: remove
|
.getString("type") == "employee"
|
||||||
userId = user.getInt("id"),
|
) Type.employee else Type.student,
|
||||||
type = when (studentinfo.getString("type")) {
|
email = json.getString("email"),
|
||||||
"lecturer" -> Type.Lecturer // ig,,,
|
nameRu = json.getString("fullname"),
|
||||||
else -> Type.Student
|
nameEn = json.getString("fullname_en"),
|
||||||
},
|
isMale = json.getString("sex") == "M",
|
||||||
email = user.getString("email"),
|
|
||||||
nameRu = user.getString("fullname"),
|
|
||||||
nameEn = user.getString("fullname_en"),
|
|
||||||
isMale = user.getString("sex") == "M",
|
|
||||||
birthday = Instant
|
birthday = Instant
|
||||||
.parse(user.getString("birthdate"))
|
.parse(json.getString("birthdate"))
|
||||||
.atZone(ZoneId.of("Europe/Moscow"))
|
.atZone(ZoneId.of("Europe/Moscow"))
|
||||||
.toLocalDate(),
|
.toLocalDate(),
|
||||||
avatar = user.getJSONObject("photo").let {
|
avatar = json.getJSONObject("photo").let {
|
||||||
AvatarSet(
|
AvatarSet(
|
||||||
it.getString("orig"),
|
it.getString("orig"),
|
||||||
it.getString("thumbnail"),
|
it.getString("thumbnail"),
|
||||||
@ -210,23 +119,7 @@ private suspend fun getMyself(login: String) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getScheduleDay(
|
suspend fun downloadSchedule(
|
||||||
type: Type = ME.type,
|
|
||||||
id: Int = ME.unnId!!,
|
|
||||||
date: LocalDate
|
|
||||||
): ArrayList<ScheduleUnit> {
|
|
||||||
|
|
||||||
if ((type == ME.type) and (id == ME.unnId!!)) {
|
|
||||||
val schedule = withContext(Dispatchers.IO) { loadSchedule(date) }
|
|
||||||
Log.d("Schedule", schedule.joinToString())
|
|
||||||
if (schedule.isNotEmpty())
|
|
||||||
return schedule
|
|
||||||
}
|
|
||||||
|
|
||||||
return getSchedule(type, id, date, date)
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun getSchedule(
|
|
||||||
type: Type = ME.type,
|
type: Type = ME.type,
|
||||||
id: Int = ME.unnId!!,
|
id: Int = ME.unnId!!,
|
||||||
start: LocalDate,
|
start: LocalDate,
|
||||||
@ -234,13 +127,13 @@ suspend fun getSchedule(
|
|||||||
): ArrayList<ScheduleUnit> {
|
): ArrayList<ScheduleUnit> {
|
||||||
val unnDatePattern = DateTimeFormatter.ofPattern("yyyy-MM-dd")
|
val unnDatePattern = DateTimeFormatter.ofPattern("yyyy-MM-dd")
|
||||||
|
|
||||||
val r = client.get("$ruzapiURL/schedule/${type.s}/$id") {
|
val r = client.get("$ruzapiURL/schedule/${type.name}/$id") {
|
||||||
parameter("start", start.format(unnDatePattern))
|
parameter("start", start.format(unnDatePattern))
|
||||||
parameter("finish", finish.format(unnDatePattern))
|
parameter("finish", finish.format(unnDatePattern))
|
||||||
parameter("lng", "1")
|
parameter("lng", "1")
|
||||||
}
|
}
|
||||||
val json = JSONArray(r.bodyAsText())
|
|
||||||
|
|
||||||
|
val json = JSONArray(r.bodyAsText())
|
||||||
val out = arrayListOf<ScheduleUnit>()
|
val out = arrayListOf<ScheduleUnit>()
|
||||||
for (i in 0 until json.length()) {
|
for (i in 0 until json.length()) {
|
||||||
val unit = json.getJSONObject(i)
|
val unit = json.getJSONObject(i)
|
||||||
@ -304,9 +197,6 @@ suspend fun getSchedule(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((type == ME.type) and (id == ME.unnId!!)) {
|
|
||||||
cacheSchedule(out)
|
|
||||||
}
|
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -318,6 +208,23 @@ suspend fun getCSRF() {
|
|||||||
CSRF = JSONObject(r.bodyAsText()).getString("sessid")
|
CSRF = JSONObject(r.bodyAsText()).getString("sessid")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun getUserByBitrixId(id: Int): User {
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
loadUserByBitrixId(id)
|
||||||
|
}?.let { return it }
|
||||||
|
|
||||||
|
val userId = JSONObject(client.get("$vuzapiURL/user/bx/$id") {
|
||||||
|
header("Cookie", "PHPSESSID=$PHPSESSID")
|
||||||
|
}.bodyAsText()).getInt("id")
|
||||||
|
|
||||||
|
getUser(userId).let { user ->
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
cacheUser(user)
|
||||||
|
}
|
||||||
|
return user
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun getBlogposts(): ArrayList<Post> {
|
suspend fun getBlogposts(): ArrayList<Post> {
|
||||||
val r = client.get("$prtl2URL/news.php") {
|
val r = client.get("$prtl2URL/news.php") {
|
||||||
header("Cookie", "PHPSESSID=$PHPSESSID")
|
header("Cookie", "PHPSESSID=$PHPSESSID")
|
||||||
@ -344,54 +251,3 @@ suspend fun getBlogposts(): ArrayList<Post> {
|
|||||||
}
|
}
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getUserByBitrixId(id: Int): User {
|
|
||||||
withContext(Dispatchers.IO) {
|
|
||||||
loadUserByBitrixId(id)
|
|
||||||
}?.let { return it }
|
|
||||||
|
|
||||||
val userId = JSONObject(client.get("$vuzapiURL/user/bx/$id") {
|
|
||||||
header("Cookie", "PHPSESSID=$PHPSESSID")
|
|
||||||
}.bodyAsText()).getInt("id")
|
|
||||||
|
|
||||||
getUser(userId).let { user ->
|
|
||||||
withContext(Dispatchers.IO) {
|
|
||||||
cacheUser(user)
|
|
||||||
}
|
|
||||||
return user
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun getUser(id: Int): User {
|
|
||||||
val json = JSONObject(
|
|
||||||
client.get("$vuzapiURL/user/$id") {
|
|
||||||
header("Cookie", "PHPSESSID=$PHPSESSID")
|
|
||||||
}.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 = 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"),
|
|
||||||
isMale = json.getString("sex") == "M",
|
|
||||||
birthday = Instant
|
|
||||||
.parse(json.getString("birthdate"))
|
|
||||||
.atZone(ZoneId.of("Europe/Moscow"))
|
|
||||||
.toLocalDate(),
|
|
||||||
avatar = json.getJSONObject("photo").let {
|
|
||||||
AvatarSet(
|
|
||||||
it.getString("orig"),
|
|
||||||
it.getString("thumbnail"),
|
|
||||||
it.getString("small"),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
100
app/src/main/java/ru/sweetbread/unn/api/models.kt
Normal file
100
app/src/main/java/ru/sweetbread/unn/api/models.kt
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
/*
|
||||||
|
* Created by sweetbread
|
||||||
|
* Copyright (c) 2025. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package ru.sweetbread.unn.api
|
||||||
|
|
||||||
|
import ru.sweetbread.unn.R
|
||||||
|
import splitties.resources.appStr
|
||||||
|
import java.time.LocalDate
|
||||||
|
import java.time.LocalDateTime
|
||||||
|
import java.time.LocalTime
|
||||||
|
|
||||||
|
enum class Type(val s: String) {
|
||||||
|
student(appStr(R.string.student)),
|
||||||
|
group("group"),
|
||||||
|
lecturer(appStr(R.string.lecturer)),
|
||||||
|
auditorium("auditorium"),
|
||||||
|
employee(appStr(R.string.employee))
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class LecturerRank(val id: Int) {
|
||||||
|
Assistant(R.string.assistant),
|
||||||
|
Lecturer(R.string.lecturer),
|
||||||
|
SLecturer(R.string.slecturer),
|
||||||
|
AProfessor(R.string.aprofessor)
|
||||||
|
}
|
||||||
|
|
||||||
|
class ScheduleUnit(
|
||||||
|
val oid: Int,
|
||||||
|
val auditorium: Auditorium,
|
||||||
|
val date: LocalDate,
|
||||||
|
val discipline: Discipline,
|
||||||
|
val kindOfWork: KindOfWork,
|
||||||
|
val lecturers: ArrayList<Lecturer>,
|
||||||
|
val stream: String,
|
||||||
|
val begin: LocalTime,
|
||||||
|
val end: LocalTime
|
||||||
|
)
|
||||||
|
|
||||||
|
class Auditorium(
|
||||||
|
val name: String,
|
||||||
|
val oid: Int,
|
||||||
|
val floor: Int,
|
||||||
|
val building: Building
|
||||||
|
)
|
||||||
|
|
||||||
|
class Building(
|
||||||
|
val name: String,
|
||||||
|
val gid: Int,
|
||||||
|
val oid: Int
|
||||||
|
)
|
||||||
|
|
||||||
|
class Discipline(
|
||||||
|
val name: String,
|
||||||
|
val oid: Int,
|
||||||
|
val type: Int
|
||||||
|
)
|
||||||
|
|
||||||
|
class KindOfWork(
|
||||||
|
val name: String,
|
||||||
|
val oid: Int,
|
||||||
|
val uid: String,
|
||||||
|
val complexity: Int
|
||||||
|
)
|
||||||
|
|
||||||
|
class Lecturer(
|
||||||
|
val name: String,
|
||||||
|
val rank: LecturerRank,
|
||||||
|
val email: String,
|
||||||
|
val unnId: Int,
|
||||||
|
val uid: String
|
||||||
|
)
|
||||||
|
|
||||||
|
class User(
|
||||||
|
val unnId: Int?,
|
||||||
|
val userId: Int,
|
||||||
|
val type: Type,
|
||||||
|
val email: String,
|
||||||
|
val nameRu: String,
|
||||||
|
val nameEn: String,
|
||||||
|
val isMale: Boolean,
|
||||||
|
val birthday: LocalDate,
|
||||||
|
val avatar: AvatarSet
|
||||||
|
)
|
||||||
|
|
||||||
|
class Post(
|
||||||
|
val id: Int,
|
||||||
|
val authorId: Int,
|
||||||
|
val enableComments: Boolean,
|
||||||
|
val numComments: Int,
|
||||||
|
val date: LocalDateTime,
|
||||||
|
val content: String
|
||||||
|
)
|
||||||
|
|
||||||
|
class AvatarSet(
|
||||||
|
val original: String,
|
||||||
|
val thumbnail: String,
|
||||||
|
val small: String
|
||||||
|
)
|
@ -1,7 +1,17 @@
|
|||||||
|
/*
|
||||||
|
* Created by sweetbread
|
||||||
|
* Copyright (c) 2025. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
package ru.sweetbread.unn.db
|
package ru.sweetbread.unn.db
|
||||||
|
|
||||||
import androidx.room.Database
|
import androidx.room.Database
|
||||||
import androidx.room.RoomDatabase
|
import androidx.room.RoomDatabase
|
||||||
|
import splitties.arch.room.roomDb
|
||||||
|
|
||||||
|
val cacheDb = roomDb<AppDatabase>(name = "cache") {
|
||||||
|
fallbackToDestructiveMigration(dropAllTables = true)
|
||||||
|
}
|
||||||
|
|
||||||
@Database(entities = [
|
@Database(entities = [
|
||||||
UserDB::class,
|
UserDB::class,
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
/*
|
||||||
|
* Created by sweetbread
|
||||||
|
* Copyright (c) 2025. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
package ru.sweetbread.unn.db
|
package ru.sweetbread.unn.db
|
||||||
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
@ -9,14 +14,13 @@ import androidx.room.Insert
|
|||||||
import androidx.room.OnConflictStrategy
|
import androidx.room.OnConflictStrategy
|
||||||
import androidx.room.PrimaryKey
|
import androidx.room.PrimaryKey
|
||||||
import androidx.room.Query
|
import androidx.room.Query
|
||||||
import ru.sweetbread.unn.Auditorium
|
import ru.sweetbread.unn.api.Auditorium
|
||||||
import ru.sweetbread.unn.Building
|
import ru.sweetbread.unn.api.Building
|
||||||
import ru.sweetbread.unn.Discipline
|
import ru.sweetbread.unn.api.Discipline
|
||||||
import ru.sweetbread.unn.KindOfWork
|
import ru.sweetbread.unn.api.KindOfWork
|
||||||
import ru.sweetbread.unn.Lecturer
|
import ru.sweetbread.unn.api.Lecturer
|
||||||
import ru.sweetbread.unn.LecturerRank
|
import ru.sweetbread.unn.api.LecturerRank
|
||||||
import ru.sweetbread.unn.ScheduleUnit
|
import ru.sweetbread.unn.api.ScheduleUnit
|
||||||
import ru.sweetbread.unn.ui.layout.db
|
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
import java.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
import java.time.LocalTime
|
import java.time.LocalTime
|
||||||
@ -43,7 +47,7 @@ interface BuildingDao {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun cacheBuilding(building: Building) {
|
fun cacheBuilding(building: Building) {
|
||||||
db.buildingDao().insert(
|
cacheDb.buildingDao().insert(
|
||||||
BuildingDB(
|
BuildingDB(
|
||||||
building.oid,
|
building.oid,
|
||||||
building.name,
|
building.name,
|
||||||
@ -54,13 +58,13 @@ fun cacheBuilding(building: Building) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun loadBuilding(oid: Int): Building? {
|
fun loadBuilding(oid: Int): Building? {
|
||||||
return db.buildingDao().get(oid)?.let {
|
return cacheDb.buildingDao().get(oid)?.let {
|
||||||
if (LocalDateTime.parse(
|
if (LocalDateTime.parse(
|
||||||
it.expiredAt,
|
it.expiredAt,
|
||||||
DateTimeFormatter.ISO_DATE_TIME
|
DateTimeFormatter.ISO_DATE_TIME
|
||||||
) > LocalDateTime.now()
|
) > LocalDateTime.now()
|
||||||
) {
|
) {
|
||||||
db.buildingDao().delete(it)
|
cacheDb.buildingDao().delete(it)
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
Building(
|
Building(
|
||||||
@ -94,7 +98,7 @@ interface AuditoriumDao {
|
|||||||
|
|
||||||
fun cacheAuditorium(auditorium: Auditorium) {
|
fun cacheAuditorium(auditorium: Auditorium) {
|
||||||
cacheBuilding(auditorium.building)
|
cacheBuilding(auditorium.building)
|
||||||
db.auditoriumDao().insert(
|
cacheDb.auditoriumDao().insert(
|
||||||
AuditoriumDB(
|
AuditoriumDB(
|
||||||
auditorium.oid,
|
auditorium.oid,
|
||||||
auditorium.name,
|
auditorium.name,
|
||||||
@ -106,13 +110,13 @@ fun cacheAuditorium(auditorium: Auditorium) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun loadAuditorium(oid: Int): Auditorium? {
|
fun loadAuditorium(oid: Int): Auditorium? {
|
||||||
return db.auditoriumDao().get(oid)?.let {
|
return cacheDb.auditoriumDao().get(oid)?.let {
|
||||||
if (LocalDateTime.parse(
|
if (LocalDateTime.parse(
|
||||||
it.expiredAt,
|
it.expiredAt,
|
||||||
DateTimeFormatter.ISO_DATE_TIME
|
DateTimeFormatter.ISO_DATE_TIME
|
||||||
) > LocalDateTime.now()
|
) > LocalDateTime.now()
|
||||||
) {
|
) {
|
||||||
db.auditoriumDao().delete(it)
|
cacheDb.auditoriumDao().delete(it)
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
val building = loadBuilding(it.buildingOid) ?: return null
|
val building = loadBuilding(it.buildingOid) ?: return null
|
||||||
@ -146,7 +150,7 @@ interface DisciplineDao {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun cacheDiscipline(discipline: Discipline) {
|
fun cacheDiscipline(discipline: Discipline) {
|
||||||
db.disciplineDao().insert(
|
cacheDb.disciplineDao().insert(
|
||||||
DisciplineDB(
|
DisciplineDB(
|
||||||
discipline.oid,
|
discipline.oid,
|
||||||
discipline.name,
|
discipline.name,
|
||||||
@ -157,13 +161,13 @@ fun cacheDiscipline(discipline: Discipline) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun loadDiscipline(oid: Int): Discipline? {
|
fun loadDiscipline(oid: Int): Discipline? {
|
||||||
return db.disciplineDao().get(oid)?.let {
|
return cacheDb.disciplineDao().get(oid)?.let {
|
||||||
if (LocalDateTime.parse(
|
if (LocalDateTime.parse(
|
||||||
it.expiredAt,
|
it.expiredAt,
|
||||||
DateTimeFormatter.ISO_DATE_TIME
|
DateTimeFormatter.ISO_DATE_TIME
|
||||||
) > LocalDateTime.now()
|
) > LocalDateTime.now()
|
||||||
) {
|
) {
|
||||||
db.disciplineDao().delete(it)
|
cacheDb.disciplineDao().delete(it)
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -197,7 +201,7 @@ interface KindOfWorkDao {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun cacheKindOfWork(kindOfWork: KindOfWork) {
|
fun cacheKindOfWork(kindOfWork: KindOfWork) {
|
||||||
db.kindOfWorkDao().insert(
|
cacheDb.kindOfWorkDao().insert(
|
||||||
KindOfWorkDB(
|
KindOfWorkDB(
|
||||||
kindOfWork.oid,
|
kindOfWork.oid,
|
||||||
kindOfWork.name,
|
kindOfWork.name,
|
||||||
@ -209,13 +213,13 @@ fun cacheKindOfWork(kindOfWork: KindOfWork) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun loadKindOfWork(oid: Int): KindOfWork? {
|
fun loadKindOfWork(oid: Int): KindOfWork? {
|
||||||
return db.kindOfWorkDao().get(oid)?.let {
|
return cacheDb.kindOfWorkDao().get(oid)?.let {
|
||||||
if (LocalDateTime.parse(
|
if (LocalDateTime.parse(
|
||||||
it.expiredAt,
|
it.expiredAt,
|
||||||
DateTimeFormatter.ISO_DATE_TIME
|
DateTimeFormatter.ISO_DATE_TIME
|
||||||
) > LocalDateTime.now()
|
) > LocalDateTime.now()
|
||||||
) {
|
) {
|
||||||
db.kindOfWorkDao().delete(it)
|
cacheDb.kindOfWorkDao().delete(it)
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -251,7 +255,7 @@ interface LecturerDao {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun cacheLecturer(lecturer: Lecturer) {
|
fun cacheLecturer(lecturer: Lecturer) {
|
||||||
db.lecturerDao().insert(
|
cacheDb.lecturerDao().insert(
|
||||||
LecturerDB(
|
LecturerDB(
|
||||||
lecturer.unnId,
|
lecturer.unnId,
|
||||||
lecturer.name,
|
lecturer.name,
|
||||||
@ -264,13 +268,13 @@ fun cacheLecturer(lecturer: Lecturer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun loadLecturer(unnId: Int): Lecturer? {
|
fun loadLecturer(unnId: Int): Lecturer? {
|
||||||
return db.lecturerDao().get(unnId)?.let {
|
return cacheDb.lecturerDao().get(unnId)?.let {
|
||||||
if (LocalDateTime.parse(
|
if (LocalDateTime.parse(
|
||||||
it.expiredAt,
|
it.expiredAt,
|
||||||
DateTimeFormatter.ISO_DATE_TIME
|
DateTimeFormatter.ISO_DATE_TIME
|
||||||
) > LocalDateTime.now()
|
) > LocalDateTime.now()
|
||||||
) {
|
) {
|
||||||
db.lecturerDao().delete(it)
|
cacheDb.lecturerDao().delete(it)
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -320,7 +324,7 @@ fun cacheSchedule(item: ScheduleUnit) {
|
|||||||
cacheKindOfWork(item.kindOfWork)
|
cacheKindOfWork(item.kindOfWork)
|
||||||
cacheLecturer(item.lecturers[0])
|
cacheLecturer(item.lecturers[0])
|
||||||
|
|
||||||
db.scheduleDao().insert(
|
cacheDb.scheduleDao().insert(
|
||||||
ScheduleUnitDB(
|
ScheduleUnitDB(
|
||||||
item.oid,
|
item.oid,
|
||||||
item.date.format(DateTimeFormatter.ISO_DATE),
|
item.date.format(DateTimeFormatter.ISO_DATE),
|
||||||
@ -347,7 +351,7 @@ fun cacheSchedule(items: ArrayList<ScheduleUnit>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun loadSchedule(oid: Int): ScheduleUnit? {
|
fun loadSchedule(oid: Int): ScheduleUnit? {
|
||||||
db.scheduleDao().getSchedule(oid)?.let {
|
cacheDb.scheduleDao().getSchedule(oid)?.let {
|
||||||
Log.d("load", it.oid.toString())
|
Log.d("load", it.oid.toString())
|
||||||
if (LocalDateTime.parse(
|
if (LocalDateTime.parse(
|
||||||
it.expiredAt,
|
it.expiredAt,
|
||||||
@ -355,7 +359,7 @@ fun loadSchedule(oid: Int): ScheduleUnit? {
|
|||||||
) < LocalDateTime.now()
|
) < LocalDateTime.now()
|
||||||
) {
|
) {
|
||||||
Log.d("delete", it.oid.toString())
|
Log.d("delete", it.oid.toString())
|
||||||
db.scheduleDao().delete(it)
|
cacheDb.scheduleDao().delete(it)
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -375,10 +379,10 @@ fun loadSchedule(oid: Int): ScheduleUnit? {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun loadSchedule(date: LocalDate): ArrayList<ScheduleUnit> {
|
fun loadSchedule(date: LocalDate): ArrayList<ScheduleUnit> {
|
||||||
db.scheduleDao().getSchedule(date.format(DateTimeFormatter.ISO_DATE))
|
cacheDb.scheduleDao().getSchedule(date.format(DateTimeFormatter.ISO_DATE))
|
||||||
.map { Log.d("meow", "${it.oid}: ${loadSchedule(it.oid)}") }
|
.map { Log.d("meow", "${it.oid}: ${loadSchedule(it.oid)}") }
|
||||||
return ArrayList(
|
return ArrayList(
|
||||||
db.scheduleDao().getSchedule(date.format(DateTimeFormatter.ISO_DATE))
|
cacheDb.scheduleDao().getSchedule(date.format(DateTimeFormatter.ISO_DATE))
|
||||||
.mapNotNull { loadSchedule(it.oid) }
|
.mapNotNull { loadSchedule(it.oid) }
|
||||||
)
|
)
|
||||||
}
|
}
|
@ -1,3 +1,8 @@
|
|||||||
|
/*
|
||||||
|
* Created by sweetbread
|
||||||
|
* Copyright (c) 2025. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
package ru.sweetbread.unn.db
|
package ru.sweetbread.unn.db
|
||||||
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
@ -8,10 +13,9 @@ import androidx.room.Entity
|
|||||||
import androidx.room.Insert
|
import androidx.room.Insert
|
||||||
import androidx.room.PrimaryKey
|
import androidx.room.PrimaryKey
|
||||||
import androidx.room.Query
|
import androidx.room.Query
|
||||||
import ru.sweetbread.unn.AvatarSet
|
import ru.sweetbread.unn.api.AvatarSet
|
||||||
import ru.sweetbread.unn.Type
|
import ru.sweetbread.unn.api.Type
|
||||||
import ru.sweetbread.unn.User
|
import ru.sweetbread.unn.api.User
|
||||||
import ru.sweetbread.unn.ui.layout.db
|
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
import java.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
import java.time.format.DateTimeFormatter
|
import java.time.format.DateTimeFormatter
|
||||||
@ -20,7 +24,6 @@ import java.time.format.DateTimeFormatter
|
|||||||
data class UserDB(
|
data class UserDB(
|
||||||
@PrimaryKey val userId: Int,
|
@PrimaryKey val userId: Int,
|
||||||
@ColumnInfo val unnId: Int?,
|
@ColumnInfo val unnId: Int?,
|
||||||
@ColumnInfo val bitrixId: Int,
|
|
||||||
@ColumnInfo val type: Type,
|
@ColumnInfo val type: Type,
|
||||||
@ColumnInfo val email: String,
|
@ColumnInfo val email: String,
|
||||||
@ColumnInfo val nameRu: String,
|
@ColumnInfo val nameRu: String,
|
||||||
@ -35,8 +38,8 @@ data class UserDB(
|
|||||||
|
|
||||||
@Dao
|
@Dao
|
||||||
interface UserDao {
|
interface UserDao {
|
||||||
@Query("SELECT * FROM userDB WHERE bitrixId = :bitrixId LIMIT 1")
|
@Query("SELECT * FROM userDB WHERE userId = :userId LIMIT 1")
|
||||||
fun getUserByBitrix(bitrixId: Int): UserDB?
|
fun getUserById(userId: Int): UserDB?
|
||||||
|
|
||||||
@Insert
|
@Insert
|
||||||
fun insert(user: UserDB)
|
fun insert(user: UserDB)
|
||||||
@ -48,11 +51,10 @@ interface UserDao {
|
|||||||
|
|
||||||
fun cacheUser(user: User) {
|
fun cacheUser(user: User) {
|
||||||
try {
|
try {
|
||||||
db.userDao().insert(
|
cacheDb.userDao().insert(
|
||||||
UserDB(
|
UserDB(
|
||||||
user.userId,
|
user.userId,
|
||||||
user.unnId,
|
user.unnId,
|
||||||
user.bitrixId,
|
|
||||||
user.type,
|
user.type,
|
||||||
user.email,
|
user.email,
|
||||||
user.nameRu,
|
user.nameRu,
|
||||||
@ -70,7 +72,7 @@ fun cacheUser(user: User) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun loadUserByBitrixId(bitrixId: Int): User? {
|
fun loadUserByBitrixId(bitrixId: Int): User? {
|
||||||
val user = db.userDao().getUserByBitrix(bitrixId)
|
val user = cacheDb.userDao().getUserById(bitrixId)
|
||||||
Log.d("UserDB", user?.nameEn ?: "None")
|
Log.d("UserDB", user?.nameEn ?: "None")
|
||||||
if (user == null) return null
|
if (user == null) return null
|
||||||
if (LocalDateTime.parse(
|
if (LocalDateTime.parse(
|
||||||
@ -78,12 +80,11 @@ fun loadUserByBitrixId(bitrixId: Int): User? {
|
|||||||
DateTimeFormatter.ISO_LOCAL_DATE_TIME
|
DateTimeFormatter.ISO_LOCAL_DATE_TIME
|
||||||
) < LocalDateTime.now()
|
) < LocalDateTime.now()
|
||||||
) {
|
) {
|
||||||
db.userDao().delete(user)
|
cacheDb.userDao().delete(user)
|
||||||
return null
|
return null
|
||||||
} else {
|
} else {
|
||||||
return User(
|
return User(
|
||||||
user.unnId,
|
user.unnId,
|
||||||
user.bitrixId,
|
|
||||||
user.userId,
|
user.userId,
|
||||||
user.type,
|
user.type,
|
||||||
user.email,
|
user.email,
|
||||||
|
@ -55,14 +55,14 @@ import coil.request.ImageRequest
|
|||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
import ru.sweetbread.unn.AvatarSet
|
|
||||||
import ru.sweetbread.unn.Post
|
|
||||||
import ru.sweetbread.unn.R
|
import ru.sweetbread.unn.R
|
||||||
import ru.sweetbread.unn.Type
|
import ru.sweetbread.unn.api.AvatarSet
|
||||||
import ru.sweetbread.unn.User
|
import ru.sweetbread.unn.api.Post
|
||||||
import ru.sweetbread.unn.getBlogposts
|
import ru.sweetbread.unn.api.Type
|
||||||
import ru.sweetbread.unn.getUserByBitrixId
|
import ru.sweetbread.unn.api.User
|
||||||
import ru.sweetbread.unn.portalURL
|
import ru.sweetbread.unn.api.getBlogposts
|
||||||
|
import ru.sweetbread.unn.api.getUserByBitrixId
|
||||||
|
import ru.sweetbread.unn.api.portalURL
|
||||||
import ru.sweetbread.unn.ui.theme.UNNTheme
|
import ru.sweetbread.unn.ui.theme.UNNTheme
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
import java.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
@ -73,8 +73,7 @@ import java.time.format.FormatStyle
|
|||||||
val defUser = User(
|
val defUser = User(
|
||||||
null,
|
null,
|
||||||
123,
|
123,
|
||||||
123,
|
Type.student,
|
||||||
Type.Student,
|
|
||||||
"cool.email@domain.com",
|
"cool.email@domain.com",
|
||||||
"Джон Сигма Омегович",
|
"Джон Сигма Омегович",
|
||||||
"Jon Sigma Omega",
|
"Jon Sigma Omega",
|
||||||
@ -241,7 +240,9 @@ fun UserItemPreview() {
|
|||||||
Modifier
|
Modifier
|
||||||
.width(300.dp)
|
.width(300.dp)
|
||||||
.clip(RoundedCornerShape(8.dp))
|
.clip(RoundedCornerShape(8.dp))
|
||||||
.background(MaterialTheme.colorScheme.primaryContainer), defUser, Type.Student.s
|
.background(MaterialTheme.colorScheme.primaryContainer),
|
||||||
|
defUser,
|
||||||
|
Type.student.s
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,15 +55,15 @@ import com.kizitonwose.calendar.core.WeekDay
|
|||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import ru.sweetbread.unn.Auditorium
|
|
||||||
import ru.sweetbread.unn.Building
|
|
||||||
import ru.sweetbread.unn.Discipline
|
|
||||||
import ru.sweetbread.unn.KindOfWork
|
|
||||||
import ru.sweetbread.unn.Lecturer
|
|
||||||
import ru.sweetbread.unn.LecturerRank
|
|
||||||
import ru.sweetbread.unn.R
|
import ru.sweetbread.unn.R
|
||||||
import ru.sweetbread.unn.ScheduleUnit
|
import ru.sweetbread.unn.api.Auditorium
|
||||||
import ru.sweetbread.unn.getScheduleDay
|
import ru.sweetbread.unn.api.Building
|
||||||
|
import ru.sweetbread.unn.api.Discipline
|
||||||
|
import ru.sweetbread.unn.api.KindOfWork
|
||||||
|
import ru.sweetbread.unn.api.Lecturer
|
||||||
|
import ru.sweetbread.unn.api.LecturerRank
|
||||||
|
import ru.sweetbread.unn.api.ScheduleUnit
|
||||||
|
import ru.sweetbread.unn.api.getScheduleDay
|
||||||
import ru.sweetbread.unn.ui.theme.UNNTheme
|
import ru.sweetbread.unn.ui.theme.UNNTheme
|
||||||
import splitties.resources.appStr
|
import splitties.resources.appStr
|
||||||
import splitties.resources.appStrArray
|
import splitties.resources.appStrArray
|
||||||
|
@ -44,7 +44,7 @@ import androidx.compose.ui.unit.dp
|
|||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import ru.sweetbread.unn.R
|
import ru.sweetbread.unn.R
|
||||||
import ru.sweetbread.unn.auth
|
import ru.sweetbread.unn.api.auth
|
||||||
import ru.sweetbread.unn.ui.theme.UNNTheme
|
import ru.sweetbread.unn.ui.theme.UNNTheme
|
||||||
import splitties.activities.start
|
import splitties.activities.start
|
||||||
import splitties.preferences.Preferences
|
import splitties.preferences.Preferences
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
package ru.sweetbread.unn.ui.layout
|
package ru.sweetbread.unn.ui.layout
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.Log
|
|
||||||
import androidx.activity.ComponentActivity
|
import androidx.activity.ComponentActivity
|
||||||
import androidx.activity.compose.setContent
|
import androidx.activity.compose.setContent
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
@ -60,50 +59,16 @@ import androidx.navigation.compose.composable
|
|||||||
import androidx.navigation.compose.currentBackStackEntryAsState
|
import androidx.navigation.compose.currentBackStackEntryAsState
|
||||||
import androidx.navigation.compose.rememberNavController
|
import androidx.navigation.compose.rememberNavController
|
||||||
import coil.compose.AsyncImage
|
import coil.compose.AsyncImage
|
||||||
import io.ktor.client.HttpClient
|
|
||||||
import io.ktor.client.engine.android.Android
|
|
||||||
import io.ktor.client.plugins.HttpRequestRetry
|
|
||||||
import io.ktor.client.plugins.HttpTimeout
|
|
||||||
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 kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import ru.sweetbread.unn.ME
|
|
||||||
import ru.sweetbread.unn.R
|
import ru.sweetbread.unn.R
|
||||||
import ru.sweetbread.unn.db.AppDatabase
|
import ru.sweetbread.unn.api.ME
|
||||||
import ru.sweetbread.unn.portalURL
|
import ru.sweetbread.unn.api.portalURL
|
||||||
import ru.sweetbread.unn.ui.composes.Blogposts
|
import ru.sweetbread.unn.ui.composes.Blogposts
|
||||||
import ru.sweetbread.unn.ui.composes.Schedule
|
import ru.sweetbread.unn.ui.composes.Schedule
|
||||||
import ru.sweetbread.unn.ui.theme.UNNTheme
|
import ru.sweetbread.unn.ui.theme.UNNTheme
|
||||||
import splitties.arch.room.roomDb
|
|
||||||
import splitties.resources.appStr
|
import splitties.resources.appStr
|
||||||
import splitties.toast.toast
|
import splitties.toast.toast
|
||||||
|
|
||||||
val client = HttpClient(Android) {
|
|
||||||
install(HttpCache)
|
|
||||||
install(Logging) {
|
|
||||||
logger = object : Logger {
|
|
||||||
override fun log(message: String) {
|
|
||||||
Log.i("Ktor", message)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
level = LogLevel.ALL
|
|
||||||
}
|
|
||||||
install(HttpTimeout) {
|
|
||||||
connectTimeoutMillis = 5000
|
|
||||||
}
|
|
||||||
install(HttpRequestRetry) {
|
|
||||||
retryOnException(maxRetries = 3, retryOnTimeout = true)
|
|
||||||
exponentialDelay()
|
|
||||||
modifyRequest { request ->
|
|
||||||
request.headers.append("x-retry-count", retryCount.toString())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val db = roomDb<AppDatabase>(name = "database")
|
|
||||||
|
|
||||||
class MainActivity : ComponentActivity() {
|
class MainActivity : ComponentActivity() {
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user