Compare commits
No commits in common. "dev" and "master" have entirely different histories.
@ -1,12 +1,6 @@
|
||||
plugins {
|
||||
alias(libs.plugins.androidApplication)
|
||||
alias(libs.plugins.jetbrainsKotlinAndroid)
|
||||
id("com.google.android.libraries.mapsplatform.secrets-gradle-plugin")
|
||||
|
||||
}
|
||||
|
||||
secrets {
|
||||
propertiesFileName = "secrets.properties"
|
||||
}
|
||||
|
||||
android {
|
||||
@ -42,7 +36,6 @@ android {
|
||||
buildFeatures {
|
||||
compose = true
|
||||
viewBinding = true
|
||||
buildConfig = true
|
||||
}
|
||||
composeOptions {
|
||||
kotlinCompilerExtensionVersion = "1.5.1"
|
||||
@ -55,10 +48,9 @@ android {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
coreLibraryDesugaring(libs.desugar.jdk.libs)
|
||||
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:1.5.0")
|
||||
|
||||
implementation(libs.androidx.core.ktx)
|
||||
implementation(libs.androidx.core.splashscreen)
|
||||
implementation(libs.androidx.lifecycle.runtime.ktx)
|
||||
implementation(libs.androidx.activity.compose)
|
||||
implementation(platform(libs.androidx.compose.bom))
|
||||
@ -79,19 +71,16 @@ dependencies {
|
||||
androidTestImplementation(libs.androidx.ui.test.junit4)
|
||||
debugImplementation(libs.androidx.ui.tooling)
|
||||
debugImplementation(libs.androidx.ui.test.manifest)
|
||||
|
||||
implementation(libs.androidx.navigation.compose)
|
||||
|
||||
implementation(libs.ktor.client.core)
|
||||
implementation(libs.ktor.client.cio)
|
||||
implementation(libs.ktor.client.logging)
|
||||
implementation(libs.coil.compose)
|
||||
|
||||
implementation(libs.androidx.datastore.preferences)
|
||||
implementation(libs.splitties.funpack.android.base.with.views.dsl)
|
||||
implementation("com.louiscad.splitties:splitties-fun-pack-android-base-with-views-dsl:3.0.0")
|
||||
|
||||
implementation(libs.compose)
|
||||
implementation("com.kizitonwose.calendar:compose:2.5.0")
|
||||
|
||||
implementation(libs.kefirbb)
|
||||
|
||||
implementation(libs.acra.http)
|
||||
}
|
@ -5,10 +5,9 @@
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
<application
|
||||
android:name=".ui.UNNApp"
|
||||
android:allowBackup="true"
|
||||
android:label="@string/app_name"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.UNN"
|
||||
@ -16,10 +15,6 @@
|
||||
<activity
|
||||
android:name=".ui.layout.MainActivity"
|
||||
android:exported="true"
|
||||
android:theme="@style/Theme.UNN" />
|
||||
<activity
|
||||
android:name=".ui.layout.LoginActivity"
|
||||
android:exported="true"
|
||||
android:theme="@style/Theme.UNN">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
@ -27,6 +22,10 @@
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".ui.layout.LoginActivity"
|
||||
android:exported="true"
|
||||
android:theme="@style/Theme.UNN"/>
|
||||
</application>
|
||||
|
||||
</manifest>
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 48 KiB |
@ -1,29 +1,24 @@
|
||||
package ru.sweetbread.unn.ui
|
||||
|
||||
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 org.json.JSONArray
|
||||
import org.json.JSONObject
|
||||
import ru.sweetbread.unn.R
|
||||
import ru.sweetbread.unn.ui.layout.LoginData
|
||||
import ru.sweetbread.unn.ui.layout.client
|
||||
import java.time.LocalDate
|
||||
import java.time.LocalDateTime
|
||||
import java.time.LocalTime
|
||||
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 ruzapiURL = "$portalURL/ruzapi"
|
||||
const val vuzapiURL = "$portalURL/bitrix/vuz/api"
|
||||
const val restURL = "$portalURL/rest"
|
||||
|
||||
enum class Type(val s: String) {
|
||||
Student("student"),
|
||||
@ -32,73 +27,55 @@ enum class Type(val s: String) {
|
||||
Auditorium("auditorium")
|
||||
}
|
||||
|
||||
enum class LecturerRank(val id: Int) {
|
||||
Assistant(R.string.assistant),
|
||||
Lecturer(R.string.lecturer),
|
||||
SLecturer(R.string.slecturer),
|
||||
AProfessor(R.string.aprofessor)
|
||||
enum class LecturerRank(val s: String) {
|
||||
Lecturer("Lecturer"),
|
||||
SLecturer("Senior Lecturer")
|
||||
}
|
||||
|
||||
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 ScheduleUnit(
|
||||
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 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 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 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 Lecturer (val name: String,
|
||||
val rank: LecturerRank,
|
||||
val email: String,
|
||||
val oid: Int,
|
||||
val uid: String)
|
||||
|
||||
class User (val unnId: Int?,
|
||||
val bitrixId: Int,
|
||||
val userId: Int,
|
||||
class User (val id: String,
|
||||
val uns: String,
|
||||
val type: Type,
|
||||
val email: String,
|
||||
val nameRu: String,
|
||||
val nameEn: String,
|
||||
val isMale: Boolean,
|
||||
val birthday: LocalDate,
|
||||
val avatar: ImageSet)
|
||||
|
||||
class Post(
|
||||
val id: Int,
|
||||
val authorId: Int,
|
||||
val enableComments: Boolean,
|
||||
val numComments: Int,
|
||||
val date: LocalDateTime,
|
||||
val content: String)
|
||||
|
||||
class ImageSet(val original: String,
|
||||
val thumbnail: String,
|
||||
val small: String)
|
||||
val name: String,
|
||||
val info: String)
|
||||
|
||||
/**
|
||||
* Authorize user by [login] and [password]
|
||||
*
|
||||
* Also defines local vars [PHPSESSID] and [ME]
|
||||
* Also defines local vars [PHPSESSID] and [ME.id]
|
||||
*/
|
||||
suspend fun auth(login: String = LoginData.login, password: String = LoginData.password, forced: Boolean = false): Boolean {
|
||||
if (!forced) {
|
||||
@ -117,67 +94,36 @@ suspend fun auth(login: String = LoginData.login, password: String = LoginData.p
|
||||
if (r.status.value == 302) {
|
||||
PHPSESSID = """PHPSESSID=([\w\d]+)""".toRegex().find(r.headers["Set-Cookie"]!!)!!.groupValues[1]
|
||||
getMyself(login)
|
||||
getCSRF()
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* Save info about current [User] in memory
|
||||
*/
|
||||
private suspend fun getMyself(login: String) {
|
||||
val studentinfo = JSONObject(client.get("$ruzapiURL/studentinfo") {
|
||||
val r = client.get("$ruzapiURL/studentinfo") {
|
||||
parameter("uns", login.substring(1))
|
||||
}.bodyAsText())
|
||||
|
||||
val user = JSONObject(
|
||||
client.get("$vuzapiURL/user") {
|
||||
header("Cookie", "PHPSESSID=${PHPSESSID}")
|
||||
}.bodyAsText()
|
||||
)
|
||||
|
||||
}
|
||||
val json = JSONObject(r.bodyAsText())
|
||||
ME = User(
|
||||
unnId = studentinfo.getString("id").toInt(),
|
||||
bitrixId = user.getInt("bitrix_id"),
|
||||
userId = user.getInt("id"),
|
||||
type = when(studentinfo.getString("type")) {
|
||||
id = json.getString("id"),
|
||||
uns = json.getString("uns"),
|
||||
type = when(json.getString("type")) {
|
||||
"lecturer" -> Type.Lecturer // ig,,,
|
||||
else -> Type.Student
|
||||
},
|
||||
email = user.getString("email"),
|
||||
nameRu = user.getString("fullname"),
|
||||
nameEn = user.getString("fullname_en"),
|
||||
isMale = user.getString("sex") == "M",
|
||||
birthday = LocalDate.parse(
|
||||
user.getString("birthdate"),
|
||||
DateTimeFormatter.ofPattern("yyyy-MM-dd")
|
||||
),
|
||||
avatar = user.getJSONObject("photo").let {
|
||||
ImageSet(
|
||||
it.getString("orig"),
|
||||
it.getString("thumbnail"),
|
||||
it.getString("small"),
|
||||
)
|
||||
}
|
||||
email = json.getString("email"),
|
||||
name = json.getString("fio"),
|
||||
info = json.getString("info")
|
||||
)
|
||||
}
|
||||
|
||||
suspend fun getSchedule(
|
||||
type: Type = ME.type,
|
||||
id: Int = ME.unnId!!,
|
||||
start: LocalDate,
|
||||
finish: LocalDate
|
||||
): ArrayList<ScheduleUnit> {
|
||||
val unnDatePattern = DateTimeFormatter.ofPattern("yyyy.MM.dd")
|
||||
|
||||
suspend fun getSchedule(type: Type = Type.Student, id: String = ME.id, start: LocalDate, finish: LocalDate): ArrayList<ScheduleUnit> {
|
||||
val r = client.get("$ruzapiURL/schedule/${type.s}/$id") {
|
||||
parameter("start", start.format(unnDatePattern))
|
||||
parameter("finish", finish.format(unnDatePattern))
|
||||
parameter("start", start.format(DateTimeFormatter.ofPattern("yyyy.MM.dd")))
|
||||
parameter("finish", finish.format(DateTimeFormatter.ofPattern("yyyy.MM.dd")))
|
||||
parameter("lng", "1")
|
||||
}
|
||||
val json = JSONArray(r.bodyAsText())
|
||||
|
||||
val out = arrayListOf<ScheduleUnit>()
|
||||
for (i in 0 until json.length()) {
|
||||
val unit = json.getJSONObject(i)
|
||||
@ -190,12 +136,10 @@ suspend fun getSchedule(
|
||||
Lecturer(
|
||||
name = lecturer.getString("lecturer"),
|
||||
email = lecturer.getString("lecturerEmail"),
|
||||
unnId = lecturer.getInt("lecturerOid"),
|
||||
oid = lecturer.getInt("lecturerOid"),
|
||||
uid = lecturer.getString("lecturerUID"),
|
||||
rank = when (lecturer.getString("lecturer_rank")) {
|
||||
"АССИСТ" -> LecturerRank.Assistant
|
||||
"СТПРЕП" -> LecturerRank.SLecturer
|
||||
"ДОЦЕНТ" -> LecturerRank.AProfessor
|
||||
else -> LecturerRank.Lecturer
|
||||
}
|
||||
)
|
||||
@ -204,7 +148,6 @@ suspend fun getSchedule(
|
||||
|
||||
out.add(
|
||||
ScheduleUnit(
|
||||
oid = unit.getInt("lessonOid"),
|
||||
auditorium = Auditorium(
|
||||
name = unit.getString("auditorium"),
|
||||
oid = unit.getInt("auditoriumOid"),
|
||||
@ -215,7 +158,7 @@ suspend fun getSchedule(
|
||||
oid = unit.getInt("buildingOid")
|
||||
)
|
||||
),
|
||||
date = LocalDate.parse(unit.getString("date"), unnDatePattern),
|
||||
date = LocalDate.parse(unit.getString("date"), DateTimeFormatter.ofPattern("yyyy.MM.dd")),
|
||||
discipline = Discipline(
|
||||
name = unit.getString("discipline"),
|
||||
oid = unit.getInt("disciplineOid"),
|
||||
@ -236,79 +179,3 @@ suspend fun getSchedule(
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
suspend fun getCSRF() {
|
||||
val r = client.get("$restURL/log.blogpost.get") {
|
||||
header("Cookie", "PHPSESSID=${PHPSESSID}")
|
||||
parameter("sessid", "")
|
||||
}
|
||||
CSRF = JSONObject(r.bodyAsText()).getString("sessid")
|
||||
}
|
||||
|
||||
suspend fun getBlogposts(): ArrayList<Post> {
|
||||
val r = client.get("$restURL/log.blogpost.get") {
|
||||
header("Cookie", "PHPSESSID=${PHPSESSID}")
|
||||
parameter("sessid", CSRF)
|
||||
}
|
||||
val json = JSONObject(r.bodyAsText())
|
||||
val result = json.getJSONArray("result")
|
||||
|
||||
val out = arrayListOf<Post>()
|
||||
for (i in 0 until result.length()) {
|
||||
val el = result.getJSONObject(i)
|
||||
out.add(
|
||||
Post(
|
||||
id = el.getString("ID").toInt(),
|
||||
authorId = el.getString("AUTHOR_ID").toInt(),
|
||||
enableComments = el.getString("ENABLE_COMMENTS") == "Y",
|
||||
numComments = el.getString("NUM_COMMENTS").toInt(),
|
||||
date = LocalDateTime.parse(
|
||||
el.getString("DATE_PUBLISH"),
|
||||
DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss'+03:00'")
|
||||
),
|
||||
content = el.getString("DETAIL_TEXT")
|
||||
)
|
||||
)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
suspend fun getUserByBitrixId(id: Int): User {
|
||||
val userId = JSONObject(client.get("$vuzapiURL/user/bx/$id") {
|
||||
header("Cookie", "PHPSESSID=${PHPSESSID}")
|
||||
}.bodyAsText()).getInt("id")
|
||||
return getUser(userId)
|
||||
}
|
||||
|
||||
suspend fun getUser(id: Int): User {
|
||||
val json = JSONObject(
|
||||
client.get("$vuzapiURL/user/$id") {
|
||||
header("Cookie", "PHPSESSID=${PHPSESSID}")
|
||||
}.bodyAsText()
|
||||
)
|
||||
|
||||
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
|
||||
},
|
||||
email = json.getString("email"),
|
||||
nameRu = json.getString("fullname"),
|
||||
nameEn = json.getString("fullname_en"),
|
||||
isMale = json.getString("sex") == "M",
|
||||
birthday = LocalDate.parse(
|
||||
json.getString("birthdate"),
|
||||
DateTimeFormatter.ofPattern("yyyy-MM-dd")
|
||||
),
|
||||
avatar = json.getJSONObject("photo").let {
|
||||
ImageSet(
|
||||
it.getString("orig"),
|
||||
it.getString("thumbnail"),
|
||||
it.getString("small"),
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
package ru.sweetbread.unn.ui
|
||||
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import org.acra.config.httpSender
|
||||
import org.acra.data.StringFormat
|
||||
import org.acra.ktx.initAcra
|
||||
import org.acra.sender.HttpSender
|
||||
import ru.sweetbread.unn.BuildConfig
|
||||
|
||||
class UNNApp : Application() {
|
||||
override fun attachBaseContext(base: Context) {
|
||||
super.attachBaseContext(base)
|
||||
|
||||
initAcra {
|
||||
buildConfigClass = BuildConfig::class.java
|
||||
reportFormat = StringFormat.JSON
|
||||
httpSender {
|
||||
uri = BuildConfig.ACRA_URL
|
||||
basicAuthLogin = BuildConfig.ACRA_LOGIN
|
||||
basicAuthPassword = BuildConfig.ACRA_PASS
|
||||
httpMethod = HttpSender.Method.POST
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,261 +0,0 @@
|
||||
package ru.sweetbread.unn.ui.composes
|
||||
|
||||
import android.text.util.Linkify
|
||||
import android.util.Log
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.LinearProgressIndicator
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.NonRestartableComposable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.toArgb
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontStyle
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.viewinterop.AndroidView
|
||||
import androidx.core.text.HtmlCompat
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import coil.compose.AsyncImage
|
||||
import com.google.android.material.textview.MaterialTextView
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import org.kefirsf.bb.BBProcessorFactory
|
||||
import org.kefirsf.bb.TextProcessor
|
||||
import ru.sweetbread.unn.R
|
||||
import ru.sweetbread.unn.ui.ImageSet
|
||||
import ru.sweetbread.unn.ui.Post
|
||||
import ru.sweetbread.unn.ui.Type
|
||||
import ru.sweetbread.unn.ui.User
|
||||
import ru.sweetbread.unn.ui.getBlogposts
|
||||
import ru.sweetbread.unn.ui.getUserByBitrixId
|
||||
import ru.sweetbread.unn.ui.portalURL
|
||||
import ru.sweetbread.unn.ui.theme.UNNTheme
|
||||
import java.time.LocalDate
|
||||
import java.time.LocalDateTime
|
||||
import java.time.format.DateTimeFormatter
|
||||
import java.time.format.FormatStyle
|
||||
|
||||
|
||||
val defUser = User(
|
||||
null,
|
||||
123,
|
||||
123,
|
||||
Type.Student,
|
||||
"cool.email@domain.com",
|
||||
"Джон Сигма Омегович",
|
||||
"Jon Sigma Omega",
|
||||
true,
|
||||
LocalDate.now(),
|
||||
ImageSet(
|
||||
"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"
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@Composable
|
||||
fun Blogposts(viewModel: PostViewModel = viewModel()) {
|
||||
val posts by viewModel.posts.collectAsState()
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
viewModel.loadPosts()
|
||||
}
|
||||
|
||||
if (posts.isNotEmpty()) {
|
||||
Log.d("Another fuck", posts.size.toString())
|
||||
LazyColumn {
|
||||
items(posts) {
|
||||
PostItem(
|
||||
Modifier
|
||||
.padding(8.dp)
|
||||
.clip(RoundedCornerShape(16.dp))
|
||||
.background(MaterialTheme.colorScheme.secondaryContainer),
|
||||
post = it
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LinearProgressIndicator(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(8.dp),
|
||||
color = MaterialTheme.colorScheme.surfaceVariant,
|
||||
trackColor = MaterialTheme.colorScheme.secondary,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class PostRepository {
|
||||
suspend fun loadPosts(): List<Post> {
|
||||
return getBlogposts()
|
||||
}
|
||||
}
|
||||
|
||||
class PostViewModel : ViewModel() {
|
||||
private val repository = PostRepository()
|
||||
private val _posts = MutableStateFlow<List<Post>>(emptyList())
|
||||
val posts: StateFlow<List<Post>> = _posts.asStateFlow()
|
||||
|
||||
suspend fun loadPosts() {
|
||||
_posts.value = repository.loadPosts()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Composable
|
||||
@NonRestartableComposable
|
||||
fun UserItem(modifier: Modifier = Modifier, user: User, info: String? = null) {
|
||||
Row(
|
||||
modifier.padding(16.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.SpaceBetween
|
||||
) {
|
||||
AsyncImage(
|
||||
modifier = Modifier
|
||||
.padding(end = 8.dp)
|
||||
.size(48.dp)
|
||||
.clip(RoundedCornerShape(50)),
|
||||
model = portalURL + user.avatar.thumbnail,
|
||||
contentDescription = user.nameEn
|
||||
)
|
||||
|
||||
Column {
|
||||
Text(user.nameRu, fontWeight = FontWeight.Bold)
|
||||
if (!info.isNullOrBlank())
|
||||
Text(
|
||||
text = info,
|
||||
fontStyle = FontStyle.Italic,
|
||||
fontSize = MaterialTheme.typography.labelLarge.fontSize
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@NonRestartableComposable
|
||||
fun PostItem(modifier: Modifier = Modifier, post: Post) {
|
||||
var user: User? by remember { mutableStateOf(null) }
|
||||
val processor = remember { BBProcessorFactory.getInstance().create() }
|
||||
var html: String by remember { mutableStateOf("") }
|
||||
|
||||
|
||||
LaunchedEffect(post) {
|
||||
html = toHtml(processor, post)
|
||||
user = getUserByBitrixId(post.authorId)
|
||||
}
|
||||
|
||||
Column(modifier.padding(16.dp)) {
|
||||
if (user != null)
|
||||
UserItem(user = user!!)
|
||||
else
|
||||
LinearProgressIndicator(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(8.dp),
|
||||
color = MaterialTheme.colorScheme.surfaceVariant,
|
||||
trackColor = MaterialTheme.colorScheme.secondary,
|
||||
)
|
||||
|
||||
AndroidView(
|
||||
factory = {
|
||||
MaterialTextView(it).apply {
|
||||
autoLinkMask = Linkify.WEB_URLS
|
||||
linksClickable = true
|
||||
setLinkTextColor(Color.White.toArgb())
|
||||
}
|
||||
},
|
||||
update = {
|
||||
it.maxLines = 25
|
||||
it.text = HtmlCompat.fromHtml(html, 0)
|
||||
}
|
||||
)
|
||||
|
||||
HorizontalDivider(
|
||||
modifier = Modifier.padding(vertical = 16.dp),
|
||||
thickness = 1.dp,
|
||||
color = MaterialTheme.colorScheme.onBackground
|
||||
)
|
||||
|
||||
Text(text = post.date.format(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM)))
|
||||
}
|
||||
}
|
||||
|
||||
private fun toHtml(
|
||||
processor: TextProcessor,
|
||||
post: Post
|
||||
): String {
|
||||
val html = processor.process(post.content)
|
||||
return html.replace("""\[URL=(.+)](.+)\[/URL]""".toRegex()) {
|
||||
Log.d("replace", it.groups.toString())
|
||||
"<a href='${it.groups[1]?.value}'>${it.groups[2]?.value}</a>"
|
||||
}.replace("""(\[FONT=.+]|\[CENTER])(.+)(\[/FONT]|\[/CENTER])""".toRegex()) {
|
||||
it.groups[2]?.value.toString()
|
||||
}.replace("""\[IMG .+].+\[/IMG]""".toRegex(), "")
|
||||
}
|
||||
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun UserItemPreview() {
|
||||
UNNTheme {
|
||||
Surface {
|
||||
UserItem(
|
||||
Modifier
|
||||
.width(300.dp)
|
||||
.clip(RoundedCornerShape(8.dp))
|
||||
.background(MaterialTheme.colorScheme.primaryContainer), defUser, Type.Student.s
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun PostItemPreview() {
|
||||
val post = Post(
|
||||
id = 154923,
|
||||
authorId = 165945,
|
||||
enableComments = true,
|
||||
numComments = 0,
|
||||
date = LocalDateTime.of(2024, 3, 20, 18, 55, 20),
|
||||
content = stringResource(id = R.string.lorem)
|
||||
)
|
||||
|
||||
UNNTheme {
|
||||
Surface {
|
||||
PostItem(
|
||||
Modifier
|
||||
.clip(RoundedCornerShape(8.dp))
|
||||
.background(MaterialTheme.colorScheme.primaryContainer), post
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
@ -1,10 +1,8 @@
|
||||
package ru.sweetbread.unn.ui.composes
|
||||
|
||||
import android.util.Log
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
@ -15,7 +13,6 @@ import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.LinearProgressIndicator
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Surface
|
||||
@ -23,7 +20,6 @@ import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableIntStateOf
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
@ -31,7 +27,6 @@ import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
@ -41,7 +36,6 @@ import com.kizitonwose.calendar.compose.WeekCalendar
|
||||
import com.kizitonwose.calendar.compose.weekcalendar.rememberWeekCalendarState
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import ru.sweetbread.unn.R
|
||||
import ru.sweetbread.unn.ui.Auditorium
|
||||
import ru.sweetbread.unn.ui.Building
|
||||
import ru.sweetbread.unn.ui.Discipline
|
||||
@ -53,14 +47,13 @@ import ru.sweetbread.unn.ui.getSchedule
|
||||
import ru.sweetbread.unn.ui.theme.UNNTheme
|
||||
import java.time.DayOfWeek
|
||||
import java.time.LocalDate
|
||||
import java.time.LocalDateTime
|
||||
import java.time.LocalTime
|
||||
import java.time.format.DateTimeFormatter
|
||||
|
||||
@Composable
|
||||
fun Schedule() {
|
||||
val state = rememberWeekCalendarState(
|
||||
firstDayOfWeek = DayOfWeek.MONDAY // TODO: set start and end weeks to September and July of current year
|
||||
firstDayOfWeek = DayOfWeek.MONDAY
|
||||
)
|
||||
|
||||
Column {
|
||||
@ -73,10 +66,14 @@ fun Schedule() {
|
||||
.padding(vertical = 16.dp)
|
||||
.aspectRatio(1f) // This is important for square sizing!
|
||||
.offset(2.dp)
|
||||
.background(if (it.date == curDate) MaterialTheme.colorScheme.inversePrimary else MaterialTheme.colorScheme.surfaceContainer)
|
||||
.background(if (it.date == curDate) MaterialTheme.colorScheme.primaryContainer else MaterialTheme.colorScheme.secondaryContainer)
|
||||
.clickable(
|
||||
onClick = { curDate = it.date },
|
||||
enabled = curDate != it.date
|
||||
onClick = {
|
||||
curDate = it.date
|
||||
Log.d("Here bug (olClick)",
|
||||
curDate.format(DateTimeFormatter.ISO_DATE)
|
||||
)
|
||||
}
|
||||
),
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
@ -96,16 +93,12 @@ fun ScheduleDay(modifier: Modifier = Modifier, date: LocalDate) {
|
||||
val scope = rememberCoroutineScope()
|
||||
var loadedDate by remember { mutableStateOf(LocalDate.MIN) }
|
||||
val lessons = remember { mutableListOf<ScheduleUnit>() }
|
||||
var expanded by remember { mutableIntStateOf(0) }
|
||||
|
||||
if (loadedDate == date) {
|
||||
Log.d("Loaded", "${date.format(DateTimeFormatter.ISO_DATE)} ${lessons.size}")
|
||||
LazyColumn (modifier) {
|
||||
items(lessons) { // TODO: Add empty list notification
|
||||
ScheduleItem(unit = it, modifier = Modifier.clickable {
|
||||
expanded = if (it.oid == expanded) 0
|
||||
else it.oid
|
||||
}, expanded = expanded == it.oid)
|
||||
items(lessons) {
|
||||
ScheduleItem(unit = it)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -121,134 +114,43 @@ fun ScheduleDay(modifier: Modifier = Modifier, date: LocalDate) {
|
||||
lessons.clear()
|
||||
lessons.addAll(getSchedule(start = date, finish = date))
|
||||
loadedDate = date
|
||||
Log.d("Loading", "${date.format(DateTimeFormatter.ISO_DATE)} ${lessons.size}")
|
||||
Log.d("Here bug", "${loadedDate.format(DateTimeFormatter.ISO_DATE)} ${date.format(DateTimeFormatter.ISO_DATE)}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ScheduleItem(modifier: Modifier = Modifier, unit: ScheduleUnit, expanded: Boolean = false) {
|
||||
val begin = unit.begin.format(DateTimeFormatter.ofPattern("HH:mm"))
|
||||
val end = unit.end.format(DateTimeFormatter.ofPattern("HH:mm"))
|
||||
|
||||
fun ScheduleItem(modifier: Modifier = Modifier, unit: ScheduleUnit) {
|
||||
Row (
|
||||
modifier
|
||||
.fillMaxWidth()
|
||||
.padding(4.dp)
|
||||
.clip(RoundedCornerShape(8.dp))
|
||||
.background(
|
||||
if ((LocalDateTime.of(
|
||||
unit.date,
|
||||
unit.begin
|
||||
) < LocalDateTime.now()) and (LocalDateTime.now() < LocalDateTime.of(
|
||||
unit.date,
|
||||
unit.end
|
||||
))
|
||||
)
|
||||
MaterialTheme.colorScheme.primaryContainer
|
||||
else MaterialTheme.colorScheme.secondaryContainer
|
||||
)
|
||||
.background(MaterialTheme.colorScheme.primaryContainer)
|
||||
.padding(8.dp)
|
||||
){
|
||||
Column (Modifier.weight(1f)) {
|
||||
Column {
|
||||
Text(
|
||||
text = unit.discipline.name,
|
||||
fontWeight = FontWeight.Bold,
|
||||
modifier = Modifier.zIndex(1f),
|
||||
maxLines = if (expanded) Int.MAX_VALUE else 1,
|
||||
overflow = TextOverflow.Ellipsis
|
||||
)
|
||||
}
|
||||
|
||||
AnimatedVisibility (expanded) {
|
||||
HorizontalDivider(
|
||||
modifier = Modifier.padding(vertical = 16.dp),
|
||||
thickness = 1.dp,
|
||||
color = MaterialTheme.colorScheme.onBackground
|
||||
)
|
||||
}
|
||||
|
||||
Column {
|
||||
Text(
|
||||
text = unit.kindOfWork.name,
|
||||
overflow = TextOverflow.Ellipsis
|
||||
)
|
||||
AnimatedVisibility (expanded) {
|
||||
Text(text = unit.stream)
|
||||
}
|
||||
}
|
||||
|
||||
AnimatedVisibility (expanded) {
|
||||
HorizontalDivider(
|
||||
modifier = Modifier.padding(vertical = 16.dp),
|
||||
thickness = 1.dp,
|
||||
color = MaterialTheme.colorScheme.onBackground
|
||||
)
|
||||
}
|
||||
|
||||
AnimatedVisibility (!expanded) {
|
||||
Row(Modifier) {
|
||||
Text(
|
||||
text = unit.auditorium.name,
|
||||
fontWeight = FontWeight.Bold,
|
||||
modifier = Modifier.padding(end = 4.dp)
|
||||
)
|
||||
Text(
|
||||
text = unit.auditorium.building.name,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis
|
||||
)
|
||||
}
|
||||
}
|
||||
AnimatedVisibility (expanded) {
|
||||
Column {
|
||||
Text(
|
||||
text = "${stringResource(R.string.auditorium)}: ${unit.auditorium.name}",
|
||||
fontWeight = FontWeight.Bold,
|
||||
modifier = Modifier.padding(end = 4.dp)
|
||||
)
|
||||
Text(
|
||||
text = "${stringResource(R.string.building)}: ${unit.auditorium.building.name}",
|
||||
overflow = TextOverflow.Ellipsis
|
||||
)
|
||||
if (unit.auditorium.floor != 0) {
|
||||
Text(
|
||||
text = "${stringResource(R.string.floor)}: ${unit.auditorium.floor}",
|
||||
overflow = TextOverflow.Ellipsis
|
||||
)
|
||||
}
|
||||
|
||||
HorizontalDivider(
|
||||
modifier = Modifier.padding(vertical = 16.dp),
|
||||
thickness = 1.dp,
|
||||
color = MaterialTheme.colorScheme.onBackground
|
||||
)
|
||||
|
||||
Column {
|
||||
Text(text = unit.lecturers[0].name, fontWeight = FontWeight.Bold)
|
||||
Text(text = stringResource(unit.lecturers[0].rank.id))
|
||||
}
|
||||
|
||||
HorizontalDivider(
|
||||
modifier = Modifier.padding(vertical = 16.dp),
|
||||
thickness = 1.dp,
|
||||
color = MaterialTheme.colorScheme.onBackground
|
||||
)
|
||||
|
||||
Row (Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween) {
|
||||
Text(begin.toString(), fontWeight = FontWeight.Bold)
|
||||
Text(end.toString())
|
||||
}
|
||||
}
|
||||
Text(
|
||||
text = unit.discipline.name,
|
||||
fontWeight = FontWeight.Bold,
|
||||
modifier = Modifier.zIndex(1f),
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis
|
||||
)
|
||||
Text(text = unit.kindOfWork.name, maxLines = 1, overflow = TextOverflow.Ellipsis)
|
||||
Row (Modifier) {
|
||||
Text(text = unit.auditorium.name, fontWeight = FontWeight.Bold, modifier = Modifier.padding(end = 4.dp))
|
||||
Text(text = unit.auditorium.building.name, maxLines = 1, overflow = TextOverflow.Ellipsis)
|
||||
}
|
||||
}
|
||||
|
||||
AnimatedVisibility (!expanded) {
|
||||
Column {
|
||||
Text(begin.toString(), fontWeight = FontWeight.Bold)
|
||||
Text(end.toString())
|
||||
}
|
||||
Column {
|
||||
val begin = unit.begin.format(DateTimeFormatter.ofPattern("HH:mm"))
|
||||
val end = unit.end.format(DateTimeFormatter.ofPattern("HH:mm"))
|
||||
Text(begin.toString(), fontWeight = FontWeight.Bold)
|
||||
Text(end.toString())
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -257,7 +159,6 @@ fun ScheduleItem(modifier: Modifier = Modifier, unit: ScheduleUnit, expanded: Bo
|
||||
@Composable
|
||||
fun ScheduleItemPreview() {
|
||||
val unit = ScheduleUnit(
|
||||
oid = 1,
|
||||
Auditorium(
|
||||
name = "с/з 1(110)",
|
||||
oid = 3752,
|
||||
@ -285,8 +186,8 @@ fun ScheduleItemPreview() {
|
||||
name = "Фамилия Имя Отчество",
|
||||
rank = LecturerRank.SLecturer,
|
||||
email = "",
|
||||
unnId = 28000,
|
||||
uid = "51000"
|
||||
oid = 28407,
|
||||
uid = "51769"
|
||||
)
|
||||
),
|
||||
stream = "3823Б1ПР1|3823Б1ПР2|3823Б1ПР3|3823Б1ПР4|3823Б1ПР5-В-OUP",
|
||||
@ -295,56 +196,9 @@ fun ScheduleItemPreview() {
|
||||
)
|
||||
|
||||
UNNTheme {
|
||||
// A surface container using the 'background' color from the theme
|
||||
Surface(color = MaterialTheme.colorScheme.background) {
|
||||
ScheduleItem(unit = unit)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun ScheduleExpandedItemPreview() {
|
||||
val unit = ScheduleUnit(
|
||||
oid = 1,
|
||||
Auditorium(
|
||||
name = "с/з 1(110)",
|
||||
oid = 3752,
|
||||
floor = 0,
|
||||
building = Building(
|
||||
name = "Корпус 6",
|
||||
gid = 30,
|
||||
oid = 155
|
||||
),
|
||||
),
|
||||
date = LocalDate.of(2024, 3, 11),
|
||||
discipline = Discipline(
|
||||
name = "Физическая культура и спорт (элективная дисциплина)",
|
||||
oid = 67895,
|
||||
type = 0
|
||||
),
|
||||
kindOfWork = KindOfWork(
|
||||
name = "Практика (семинарские занятия)",
|
||||
oid = 261,
|
||||
uid = "281474976710661",
|
||||
complexity = 1
|
||||
),
|
||||
lecturers = arrayListOf(
|
||||
Lecturer(
|
||||
name = "Фамилия Имя Отчество",
|
||||
rank = LecturerRank.SLecturer,
|
||||
email = "",
|
||||
unnId = 28000,
|
||||
uid = "51000"
|
||||
)
|
||||
),
|
||||
stream = "3823Б1ПР1|3823Б1ПР2|3823Б1ПР3|3823Б1ПР4|3823Б1ПР5-В-OUP",
|
||||
begin = LocalTime.of(10, 50),
|
||||
end = LocalTime.of(12, 20)
|
||||
)
|
||||
|
||||
UNNTheme {
|
||||
Surface(color = MaterialTheme.colorScheme.background) {
|
||||
ScheduleItem(unit = unit, expanded = true)
|
||||
}
|
||||
}
|
||||
}
|
@ -36,30 +36,14 @@ import androidx.compose.ui.text.input.PasswordVisualTransformation
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import ru.sweetbread.unn.R
|
||||
import ru.sweetbread.unn.ui.auth
|
||||
import ru.sweetbread.unn.ui.theme.UNNTheme
|
||||
import splitties.activities.start
|
||||
import splitties.preferences.Preferences
|
||||
|
||||
object LoginData : Preferences("loginData") {
|
||||
var login by stringPref("login", "")
|
||||
var password by stringPref("password", "")
|
||||
}
|
||||
|
||||
class LoginActivity : ComponentActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
if ((LoginData.login != "") and (LoginData.password != ""))
|
||||
runBlocking {
|
||||
if (auth()) {
|
||||
start<MainActivity>()
|
||||
finish()
|
||||
}
|
||||
}
|
||||
|
||||
setContent {
|
||||
UNNTheme {
|
||||
Surface(
|
||||
@ -78,14 +62,13 @@ class LoginActivity : ComponentActivity() {
|
||||
LoginData.login = login
|
||||
LoginData.password = password
|
||||
start<MainActivity>()
|
||||
finish()
|
||||
}, {
|
||||
scope.launch {
|
||||
|
||||
snackbarHostState
|
||||
.showSnackbar(
|
||||
message = "Error",
|
||||
duration = SnackbarDuration.Short
|
||||
duration = SnackbarDuration.Long
|
||||
)
|
||||
}
|
||||
})
|
||||
|
@ -4,39 +4,85 @@ import android.os.Bundle
|
||||
import android.util.Log
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.aspectRatio
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.offset
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.AccountBox
|
||||
import androidx.compose.material.icons.filled.DateRange
|
||||
import androidx.compose.material.icons.filled.Home
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.LinearProgressIndicator
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.NavigationBar
|
||||
import androidx.compose.material3.NavigationBarItem
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.zIndex
|
||||
import androidx.navigation.NavType
|
||||
import androidx.navigation.compose.NavHost
|
||||
import androidx.navigation.compose.composable
|
||||
import androidx.navigation.compose.rememberNavController
|
||||
import androidx.navigation.navArgument
|
||||
import com.kizitonwose.calendar.compose.WeekCalendar
|
||||
import com.kizitonwose.calendar.compose.weekcalendar.rememberWeekCalendarState
|
||||
import io.ktor.client.HttpClient
|
||||
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 ru.sweetbread.unn.ui.composes.Blogposts
|
||||
import ru.sweetbread.unn.ui.composes.Schedule
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import ru.sweetbread.unn.ui.Auditorium
|
||||
import ru.sweetbread.unn.ui.Building
|
||||
import ru.sweetbread.unn.ui.Discipline
|
||||
import ru.sweetbread.unn.ui.KindOfWork
|
||||
import ru.sweetbread.unn.ui.Lecturer
|
||||
import ru.sweetbread.unn.ui.LecturerRank
|
||||
import ru.sweetbread.unn.ui.ScheduleUnit
|
||||
import ru.sweetbread.unn.ui.auth
|
||||
import ru.sweetbread.unn.ui.getSchedule
|
||||
import ru.sweetbread.unn.ui.theme.UNNTheme
|
||||
import splitties.activities.start
|
||||
import splitties.preferences.Preferences
|
||||
import splitties.toast.toast
|
||||
import java.io.File
|
||||
import java.time.DayOfWeek
|
||||
import java.time.LocalDate
|
||||
import java.time.LocalTime
|
||||
import java.time.format.DateTimeFormatter
|
||||
import io.ktor.client.plugins.logging.*
|
||||
import ru.sweetbread.unn.ui.composes.Schedule
|
||||
import ru.sweetbread.unn.ui.composes.ScheduleDay
|
||||
|
||||
object LoginData : Preferences("loginData") {
|
||||
var login by stringPref("login", "")
|
||||
var password by stringPref("password", "")
|
||||
}
|
||||
|
||||
val client = HttpClient {
|
||||
install(HttpCache)
|
||||
@ -60,50 +106,46 @@ val client = HttpClient {
|
||||
}
|
||||
}
|
||||
|
||||
val cacheDir = File("/data/data/ru.sweetbread.unn/files/cache")
|
||||
|
||||
class MainActivity : ComponentActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
Log.d("mkdir", cacheDir.mkdir().toString())
|
||||
|
||||
|
||||
if (LoginData.login.isEmpty() or LoginData.password.isEmpty()) start<LoginActivity>()
|
||||
runBlocking {
|
||||
if (!auth()) start<LoginActivity>()
|
||||
}
|
||||
|
||||
setContent {
|
||||
UNNTheme {
|
||||
// A surface container using the 'background' color from the theme
|
||||
Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background) {
|
||||
val navController = rememberNavController()
|
||||
var route by remember { mutableStateOf("portal/blogposts") }
|
||||
|
||||
Scaffold(
|
||||
bottomBar = {
|
||||
NavigationBar {
|
||||
NavigationBarItem(
|
||||
onClick = {
|
||||
route = "portal/blogposts"
|
||||
navController.navigate(route)
|
||||
},
|
||||
onClick = { toast("Not implemented") },
|
||||
icon = {
|
||||
Icon(
|
||||
Icons.Filled.Home,
|
||||
contentDescription = "Home"
|
||||
)
|
||||
},
|
||||
selected = route.startsWith("portal/")
|
||||
selected = navController.currentDestination?.route?.startsWith("home") ?: false
|
||||
)
|
||||
|
||||
NavigationBarItem(
|
||||
onClick = {
|
||||
route = "journal/schedule"
|
||||
navController.navigate(route)
|
||||
},
|
||||
onClick = { navController.navigate("schedule/student/me/today")
|
||||
Log.d("route", navController.currentDestination?.route.toString())},
|
||||
icon = {
|
||||
Icon(
|
||||
Icons.Filled.DateRange,
|
||||
contentDescription = "Schedule"
|
||||
)
|
||||
},
|
||||
selected = route.startsWith("journal/")
|
||||
selected = navController.currentDestination?.route?.startsWith("schedule") ?: false
|
||||
)
|
||||
|
||||
NavigationBarItem(
|
||||
onClick = { toast("Not implemented") },
|
||||
icon = {
|
||||
@ -116,13 +158,19 @@ class MainActivity : ComponentActivity() {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
) {innerPadding ->
|
||||
Box(Modifier.padding(innerPadding)) {
|
||||
NavHost(navController, startDestination = "portal/blogposts") {
|
||||
composable("portal/blogposts") {
|
||||
Blogposts()
|
||||
NavHost(navController, startDestination = "home/blogposts") {
|
||||
composable("home/blogposts") {
|
||||
Text("Not implemented")
|
||||
}
|
||||
composable("journal/schedule") {
|
||||
composable("schedule/{type}/{who}/{when}",
|
||||
arguments = listOf(
|
||||
navArgument("type") { type = NavType.StringType },
|
||||
navArgument("who") { type = NavType.StringType },
|
||||
navArgument("when") { type = NavType.StringType },)
|
||||
) {
|
||||
Schedule()
|
||||
}
|
||||
}
|
||||
|
170
app/src/main/res/drawable/ic_launcher_background.xml
Normal file
@ -0,0 +1,170 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<path
|
||||
android:fillColor="#3DDC84"
|
||||
android:pathData="M0,0h108v108h-108z" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M9,0L9,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,0L19,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,0L29,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,0L39,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,0L49,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,0L59,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,0L69,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,0L79,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M89,0L89,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M99,0L99,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,9L108,9"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,19L108,19"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,29L108,29"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,39L108,39"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,49L108,49"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,59L108,59"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,69L108,69"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,79L108,79"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,89L108,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,99L108,99"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,29L89,29"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,39L89,39"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,49L89,49"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,59L89,59"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,69L89,69"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,79L89,79"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,19L29,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,19L39,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,19L49,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,19L59,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,19L69,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,19L79,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
</vector>
|
30
app/src/main/res/drawable/ic_launcher_foreground.xml
Normal file
@ -0,0 +1,30 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:endX="85.84757"
|
||||
android:endY="92.4963"
|
||||
android:startX="42.9492"
|
||||
android:startY="49.59793"
|
||||
android:type="linear">
|
||||
<item
|
||||
android:color="#44000000"
|
||||
android:offset="0.0" />
|
||||
<item
|
||||
android:color="#00000000"
|
||||
android:offset="1.0" />
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:fillType="nonZero"
|
||||
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
|
||||
android:strokeWidth="1"
|
||||
android:strokeColor="#00000000" />
|
||||
</vector>
|
BIN
app/src/main/res/drawable/unn_logo.png
Normal file
After Width: | Height: | Size: 76 KiB |
@ -2,5 +2,4 @@
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/ic_launcher_background"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
<monochrome android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 790 B After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 878 B After Width: | Height: | Size: 942 B |
Before Width: | Height: | Size: 534 B After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.0 KiB |
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 7.0 KiB |
Before Width: | Height: | Size: 6.5 KiB After Width: | Height: | Size: 6.6 KiB |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 4.9 KiB |
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 9.1 KiB After Width: | Height: | Size: 9.7 KiB |
@ -3,11 +3,4 @@
|
||||
<string name="prompt_password">Пароль</string>
|
||||
<string name="prompt_login">Логин</string>
|
||||
<string name="sign_in">Войти</string>
|
||||
<string name="assistant">Ассистент</string>
|
||||
<string name="lecturer">Преподаватель</string>
|
||||
<string name="slecturer">Старший Преподаватель</string>
|
||||
<string name="aprofessor">Доцент</string>
|
||||
<string name="auditorium">Аудитория</string>
|
||||
<string name="building">Здание</string>
|
||||
<string name="floor">Этаж</string>
|
||||
</resources>
|
@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="ic_launcher_background">#1565AA</color>
|
||||
<color name="ic_launcher_background">#FFFFFF</color>
|
||||
</resources>
|
@ -5,13 +5,5 @@
|
||||
<string name="prompt_login">Login</string>
|
||||
<string name="prompt_password">Password</string>
|
||||
<string name="sign_in">Sign in</string>
|
||||
<string name="assistant">Assistant</string>
|
||||
<string name="lecturer">Lecturer</string>
|
||||
<string name="slecturer">Senior Lecturer</string>
|
||||
<string name="aprofessor">Assistant professor</string>
|
||||
<string name="auditorium">Auditorium</string>
|
||||
<string name="building">Building</string>
|
||||
<string name="floor">Floor</string>
|
||||
<string name="lorem" translatable="false">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam vel iaculis elit. Aliquam varius urna ut nisl rhoncus ullamcorper. Maecenas et nisl at dui mollis maximus nec in libero. Ut eu nulla id felis hendrerit lobortis. Maecenas vel facilisis lectus. Morbi eleifend massa a ante consequat, eu aliquam elit euismod. Aenean quis erat tincidunt, egestas ligula id, convallis tortor. Vivamus volutpat condimentum nisl sed eleifend. Aenean dapibus dolor ut orci lobortis, placerat lobortis tortor pretium. Nam eros lectus, convallis sed ultricies sit amet, lacinia sed sem. In mi odio, porta non malesuada et, cursus a metus. Morbi quis odio sed quam commodo gravida id sit amet dolor. Donec ac iaculis massa. Nulla mauris sapien, auctor consequat est in, tempus accumsan ipsum. Donec semper volutpat nisi. Quisque dignissim tellus ipsum, sed malesuada libero aliquam sed. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Nam eleifend pharetra orci eu scelerisque. In hac habitasse platea dictumst. Sed non neque vitae metus porttitor vestibulum ut eget felis. Aliquam venenatis a magna eu mattis. Proin rutrum, sapien id viverra finibus, nisi quam aliquam eros, et dignissim lectus sem sit amet purus. Donec et semper enim, sed pretium lacus. Nullam venenatis ullamcorper maximus. Mauris pellentesque velit non sem sollicitudin molestie. Duis hendrerit consequat enim eget euismod.</string>
|
||||
<!-- <string name="login_failed">"Login failed"</string>-->
|
||||
</resources>
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<style name="Theme.UNN" parent="android:Theme.Material.NoActionBar" />
|
||||
<style name="Theme.UNN" parent="android:Theme.Material.Light.NoActionBar" />
|
||||
</resources>
|
36
app/src/main/res/xml/data_extraction_rules.xml
Normal file
@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Sample data extraction rules file; uncomment and customize as necessary.
|
||||
See https://developer.android.com/about/versions/12/backup-restore#xml-changes
|
||||
for details.
|
||||
-->
|
||||
<data-extraction-rules>
|
||||
<cloud-backup>
|
||||
<!--
|
||||
TODO: Use <include> and <exclude> to control what is backed up.
|
||||
The domain can be file, database, sharedpref, external or root.
|
||||
Examples:
|
||||
|
||||
<include domain="file" path="file_to_include"/>
|
||||
<exclude domain="file" path="file_to_exclude"/>
|
||||
<include domain="file" path="include_folder"/>
|
||||
<exclude domain="file" path="include_folder/file_to_exclude"/>
|
||||
<exclude domain="file" path="exclude_folder"/>
|
||||
<include domain="file" path="exclude_folder/file_to_include"/>
|
||||
|
||||
<include domain="sharedpref" path="include_shared_pref1.xml"/>
|
||||
<include domain="database" path="db_name/file_to_include"/>
|
||||
<exclude domain="database" path="db_name/include_folder/file_to_exclude"/>
|
||||
<include domain="external" path="file_to_include"/>
|
||||
<exclude domain="external" path="file_to_exclude"/>
|
||||
<include domain="root" path="file_to_include"/>
|
||||
<exclude domain="root" path="file_to_exclude"/>
|
||||
-->
|
||||
</cloud-backup>
|
||||
<!--
|
||||
<device-transfer>
|
||||
<include .../>
|
||||
<exclude .../>
|
||||
</device-transfer>
|
||||
-->
|
||||
</data-extraction-rules>
|
@ -2,10 +2,4 @@
|
||||
plugins {
|
||||
alias(libs.plugins.androidApplication) apply false
|
||||
alias(libs.plugins.jetbrainsKotlinAndroid) apply false
|
||||
}
|
||||
|
||||
buildscript {
|
||||
dependencies {
|
||||
classpath(libs.secrets.gradle.plugin)
|
||||
}
|
||||
}
|
@ -1,43 +1,32 @@
|
||||
[versions]
|
||||
acraHttp = "5.11.3"
|
||||
agp = "8.3.1"
|
||||
coilCompose = "2.6.0"
|
||||
compose = "2.5.0"
|
||||
coreSplashscreen = "1.0.1"
|
||||
agp = "8.3.0"
|
||||
datastorePreferences = "1.0.0"
|
||||
desugar_jdk_libs = "2.0.4"
|
||||
kotlin = "1.9.0"
|
||||
coreKtx = "1.12.0"
|
||||
coreKtx = "1.10.1"
|
||||
junit = "4.13.2"
|
||||
junitVersion = "1.1.5"
|
||||
espressoCore = "3.5.1"
|
||||
ktorClientCio = "2.3.9"
|
||||
ktorClientCore = "2.3.9"
|
||||
ktorClientLogging = "2.3.9"
|
||||
lifecycleRuntimeKtx = "2.7.0"
|
||||
activityCompose = "1.8.2"
|
||||
composeBom = "2024.02.02"
|
||||
lifecycleRuntimeKtx = "2.6.1"
|
||||
activityCompose = "1.7.0"
|
||||
composeBom = "2023.08.00"
|
||||
appcompat = "1.6.1"
|
||||
material = "1.11.0"
|
||||
annotation = "1.7.1"
|
||||
material = "1.10.0"
|
||||
annotation = "1.6.0"
|
||||
constraintlayout = "2.1.4"
|
||||
lifecycleLivedataKtx = "2.7.0"
|
||||
lifecycleViewmodelKtx = "2.7.0"
|
||||
activity = "1.8.2"
|
||||
lifecycleLivedataKtx = "2.6.1"
|
||||
lifecycleViewmodelKtx = "2.6.1"
|
||||
activity = "1.8.0"
|
||||
navigationCompose = "2.7.7"
|
||||
richeditorCompose = "1.0.0-rc01"
|
||||
secretsGradlePlugin = "2.0.1"
|
||||
splittiesFunPackAndroidBaseWithViewsDsl = "3.0.0"
|
||||
kefirbb = "1.5"
|
||||
|
||||
[libraries]
|
||||
acra-http = { module = "ch.acra:acra-http", version.ref = "acraHttp" }
|
||||
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
|
||||
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" }
|
||||
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" }
|
||||
junit = { group = "junit", name = "junit", version.ref = "junit" }
|
||||
androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
|
||||
androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
|
||||
androidx-lifecycle-runtime-ktx = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "lifecycleRuntimeKtx" }
|
||||
@ -60,10 +49,7 @@ androidx-constraintlayout = { group = "androidx.constraintlayout", name = "const
|
||||
androidx-lifecycle-livedata-ktx = { group = "androidx.lifecycle", name = "lifecycle-livedata-ktx", version.ref = "lifecycleLivedataKtx" }
|
||||
androidx-lifecycle-viewmodel-ktx = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-ktx", version.ref = "lifecycleViewmodelKtx" }
|
||||
androidx-activity = { group = "androidx.activity", name = "activity", version.ref = "activity" }
|
||||
richeditor-compose = { module = "com.mohamedrejeb.richeditor:richeditor-compose", version.ref = "richeditorCompose" }
|
||||
secrets-gradle-plugin = { module = "com.google.android.libraries.mapsplatform.secrets-gradle-plugin:secrets-gradle-plugin", version.ref = "secretsGradlePlugin" }
|
||||
splitties-funpack-android-base-with-views-dsl = { module = "com.louiscad.splitties:splitties-fun-pack-android-base-with-views-dsl", version.ref = "splittiesFunPackAndroidBaseWithViewsDsl" }
|
||||
kefirbb = { group = "org.kefirsf", name = "kefirbb", version.ref = "kefirbb" }
|
||||
splitties-fun-pack-android-base-with-views-dsl = { module = "com.louiscad.splitties:splitties-fun-pack-android-base-with-views-dsl", version.ref = "splittiesFunPackAndroidBaseWithViewsDsl" }
|
||||
|
||||
[plugins]
|
||||
androidApplication = { id = "com.android.application", version.ref = "agp" }
|
||||
|