diff --git a/.idea/appInsightsSettings.xml b/.idea/appInsightsSettings.xml
index a1d7d06..c6a9c7c 100644
--- a/.idea/appInsightsSettings.xml
+++ b/.idea/appInsightsSettings.xml
@@ -15,15 +15,33 @@
+
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 2f3aee5..f8e50eb 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -32,8 +32,8 @@ android {
applicationId = "ru.n08i40k.polytechnic.next"
minSdk = 26
targetSdk = 35
- versionCode = 9
- versionName = "1.4.0"
+ versionCode = 10
+ versionName = "1.5.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {
@@ -89,13 +89,22 @@ android {
}
dependencies {
+ // work manager
+ implementation(libs.androidx.work.runtime)
+ implementation(libs.androidx.work.runtime.ktx)
+
+ // hilt
implementation(libs.hilt.android)
ksp(libs.hilt.android.compiler)
implementation(libs.androidx.hilt.navigation.compose)
+ // firebase
implementation(platform(libs.firebase.bom))
implementation(libs.firebase.analytics)
+ implementation(libs.firebase.messaging)
+ implementation(libs.firebase.crashlytics)
+ // datastore
implementation(libs.androidx.datastore)
implementation(libs.protobuf.lite)
@@ -112,7 +121,7 @@ dependencies {
implementation(libs.androidx.material3)
implementation(libs.volley)
implementation(libs.androidx.navigation.compose)
- implementation(libs.firebase.crashlytics)
+
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 90fd030..a274b7a 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -3,6 +3,7 @@
xmlns:tools="http://schemas.android.com/tools">
+
+
+
+
+
+
+
+
{
return withContext(Dispatchers.IO) {
val groupName = runBlocking {
@@ -27,8 +24,8 @@ class RemoteScheduleRepository(private val context: Context) : ScheduleRepositor
return@withContext MyResult.Failure(IllegalArgumentException("No group name provided!"))
val response = tryFuture {
- ScheduleGetReq(
- ScheduleGetReqData(groupName),
+ ScheduleGet(
+ ScheduleGet.RequestDto(groupName),
context,
it,
it
diff --git a/app/src/main/java/ru/n08i40k/polytechnic/next/data/scheduleReplacer/impl/FakeScheduleReplacerRepository.kt b/app/src/main/java/ru/n08i40k/polytechnic/next/data/scheduleReplacer/impl/FakeScheduleReplacerRepository.kt
index 27aa71e..8c083ed 100644
--- a/app/src/main/java/ru/n08i40k/polytechnic/next/data/scheduleReplacer/impl/FakeScheduleReplacerRepository.kt
+++ b/app/src/main/java/ru/n08i40k/polytechnic/next/data/scheduleReplacer/impl/FakeScheduleReplacerRepository.kt
@@ -1,4 +1,4 @@
-package ru.n08i40k.polytechnic.next.data.schedule.impl
+package ru.n08i40k.polytechnic.next.data.scheduleReplacer.impl
import ru.n08i40k.polytechnic.next.data.MyResult
import ru.n08i40k.polytechnic.next.data.scheduleReplacer.ScheduleReplacerRepository
diff --git a/app/src/main/java/ru/n08i40k/polytechnic/next/data/scheduleReplacer/impl/RemoteScheduleReplacerRepository.kt b/app/src/main/java/ru/n08i40k/polytechnic/next/data/scheduleReplacer/impl/RemoteScheduleReplacerRepository.kt
index 6a95dd0..70cd290 100644
--- a/app/src/main/java/ru/n08i40k/polytechnic/next/data/scheduleReplacer/impl/RemoteScheduleReplacerRepository.kt
+++ b/app/src/main/java/ru/n08i40k/polytechnic/next/data/scheduleReplacer/impl/RemoteScheduleReplacerRepository.kt
@@ -1,4 +1,4 @@
-package ru.n08i40k.polytechnic.next.data.schedule.impl
+package ru.n08i40k.polytechnic.next.data.scheduleReplacer.impl
import android.content.Context
import kotlinx.coroutines.Dispatchers
@@ -6,15 +6,15 @@ import kotlinx.coroutines.withContext
import ru.n08i40k.polytechnic.next.data.MyResult
import ru.n08i40k.polytechnic.next.data.scheduleReplacer.ScheduleReplacerRepository
import ru.n08i40k.polytechnic.next.model.ScheduleReplacer
-import ru.n08i40k.polytechnic.next.network.data.scheduleReplacer.ScheduleReplacerClearReq
-import ru.n08i40k.polytechnic.next.network.data.scheduleReplacer.ScheduleReplacerGetReq
-import ru.n08i40k.polytechnic.next.network.data.scheduleReplacer.ScheduleReplacerSetReq
+import ru.n08i40k.polytechnic.next.network.request.scheduleReplacer.ScheduleReplacerClear
+import ru.n08i40k.polytechnic.next.network.request.scheduleReplacer.ScheduleReplacerGet
+import ru.n08i40k.polytechnic.next.network.request.scheduleReplacer.ScheduleReplacerSet
import ru.n08i40k.polytechnic.next.network.tryFuture
class RemoteScheduleReplacerRepository(private val context: Context) : ScheduleReplacerRepository {
override suspend fun getAll(): MyResult> =
withContext(Dispatchers.IO) {
- tryFuture { ScheduleReplacerGetReq(context, it, it) }
+ tryFuture { ScheduleReplacerGet(context, it, it) }
}
@@ -24,12 +24,12 @@ class RemoteScheduleReplacerRepository(private val context: Context) : ScheduleR
fileType: String
): MyResult =
withContext(Dispatchers.IO) {
- tryFuture { ScheduleReplacerSetReq(context, fileName, fileData, fileType, it, it) }
+ tryFuture { ScheduleReplacerSet(context, fileName, fileData, fileType, it, it) }
}
override suspend fun clear(): MyResult {
val response = withContext(Dispatchers.IO) {
- tryFuture { ScheduleReplacerClearReq(context, it, it) }
+ tryFuture { ScheduleReplacerClear(context, it, it) }
}
return when (response) {
diff --git a/app/src/main/java/ru/n08i40k/polytechnic/next/data/users/ProfileRepository.kt b/app/src/main/java/ru/n08i40k/polytechnic/next/data/users/ProfileRepository.kt
index 00e6c73..4d08f12 100644
--- a/app/src/main/java/ru/n08i40k/polytechnic/next/data/users/ProfileRepository.kt
+++ b/app/src/main/java/ru/n08i40k/polytechnic/next/data/users/ProfileRepository.kt
@@ -5,4 +5,6 @@ import ru.n08i40k.polytechnic.next.model.Profile
interface ProfileRepository {
suspend fun getProfile(): MyResult
+
+ suspend fun setFcmToken(token: String): MyResult
}
\ No newline at end of file
diff --git a/app/src/main/java/ru/n08i40k/polytechnic/next/data/users/impl/FakeProfileRepository.kt b/app/src/main/java/ru/n08i40k/polytechnic/next/data/users/impl/FakeProfileRepository.kt
index 4deeef6..fb8f920 100644
--- a/app/src/main/java/ru/n08i40k/polytechnic/next/data/users/impl/FakeProfileRepository.kt
+++ b/app/src/main/java/ru/n08i40k/polytechnic/next/data/users/impl/FakeProfileRepository.kt
@@ -26,4 +26,8 @@ class FakeProfileRepository : ProfileRepository {
MyResult.Success(exampleProfile)
}
}
+
+ override suspend fun setFcmToken(token: String): MyResult {
+ return MyResult.Success(Unit)
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/ru/n08i40k/polytechnic/next/data/users/impl/RemoteProfileRepository.kt b/app/src/main/java/ru/n08i40k/polytechnic/next/data/users/impl/RemoteProfileRepository.kt
index 85108ed..c3606d3 100644
--- a/app/src/main/java/ru/n08i40k/polytechnic/next/data/users/impl/RemoteProfileRepository.kt
+++ b/app/src/main/java/ru/n08i40k/polytechnic/next/data/users/impl/RemoteProfileRepository.kt
@@ -6,18 +6,18 @@ import kotlinx.coroutines.withContext
import ru.n08i40k.polytechnic.next.data.MyResult
import ru.n08i40k.polytechnic.next.data.users.ProfileRepository
import ru.n08i40k.polytechnic.next.model.Profile
-import ru.n08i40k.polytechnic.next.network.data.profile.UsersMeRequest
+import ru.n08i40k.polytechnic.next.network.request.fcm.FcmSetToken
+import ru.n08i40k.polytechnic.next.network.request.profile.ProfileMe
import ru.n08i40k.polytechnic.next.network.tryFuture
class RemoteProfileRepository(private val context: Context) : ProfileRepository {
override suspend fun getProfile(): MyResult =
withContext(Dispatchers.IO) {
- tryFuture {
- UsersMeRequest(
- context,
- it,
- it
- )
- }
+ tryFuture { ProfileMe(context, it, it) }
+ }
+
+ override suspend fun setFcmToken(token: String): MyResult =
+ withContext(Dispatchers.IO) {
+ tryFuture { FcmSetToken(context, token, it, it) }
}
}
\ No newline at end of file
diff --git a/app/src/main/java/ru/n08i40k/polytechnic/next/network/AuthorizedMultipartRequest.kt b/app/src/main/java/ru/n08i40k/polytechnic/next/network/AuthorizedMultipartRequest.kt
index 4a907a5..3ac758c 100644
--- a/app/src/main/java/ru/n08i40k/polytechnic/next/network/AuthorizedMultipartRequest.kt
+++ b/app/src/main/java/ru/n08i40k/polytechnic/next/network/AuthorizedMultipartRequest.kt
@@ -2,7 +2,7 @@ package ru.n08i40k.polytechnic.next.network
import android.content.Context
import com.android.volley.Response
-import ru.n08i40k.polytechnic.next.network.data.AuthorizedRequest
+import ru.n08i40k.polytechnic.next.network.request.AuthorizedRequest
import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import java.io.DataOutputStream
diff --git a/app/src/main/java/ru/n08i40k/polytechnic/next/network/NetworkValues.kt b/app/src/main/java/ru/n08i40k/polytechnic/next/network/NetworkValues.kt
index c22dd08..d9f94e5 100644
--- a/app/src/main/java/ru/n08i40k/polytechnic/next/network/NetworkValues.kt
+++ b/app/src/main/java/ru/n08i40k/polytechnic/next/network/NetworkValues.kt
@@ -1,5 +1,5 @@
package ru.n08i40k.polytechnic.next.network
object NetworkValues {
- const val API_HOST = "https://polytechnic.n08i40k.ru:5050/api/v1/"
+ const val API_HOST = "https://192.168.0.103:5050/api/v1/"
}
\ No newline at end of file
diff --git a/app/src/main/java/ru/n08i40k/polytechnic/next/network/RequestUtils.kt b/app/src/main/java/ru/n08i40k/polytechnic/next/network/RequestUtils.kt
index 27d5fdf..0fad533 100644
--- a/app/src/main/java/ru/n08i40k/polytechnic/next/network/RequestUtils.kt
+++ b/app/src/main/java/ru/n08i40k/polytechnic/next/network/RequestUtils.kt
@@ -10,7 +10,9 @@ fun tryFuture(
buildRequest: (RequestFuture) -> RequestT
): MyResult {
val future = RequestFuture.newFuture()
+
buildRequest(future).send()
+
return tryGet(future)
}
diff --git a/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/auth/ChangePasswordRequestData.kt b/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/auth/ChangePasswordRequestData.kt
deleted file mode 100644
index 82cd4d4..0000000
--- a/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/auth/ChangePasswordRequestData.kt
+++ /dev/null
@@ -1,6 +0,0 @@
-package ru.n08i40k.polytechnic.next.network.data.auth
-
-import kotlinx.serialization.Serializable
-
-@Serializable
-data class ChangePasswordRequestData(val oldPassword: String, val newPassword: String)
\ No newline at end of file
diff --git a/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/auth/LoginRequestData.kt b/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/auth/LoginRequestData.kt
deleted file mode 100644
index 1ce3946..0000000
--- a/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/auth/LoginRequestData.kt
+++ /dev/null
@@ -1,6 +0,0 @@
-package ru.n08i40k.polytechnic.next.network.data.auth
-
-import kotlinx.serialization.Serializable
-
-@Serializable
-data class LoginRequestData(val username: String, val password: String)
\ No newline at end of file
diff --git a/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/auth/LoginResponseData.kt b/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/auth/LoginResponseData.kt
deleted file mode 100644
index ad59960..0000000
--- a/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/auth/LoginResponseData.kt
+++ /dev/null
@@ -1,6 +0,0 @@
-package ru.n08i40k.polytechnic.next.network.data.auth
-
-import kotlinx.serialization.Serializable
-
-@Serializable
-data class LoginResponseData(val id: String, val accessToken: String)
\ No newline at end of file
diff --git a/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/auth/RegisterRequestData.kt b/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/auth/RegisterRequestData.kt
deleted file mode 100644
index 13954d2..0000000
--- a/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/auth/RegisterRequestData.kt
+++ /dev/null
@@ -1,12 +0,0 @@
-package ru.n08i40k.polytechnic.next.network.data.auth
-
-import kotlinx.serialization.Serializable
-import ru.n08i40k.polytechnic.next.model.UserRole
-
-@Serializable
-data class RegisterRequestData(
- val username: String,
- val password: String,
- val group: String,
- val role: UserRole
-)
\ No newline at end of file
diff --git a/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/auth/RegisterResponseData.kt b/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/auth/RegisterResponseData.kt
deleted file mode 100644
index d2d64b6..0000000
--- a/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/auth/RegisterResponseData.kt
+++ /dev/null
@@ -1,6 +0,0 @@
-package ru.n08i40k.polytechnic.next.network.data.auth
-
-import kotlinx.serialization.Serializable
-
-@Serializable
-data class RegisterResponseData(val id: String, val accessToken: String)
\ No newline at end of file
diff --git a/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/profile/ChangeGroupRequestData.kt b/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/profile/ChangeGroupRequestData.kt
deleted file mode 100644
index e9f7f41..0000000
--- a/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/profile/ChangeGroupRequestData.kt
+++ /dev/null
@@ -1,6 +0,0 @@
-package ru.n08i40k.polytechnic.next.network.data.profile
-
-import kotlinx.serialization.Serializable
-
-@Serializable
-data class ChangeGroupRequestData(val group: String)
\ No newline at end of file
diff --git a/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/profile/ChangeUsernameRequestData.kt b/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/profile/ChangeUsernameRequestData.kt
deleted file mode 100644
index 3157d3f..0000000
--- a/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/profile/ChangeUsernameRequestData.kt
+++ /dev/null
@@ -1,6 +0,0 @@
-package ru.n08i40k.polytechnic.next.network.data.profile
-
-import kotlinx.serialization.Serializable
-
-@Serializable
-data class ChangeUsernameRequestData(val username: String)
\ No newline at end of file
diff --git a/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/schedule/ScheduleGetCacheStatusReq.kt b/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/schedule/ScheduleGetCacheStatusReq.kt
deleted file mode 100644
index 3b2f592..0000000
--- a/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/schedule/ScheduleGetCacheStatusReq.kt
+++ /dev/null
@@ -1,18 +0,0 @@
-package ru.n08i40k.polytechnic.next.network.data.schedule
-
-import android.content.Context
-import com.android.volley.Response
-import kotlinx.serialization.json.Json
-import ru.n08i40k.polytechnic.next.network.data.AuthorizedRequest
-
-class ScheduleGetCacheStatusReq(
- context: Context,
- listener: Response.Listener,
- errorListener: Response.ErrorListener? = null
-) : AuthorizedRequest(
- context,
- Method.GET,
- "schedule/cache-status",
- { listener.onResponse(Json.decodeFromString(it)) },
- errorListener
-)
\ No newline at end of file
diff --git a/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/schedule/ScheduleGetCacheStatusResData.kt b/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/schedule/ScheduleGetCacheStatusResData.kt
deleted file mode 100644
index 741a44c..0000000
--- a/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/schedule/ScheduleGetCacheStatusResData.kt
+++ /dev/null
@@ -1,11 +0,0 @@
-package ru.n08i40k.polytechnic.next.network.data.schedule
-
-import kotlinx.serialization.Serializable
-
-@Serializable
-data class ScheduleGetCacheStatusResData(
- val cacheUpdateRequired: Boolean,
- val cacheHash: String,
- val lastCacheUpdate: Long,
- val lastScheduleUpdate: Long,
-)
\ No newline at end of file
diff --git a/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/schedule/ScheduleGetGroupNamesReq.kt b/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/schedule/ScheduleGetGroupNamesReq.kt
deleted file mode 100644
index a61ba11..0000000
--- a/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/schedule/ScheduleGetGroupNamesReq.kt
+++ /dev/null
@@ -1,18 +0,0 @@
-package ru.n08i40k.polytechnic.next.network.data.schedule
-
-import android.content.Context
-import com.android.volley.Response
-import kotlinx.serialization.json.Json
-import ru.n08i40k.polytechnic.next.network.data.CachedRequest
-
-class ScheduleGetGroupNamesReq(
- context: Context,
- listener: Response.Listener,
- errorListener: Response.ErrorListener? = null
-) : CachedRequest(
- context,
- Method.GET,
- "schedule/get-group-names",
- { listener.onResponse(Json.decodeFromString(it)) },
- errorListener
-)
\ No newline at end of file
diff --git a/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/schedule/ScheduleGetGroupNamesResData.kt b/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/schedule/ScheduleGetGroupNamesResData.kt
deleted file mode 100644
index 1ab02f2..0000000
--- a/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/schedule/ScheduleGetGroupNamesResData.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package ru.n08i40k.polytechnic.next.network.data.schedule
-
-import kotlinx.serialization.Serializable
-
-@Serializable
-data class ScheduleGetGroupNamesResData(
- val names: ArrayList,
-)
\ No newline at end of file
diff --git a/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/schedule/ScheduleGetReq.kt b/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/schedule/ScheduleGetReq.kt
deleted file mode 100644
index 03937ee..0000000
--- a/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/schedule/ScheduleGetReq.kt
+++ /dev/null
@@ -1,24 +0,0 @@
-package ru.n08i40k.polytechnic.next.network.data.schedule
-
-import android.content.Context
-import com.android.volley.Response
-import kotlinx.serialization.encodeToString
-import kotlinx.serialization.json.Json
-import ru.n08i40k.polytechnic.next.network.data.CachedRequest
-
-class ScheduleGetReq(
- private val data: ScheduleGetReqData,
- context: Context,
- listener: Response.Listener,
- errorListener: Response.ErrorListener? = null
-) : CachedRequest(
- context,
- Method.POST,
- "schedule/get-group",
- { listener.onResponse(Json.decodeFromString(it)) },
- errorListener
-) {
- override fun getBody(): ByteArray {
- return Json.encodeToString(data).toByteArray()
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/schedule/ScheduleGetReqData.kt b/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/schedule/ScheduleGetReqData.kt
deleted file mode 100644
index 44af8f1..0000000
--- a/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/schedule/ScheduleGetReqData.kt
+++ /dev/null
@@ -1,6 +0,0 @@
-package ru.n08i40k.polytechnic.next.network.data.schedule
-
-import kotlinx.serialization.Serializable
-
-@Serializable
-data class ScheduleGetReqData(val name: String)
\ No newline at end of file
diff --git a/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/schedule/ScheduleGetResData.kt b/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/schedule/ScheduleGetResData.kt
deleted file mode 100644
index a9ccfe0..0000000
--- a/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/schedule/ScheduleGetResData.kt
+++ /dev/null
@@ -1,11 +0,0 @@
-package ru.n08i40k.polytechnic.next.network.data.schedule
-
-import kotlinx.serialization.Serializable
-import ru.n08i40k.polytechnic.next.model.Group
-
-@Serializable
-data class ScheduleGetResData(
- val updatedAt: String,
- val group: Group,
- val lastChangedDays: ArrayList,
-)
\ No newline at end of file
diff --git a/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/schedule/ScheduleUpdateReqData.kt b/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/schedule/ScheduleUpdateReqData.kt
deleted file mode 100644
index a703f70..0000000
--- a/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/schedule/ScheduleUpdateReqData.kt
+++ /dev/null
@@ -1,6 +0,0 @@
-package ru.n08i40k.polytechnic.next.network.data.schedule
-
-import kotlinx.serialization.Serializable
-
-@Serializable
-data class ScheduleUpdateReqData(val mainPage: String)
\ No newline at end of file
diff --git a/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/scheduleReplacer/ScheduleReplacerClearReq.kt b/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/scheduleReplacer/ScheduleReplacerClearReq.kt
deleted file mode 100644
index 23b10d0..0000000
--- a/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/scheduleReplacer/ScheduleReplacerClearReq.kt
+++ /dev/null
@@ -1,18 +0,0 @@
-package ru.n08i40k.polytechnic.next.network.data.scheduleReplacer
-
-import android.content.Context
-import com.android.volley.Response
-import kotlinx.serialization.json.Json
-import ru.n08i40k.polytechnic.next.network.data.AuthorizedRequest
-
-class ScheduleReplacerClearReq(
- context: Context,
- listener: Response.Listener,
- errorListener: Response.ErrorListener?
-) : AuthorizedRequest(
- context,
- Method.POST,
- "schedule-replacer/clear",
- { listener.onResponse(Json.decodeFromString(it)) },
- errorListener
-)
\ No newline at end of file
diff --git a/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/scheduleReplacer/ScheduleReplacerClearResData.kt b/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/scheduleReplacer/ScheduleReplacerClearResData.kt
deleted file mode 100644
index 1218ed0..0000000
--- a/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/scheduleReplacer/ScheduleReplacerClearResData.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package ru.n08i40k.polytechnic.next.network.data.scheduleReplacer
-
-import kotlinx.serialization.Serializable
-
-@Serializable
-data class ScheduleReplacerClearResData(
- val count: Int
-)
\ No newline at end of file
diff --git a/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/scheduleReplacer/ScheduleReplacerGetResData.kt b/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/scheduleReplacer/ScheduleReplacerGetResData.kt
deleted file mode 100644
index 799e22d..0000000
--- a/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/scheduleReplacer/ScheduleReplacerGetResData.kt
+++ /dev/null
@@ -1,5 +0,0 @@
-package ru.n08i40k.polytechnic.next.network.data.scheduleReplacer
-
-import ru.n08i40k.polytechnic.next.model.ScheduleReplacer
-
-typealias ScheduleReplacerGetResData = List
diff --git a/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/AuthorizedRequest.kt b/app/src/main/java/ru/n08i40k/polytechnic/next/network/request/AuthorizedRequest.kt
similarity index 92%
rename from app/src/main/java/ru/n08i40k/polytechnic/next/network/data/AuthorizedRequest.kt
rename to app/src/main/java/ru/n08i40k/polytechnic/next/network/request/AuthorizedRequest.kt
index 03f3076..fc4fe43 100644
--- a/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/AuthorizedRequest.kt
+++ b/app/src/main/java/ru/n08i40k/polytechnic/next/network/request/AuthorizedRequest.kt
@@ -1,4 +1,4 @@
-package ru.n08i40k.polytechnic.next.network.data
+package ru.n08i40k.polytechnic.next.network.request
import android.content.Context
import com.android.volley.AuthFailureError
@@ -40,7 +40,7 @@ open class AuthorizedRequest(
context.settingsDataStore.data.map { settings -> settings.accessToken }.first()
}
- if (accessToken.isEmpty())
+ if (accessToken.isEmpty() && context.profileViewModel != null)
context.profileViewModel!!.onUnauthorized()
val headers = super.getHeaders()
diff --git a/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/CachedRequest.kt b/app/src/main/java/ru/n08i40k/polytechnic/next/network/request/CachedRequest.kt
similarity index 89%
rename from app/src/main/java/ru/n08i40k/polytechnic/next/network/data/CachedRequest.kt
rename to app/src/main/java/ru/n08i40k/polytechnic/next/network/request/CachedRequest.kt
index 1a60fda..03694a6 100644
--- a/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/CachedRequest.kt
+++ b/app/src/main/java/ru/n08i40k/polytechnic/next/network/request/CachedRequest.kt
@@ -1,4 +1,4 @@
-package ru.n08i40k.polytechnic.next.network.data
+package ru.n08i40k.polytechnic.next.network.request
import android.content.Context
import com.android.volley.Response
@@ -11,10 +11,8 @@ import ru.n08i40k.polytechnic.next.PolytechnicApplication
import ru.n08i40k.polytechnic.next.data.AppContainer
import ru.n08i40k.polytechnic.next.data.MyResult
import ru.n08i40k.polytechnic.next.network.NetworkConnection
-import ru.n08i40k.polytechnic.next.network.data.schedule.ScheduleGetCacheStatusReq
-import ru.n08i40k.polytechnic.next.network.data.schedule.ScheduleGetCacheStatusResData
-import ru.n08i40k.polytechnic.next.network.data.schedule.ScheduleUpdateReq
-import ru.n08i40k.polytechnic.next.network.data.schedule.ScheduleUpdateReqData
+import ru.n08i40k.polytechnic.next.network.request.schedule.ScheduleGetCacheStatus
+import ru.n08i40k.polytechnic.next.network.request.schedule.ScheduleUpdate
import ru.n08i40k.polytechnic.next.network.tryFuture
import ru.n08i40k.polytechnic.next.network.tryGet
import java.util.logging.Logger
@@ -58,14 +56,14 @@ open class CachedRequest(
}
}
- private suspend fun updateMainPage(): MyResult {
+ private suspend fun updateMainPage(): MyResult {
return withContext(Dispatchers.IO) {
when (val mainPage = getMainPage()) {
is MyResult.Failure -> mainPage
is MyResult.Success -> {
tryFuture {
- ScheduleUpdateReq(
- ScheduleUpdateReqData(mainPage.data),
+ ScheduleUpdate(
+ ScheduleUpdate.RequestDto(mainPage.data),
context,
it,
it
@@ -83,7 +81,7 @@ open class CachedRequest(
logger.info("Getting cache status...")
val cacheStatusResult = tryFuture {
- ScheduleGetCacheStatusReq(context, it, it)
+ ScheduleGetCacheStatus(context, it, it)
}
if (cacheStatusResult is MyResult.Success) {
diff --git a/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/auth/ChangePassword.kt b/app/src/main/java/ru/n08i40k/polytechnic/next/network/request/auth/AuthChangePassword.kt
similarity index 57%
rename from app/src/main/java/ru/n08i40k/polytechnic/next/network/data/auth/ChangePassword.kt
rename to app/src/main/java/ru/n08i40k/polytechnic/next/network/request/auth/AuthChangePassword.kt
index 5780d97..88f4bf3 100644
--- a/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/auth/ChangePassword.kt
+++ b/app/src/main/java/ru/n08i40k/polytechnic/next/network/request/auth/AuthChangePassword.kt
@@ -1,13 +1,14 @@
-package ru.n08i40k.polytechnic.next.network.data.auth
+package ru.n08i40k.polytechnic.next.network.request.auth
import android.content.Context
import com.android.volley.Response
+import kotlinx.serialization.Serializable
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
-import ru.n08i40k.polytechnic.next.network.data.AuthorizedRequest
+import ru.n08i40k.polytechnic.next.network.request.AuthorizedRequest
-class ChangePasswordRequest(
- private val data: ChangePasswordRequestData,
+class AuthChangePassword(
+ private val data: RequestDto,
context: Context,
listener: Response.Listener,
errorListener: Response.ErrorListener?
@@ -15,10 +16,13 @@ class ChangePasswordRequest(
context,
Method.POST,
"auth/change-password",
- Response.Listener { listener.onResponse(null) },
+ { listener.onResponse(null) },
errorListener,
canBeUnauthorized = true
) {
+ @Serializable
+ data class RequestDto(val oldPassword: String, val newPassword: String)
+
override fun getBody(): ByteArray {
return Json.encodeToString(data).toByteArray()
}
diff --git a/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/auth/Login.kt b/app/src/main/java/ru/n08i40k/polytechnic/next/network/request/auth/AuthLogin.kt
similarity index 58%
rename from app/src/main/java/ru/n08i40k/polytechnic/next/network/data/auth/Login.kt
rename to app/src/main/java/ru/n08i40k/polytechnic/next/network/request/auth/AuthLogin.kt
index ddd1479..d6b7fb7 100644
--- a/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/auth/Login.kt
+++ b/app/src/main/java/ru/n08i40k/polytechnic/next/network/request/auth/AuthLogin.kt
@@ -1,15 +1,16 @@
-package ru.n08i40k.polytechnic.next.network.data.auth
+package ru.n08i40k.polytechnic.next.network.request.auth
import android.content.Context
import com.android.volley.Response
+import kotlinx.serialization.Serializable
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import ru.n08i40k.polytechnic.next.network.RequestBase
-class LoginRequest(
- private val data: LoginRequestData,
+class AuthLogin(
+ private val data: RequestDto,
context: Context,
- listener: Response.Listener,
+ listener: Response.Listener,
errorListener: Response.ErrorListener?
) : RequestBase(
context,
@@ -18,6 +19,12 @@ class LoginRequest(
{ listener.onResponse(Json.decodeFromString(it)) },
errorListener
) {
+ @Serializable
+ data class RequestDto(val username: String, val password: String)
+
+ @Serializable
+ data class ResponseDto(val id: String, val accessToken: String)
+
override fun getBody(): ByteArray {
return Json.encodeToString(data).toByteArray()
}
diff --git a/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/auth/Register.kt b/app/src/main/java/ru/n08i40k/polytechnic/next/network/request/auth/AuthRegister.kt
similarity index 50%
rename from app/src/main/java/ru/n08i40k/polytechnic/next/network/data/auth/Register.kt
rename to app/src/main/java/ru/n08i40k/polytechnic/next/network/request/auth/AuthRegister.kt
index d82baf8..53db1b0 100644
--- a/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/auth/Register.kt
+++ b/app/src/main/java/ru/n08i40k/polytechnic/next/network/request/auth/AuthRegister.kt
@@ -1,15 +1,17 @@
-package ru.n08i40k.polytechnic.next.network.data.auth
+package ru.n08i40k.polytechnic.next.network.request.auth
import android.content.Context
import com.android.volley.Response
+import kotlinx.serialization.Serializable
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
+import ru.n08i40k.polytechnic.next.model.UserRole
import ru.n08i40k.polytechnic.next.network.RequestBase
-class RegisterRequest(
- private val data: RegisterRequestData,
+class AuthRegister(
+ private val data: RequestDto,
context: Context,
- listener: Response.Listener,
+ listener: Response.Listener,
errorListener: Response.ErrorListener?
) : RequestBase(
context,
@@ -18,6 +20,17 @@ class RegisterRequest(
{ listener.onResponse(Json.decodeFromString(it)) },
errorListener
) {
+ @Serializable
+ data class RequestDto(
+ val username: String,
+ val password: String,
+ val group: String,
+ val role: UserRole
+ )
+
+ @Serializable
+ data class ResponseDto(val id: String, val accessToken: String)
+
override fun getBody(): ByteArray {
return Json.encodeToString(data).toByteArray()
}
diff --git a/app/src/main/java/ru/n08i40k/polytechnic/next/network/request/fcm/FcmSetToken.kt b/app/src/main/java/ru/n08i40k/polytechnic/next/network/request/fcm/FcmSetToken.kt
new file mode 100644
index 0000000..684a7b2
--- /dev/null
+++ b/app/src/main/java/ru/n08i40k/polytechnic/next/network/request/fcm/FcmSetToken.kt
@@ -0,0 +1,18 @@
+package ru.n08i40k.polytechnic.next.network.request.fcm
+
+import android.content.Context
+import com.android.volley.Response
+import ru.n08i40k.polytechnic.next.network.request.AuthorizedRequest
+
+class FcmSetToken(
+ context: Context,
+ token: String,
+ listener: Response.Listener,
+ errorListener: Response.ErrorListener?,
+) : AuthorizedRequest(
+ context, Method.POST,
+ "fcm/set-token/$token",
+ { listener.onResponse(Unit) },
+ errorListener,
+ true
+)
\ No newline at end of file
diff --git a/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/profile/ChangeGroup.kt b/app/src/main/java/ru/n08i40k/polytechnic/next/network/request/profile/ProfileChangeGroup.kt
similarity index 58%
rename from app/src/main/java/ru/n08i40k/polytechnic/next/network/data/profile/ChangeGroup.kt
rename to app/src/main/java/ru/n08i40k/polytechnic/next/network/request/profile/ProfileChangeGroup.kt
index 29de4a4..6b3cd45 100644
--- a/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/profile/ChangeGroup.kt
+++ b/app/src/main/java/ru/n08i40k/polytechnic/next/network/request/profile/ProfileChangeGroup.kt
@@ -1,13 +1,14 @@
-package ru.n08i40k.polytechnic.next.network.data.profile
+package ru.n08i40k.polytechnic.next.network.request.profile
import android.content.Context
import com.android.volley.Response
+import kotlinx.serialization.Serializable
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
-import ru.n08i40k.polytechnic.next.network.data.AuthorizedRequest
+import ru.n08i40k.polytechnic.next.network.request.AuthorizedRequest
-class ChangeGroupRequest(
- private val data: ChangeGroupRequestData,
+class ProfileChangeGroup(
+ private val data: RequestDto,
context: Context,
listener: Response.Listener,
errorListener: Response.ErrorListener?
@@ -15,9 +16,12 @@ class ChangeGroupRequest(
context,
Method.POST,
"users/change-group",
- Response.Listener { listener.onResponse(null) },
+ { listener.onResponse(null) },
errorListener
) {
+ @Serializable
+ data class RequestDto(val group: String)
+
override fun getBody(): ByteArray {
return Json.encodeToString(data).toByteArray()
}
diff --git a/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/profile/ChangeUsername.kt b/app/src/main/java/ru/n08i40k/polytechnic/next/network/request/profile/ProfileChangeUsername.kt
similarity index 58%
rename from app/src/main/java/ru/n08i40k/polytechnic/next/network/data/profile/ChangeUsername.kt
rename to app/src/main/java/ru/n08i40k/polytechnic/next/network/request/profile/ProfileChangeUsername.kt
index ffa3330..d32c79c 100644
--- a/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/profile/ChangeUsername.kt
+++ b/app/src/main/java/ru/n08i40k/polytechnic/next/network/request/profile/ProfileChangeUsername.kt
@@ -1,13 +1,14 @@
-package ru.n08i40k.polytechnic.next.network.data.profile
+package ru.n08i40k.polytechnic.next.network.request.profile
import android.content.Context
import com.android.volley.Response
+import kotlinx.serialization.Serializable
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
-import ru.n08i40k.polytechnic.next.network.data.AuthorizedRequest
+import ru.n08i40k.polytechnic.next.network.request.AuthorizedRequest
-class ChangeUsernameRequest(
- private val data: ChangeUsernameRequestData,
+class ProfileChangeUsername(
+ private val data: RequestDto,
context: Context,
listener: Response.Listener,
errorListener: Response.ErrorListener?
@@ -15,9 +16,12 @@ class ChangeUsernameRequest(
context,
Method.POST,
"users/change-username",
- Response.Listener { listener.onResponse(null) },
+ { listener.onResponse(null) },
errorListener
) {
+ @Serializable
+ data class RequestDto(val username: String)
+
override fun getBody(): ByteArray {
return Json.encodeToString(data).toByteArray()
}
diff --git a/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/profile/UsersMe.kt b/app/src/main/java/ru/n08i40k/polytechnic/next/network/request/profile/ProfileMe.kt
similarity index 73%
rename from app/src/main/java/ru/n08i40k/polytechnic/next/network/data/profile/UsersMe.kt
rename to app/src/main/java/ru/n08i40k/polytechnic/next/network/request/profile/ProfileMe.kt
index 3c4b83c..766f904 100644
--- a/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/profile/UsersMe.kt
+++ b/app/src/main/java/ru/n08i40k/polytechnic/next/network/request/profile/ProfileMe.kt
@@ -1,12 +1,12 @@
-package ru.n08i40k.polytechnic.next.network.data.profile
+package ru.n08i40k.polytechnic.next.network.request.profile
import android.content.Context
import com.android.volley.Response
import kotlinx.serialization.json.Json
import ru.n08i40k.polytechnic.next.model.Profile
-import ru.n08i40k.polytechnic.next.network.data.AuthorizedRequest
+import ru.n08i40k.polytechnic.next.network.request.AuthorizedRequest
-class UsersMeRequest(
+class ProfileMe(
context: Context,
listener: Response.Listener,
errorListener: Response.ErrorListener?
diff --git a/app/src/main/java/ru/n08i40k/polytechnic/next/network/request/schedule/ScheduleGet.kt b/app/src/main/java/ru/n08i40k/polytechnic/next/network/request/schedule/ScheduleGet.kt
new file mode 100644
index 0000000..e0de8db
--- /dev/null
+++ b/app/src/main/java/ru/n08i40k/polytechnic/next/network/request/schedule/ScheduleGet.kt
@@ -0,0 +1,36 @@
+package ru.n08i40k.polytechnic.next.network.request.schedule
+
+import android.content.Context
+import com.android.volley.Response
+import kotlinx.serialization.Serializable
+import kotlinx.serialization.encodeToString
+import kotlinx.serialization.json.Json
+import ru.n08i40k.polytechnic.next.model.Group
+import ru.n08i40k.polytechnic.next.network.request.CachedRequest
+
+class ScheduleGet(
+ private val data: RequestDto,
+ context: Context,
+ listener: Response.Listener,
+ errorListener: Response.ErrorListener? = null
+) : CachedRequest(
+ context,
+ Method.POST,
+ "schedule/get-group",
+ { listener.onResponse(Json.decodeFromString(it)) },
+ errorListener
+) {
+ @Serializable
+ data class RequestDto(val name: String)
+
+ @Serializable
+ data class ResponseDto(
+ val updatedAt: String,
+ val group: Group,
+ val lastChangedDays: ArrayList,
+ )
+
+ override fun getBody(): ByteArray {
+ return Json.encodeToString(data).toByteArray()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/ru/n08i40k/polytechnic/next/network/request/schedule/ScheduleGetCacheStatus.kt b/app/src/main/java/ru/n08i40k/polytechnic/next/network/request/schedule/ScheduleGetCacheStatus.kt
new file mode 100644
index 0000000..97873e5
--- /dev/null
+++ b/app/src/main/java/ru/n08i40k/polytechnic/next/network/request/schedule/ScheduleGetCacheStatus.kt
@@ -0,0 +1,27 @@
+package ru.n08i40k.polytechnic.next.network.request.schedule
+
+import android.content.Context
+import com.android.volley.Response
+import kotlinx.serialization.Serializable
+import kotlinx.serialization.json.Json
+import ru.n08i40k.polytechnic.next.network.request.AuthorizedRequest
+
+class ScheduleGetCacheStatus(
+ context: Context,
+ listener: Response.Listener,
+ errorListener: Response.ErrorListener? = null
+) : AuthorizedRequest(
+ context,
+ Method.GET,
+ "schedule/cache-status",
+ { listener.onResponse(Json.decodeFromString(it)) },
+ errorListener
+) {
+ @Serializable
+ data class ResponseDto(
+ val cacheUpdateRequired: Boolean,
+ val cacheHash: String,
+ val lastCacheUpdate: Long,
+ val lastScheduleUpdate: Long,
+ )
+}
\ No newline at end of file
diff --git a/app/src/main/java/ru/n08i40k/polytechnic/next/network/request/schedule/ScheduleGetGroupNames.kt b/app/src/main/java/ru/n08i40k/polytechnic/next/network/request/schedule/ScheduleGetGroupNames.kt
new file mode 100644
index 0000000..b7e7922
--- /dev/null
+++ b/app/src/main/java/ru/n08i40k/polytechnic/next/network/request/schedule/ScheduleGetGroupNames.kt
@@ -0,0 +1,24 @@
+package ru.n08i40k.polytechnic.next.network.request.schedule
+
+import android.content.Context
+import com.android.volley.Response
+import kotlinx.serialization.Serializable
+import kotlinx.serialization.json.Json
+import ru.n08i40k.polytechnic.next.network.request.CachedRequest
+
+class ScheduleGetGroupNames(
+ context: Context,
+ listener: Response.Listener,
+ errorListener: Response.ErrorListener? = null
+) : CachedRequest(
+ context,
+ Method.GET,
+ "schedule/get-group-names",
+ { listener.onResponse(Json.decodeFromString(it)) },
+ errorListener
+) {
+ @Serializable
+ data class ResponseDto(
+ val names: ArrayList,
+ )
+}
\ No newline at end of file
diff --git a/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/schedule/ScheduleUpdateReq.kt b/app/src/main/java/ru/n08i40k/polytechnic/next/network/request/schedule/ScheduleUpdate.kt
similarity index 57%
rename from app/src/main/java/ru/n08i40k/polytechnic/next/network/data/schedule/ScheduleUpdateReq.kt
rename to app/src/main/java/ru/n08i40k/polytechnic/next/network/request/schedule/ScheduleUpdate.kt
index 8e13f7c..ad3f4f5 100644
--- a/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/schedule/ScheduleUpdateReq.kt
+++ b/app/src/main/java/ru/n08i40k/polytechnic/next/network/request/schedule/ScheduleUpdate.kt
@@ -1,15 +1,16 @@
-package ru.n08i40k.polytechnic.next.network.data.schedule
+package ru.n08i40k.polytechnic.next.network.request.schedule
import android.content.Context
import com.android.volley.Response
+import kotlinx.serialization.Serializable
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
-import ru.n08i40k.polytechnic.next.network.data.AuthorizedRequest
+import ru.n08i40k.polytechnic.next.network.request.AuthorizedRequest
-class ScheduleUpdateReq(
- private val data: ScheduleUpdateReqData,
+class ScheduleUpdate(
+ private val data: RequestDto,
context: Context,
- listener: Response.Listener,
+ listener: Response.Listener,
errorListener: Response.ErrorListener? = null
) : AuthorizedRequest(
context,
@@ -18,6 +19,9 @@ class ScheduleUpdateReq(
{ listener.onResponse(Json.decodeFromString(it)) },
errorListener
) {
+ @Serializable
+ data class RequestDto(val mainPage: String)
+
override fun getBody(): ByteArray {
return Json.encodeToString(data).toByteArray()
}
diff --git a/app/src/main/java/ru/n08i40k/polytechnic/next/network/request/scheduleReplacer/ScheduleReplacerClear.kt b/app/src/main/java/ru/n08i40k/polytechnic/next/network/request/scheduleReplacer/ScheduleReplacerClear.kt
new file mode 100644
index 0000000..0079532
--- /dev/null
+++ b/app/src/main/java/ru/n08i40k/polytechnic/next/network/request/scheduleReplacer/ScheduleReplacerClear.kt
@@ -0,0 +1,24 @@
+package ru.n08i40k.polytechnic.next.network.request.scheduleReplacer
+
+import android.content.Context
+import com.android.volley.Response
+import kotlinx.serialization.Serializable
+import kotlinx.serialization.json.Json
+import ru.n08i40k.polytechnic.next.network.request.AuthorizedRequest
+
+class ScheduleReplacerClear(
+ context: Context,
+ listener: Response.Listener,
+ errorListener: Response.ErrorListener?
+) : AuthorizedRequest(
+ context,
+ Method.POST,
+ "schedule-replacer/clear",
+ { listener.onResponse(Json.decodeFromString(it)) },
+ errorListener
+) {
+ @Serializable
+ data class ResponseDto(
+ val count: Int
+ )
+}
\ No newline at end of file
diff --git a/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/scheduleReplacer/ScheduleReplacerGetReq.kt b/app/src/main/java/ru/n08i40k/polytechnic/next/network/request/scheduleReplacer/ScheduleReplacerGet.kt
similarity index 53%
rename from app/src/main/java/ru/n08i40k/polytechnic/next/network/data/scheduleReplacer/ScheduleReplacerGetReq.kt
rename to app/src/main/java/ru/n08i40k/polytechnic/next/network/request/scheduleReplacer/ScheduleReplacerGet.kt
index 7ea030e..7796deb 100644
--- a/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/scheduleReplacer/ScheduleReplacerGetReq.kt
+++ b/app/src/main/java/ru/n08i40k/polytechnic/next/network/request/scheduleReplacer/ScheduleReplacerGet.kt
@@ -1,13 +1,14 @@
-package ru.n08i40k.polytechnic.next.network.data.scheduleReplacer
+package ru.n08i40k.polytechnic.next.network.request.scheduleReplacer
import android.content.Context
import com.android.volley.Response
import kotlinx.serialization.json.Json
-import ru.n08i40k.polytechnic.next.network.data.AuthorizedRequest
+import ru.n08i40k.polytechnic.next.model.ScheduleReplacer
+import ru.n08i40k.polytechnic.next.network.request.AuthorizedRequest
-class ScheduleReplacerGetReq(
+class ScheduleReplacerGet(
context: Context,
- listener: Response.Listener,
+ listener: Response.Listener>,
errorListener: Response.ErrorListener?
) : AuthorizedRequest(
context,
diff --git a/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/scheduleReplacer/ScheduleReplacerSetReq.kt b/app/src/main/java/ru/n08i40k/polytechnic/next/network/request/scheduleReplacer/ScheduleReplacerSet.kt
similarity index 88%
rename from app/src/main/java/ru/n08i40k/polytechnic/next/network/data/scheduleReplacer/ScheduleReplacerSetReq.kt
rename to app/src/main/java/ru/n08i40k/polytechnic/next/network/request/scheduleReplacer/ScheduleReplacerSet.kt
index 771f372..5bbf5f7 100644
--- a/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/scheduleReplacer/ScheduleReplacerSetReq.kt
+++ b/app/src/main/java/ru/n08i40k/polytechnic/next/network/request/scheduleReplacer/ScheduleReplacerSet.kt
@@ -1,10 +1,10 @@
-package ru.n08i40k.polytechnic.next.network.data.scheduleReplacer
+package ru.n08i40k.polytechnic.next.network.request.scheduleReplacer
import android.content.Context
import com.android.volley.Response
import ru.n08i40k.polytechnic.next.network.AuthorizedMultipartRequest
-class ScheduleReplacerSetReq(
+class ScheduleReplacerSet(
context: Context,
private val fileName: String,
private val fileData: ByteArray,
diff --git a/app/src/main/java/ru/n08i40k/polytechnic/next/service/MyFirebaseMessagingService.kt b/app/src/main/java/ru/n08i40k/polytechnic/next/service/MyFirebaseMessagingService.kt
new file mode 100644
index 0000000..72563dd
--- /dev/null
+++ b/app/src/main/java/ru/n08i40k/polytechnic/next/service/MyFirebaseMessagingService.kt
@@ -0,0 +1,110 @@
+package ru.n08i40k.polytechnic.next.service
+
+import android.Manifest
+import android.content.Context
+import android.content.pm.PackageManager
+import androidx.core.app.ActivityCompat
+import androidx.core.app.NotificationCompat
+import androidx.core.app.NotificationManagerCompat
+import androidx.work.BackoffPolicy
+import androidx.work.Constraints
+import androidx.work.NetworkType
+import androidx.work.OneTimeWorkRequestBuilder
+import androidx.work.WorkManager
+import androidx.work.Worker
+import androidx.work.WorkerParameters
+import androidx.work.workDataOf
+import com.google.firebase.messaging.FirebaseMessagingService
+import com.google.firebase.messaging.RemoteMessage
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.runBlocking
+import ru.n08i40k.polytechnic.next.NotificationChannels
+import ru.n08i40k.polytechnic.next.PolytechnicApplication
+import ru.n08i40k.polytechnic.next.R
+import ru.n08i40k.polytechnic.next.data.MyResult
+import ru.n08i40k.polytechnic.next.settings.settingsDataStore
+import java.time.Duration
+
+class MyFirebaseMessagingService : FirebaseMessagingService() {
+ override fun onNewToken(token: String) {
+ super.onNewToken(token)
+
+ val constraints = Constraints.Builder()
+ .setRequiredNetworkType(NetworkType.CONNECTED)
+ .build()
+
+ val request = OneTimeWorkRequestBuilder()
+ .setConstraints(constraints)
+ .setBackoffCriteria(BackoffPolicy.LINEAR, Duration.ofMinutes(1))
+ .setInputData(workDataOf("TOKEN" to token))
+ .build()
+
+ WorkManager
+ .getInstance(applicationContext)
+ .enqueue(request)
+ }
+
+ override fun onMessageReceived(message: RemoteMessage) {
+ val type = message.data["type"]
+
+ when (type) {
+ "schedule-update" -> {
+ val notification = NotificationCompat
+ .Builder(applicationContext, NotificationChannels.SCHEDULE_UPDATE)
+ .setSmallIcon(R.drawable.logo)
+ .setContentTitle(getString(R.string.schedule_update_title))
+ .setContentText(
+ getString(
+ if (message.data["replaced"] == "true")
+ R.string.schedule_update_replaced
+ else
+ R.string.schedule_update_default
+ )
+ )
+ .setPriority(NotificationCompat.PRIORITY_DEFAULT)
+ .setAutoCancel(true)
+ .build()
+
+ with(NotificationManagerCompat.from(this)) {
+ if (ActivityCompat.checkSelfPermission(
+ this@MyFirebaseMessagingService,
+ Manifest.permission.POST_NOTIFICATIONS
+ ) != PackageManager.PERMISSION_GRANTED
+ ) {
+ return@with
+ }
+
+ notify(message.data["etag"].hashCode(), notification)
+ }
+ }
+ }
+
+ super.onMessageReceived(message)
+ }
+
+ class SetFcmTokenWorker(context: Context, workerParams: WorkerParameters) :
+ Worker(context, workerParams) {
+ override fun doWork(): Result {
+ val fcmToken = inputData.getString("TOKEN") ?: return Result.failure()
+
+ val accessToken = runBlocking {
+ applicationContext.settingsDataStore.data.map { it.accessToken }.first()
+ }
+ if (accessToken.isEmpty())
+ return Result.retry()
+
+ val setResult = runBlocking {
+ (applicationContext as PolytechnicApplication)
+ .container
+ .profileRepository
+ .setFcmToken(fcmToken)
+ }
+
+ return when (setResult) {
+ is MyResult.Success -> Result.success()
+ is MyResult.Failure -> Result.retry()
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/ru/n08i40k/polytechnic/next/ui/MainActivity.kt b/app/src/main/java/ru/n08i40k/polytechnic/next/ui/MainActivity.kt
index c82b843..7e03dc1 100644
--- a/app/src/main/java/ru/n08i40k/polytechnic/next/ui/MainActivity.kt
+++ b/app/src/main/java/ru/n08i40k/polytechnic/next/ui/MainActivity.kt
@@ -1,9 +1,17 @@
package ru.n08i40k.polytechnic.next.ui
+import android.Manifest
+import android.annotation.SuppressLint
+import android.app.NotificationChannel
+import android.app.NotificationManager
+import android.content.Context
+import android.content.pm.PackageManager
+import android.os.Build
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
+import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.WindowInsetsSides
@@ -11,20 +19,95 @@ import androidx.compose.foundation.layout.only
import androidx.compose.foundation.layout.safeContent
import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.ui.Modifier
+import androidx.core.content.ContextCompat
import androidx.core.view.WindowCompat
import androidx.lifecycle.lifecycleScope
+import androidx.work.PeriodicWorkRequest
+import androidx.work.WorkManager
+import androidx.work.Worker
+import androidx.work.WorkerParameters
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
+import kotlinx.coroutines.runBlocking
+import ru.n08i40k.polytechnic.next.NotificationChannels.SCHEDULE_UPDATE
+import ru.n08i40k.polytechnic.next.PolytechnicApplication
+import ru.n08i40k.polytechnic.next.R
import ru.n08i40k.polytechnic.next.settings.settingsDataStore
+import java.util.concurrent.TimeUnit
@AndroidEntryPoint
class MainActivity : ComponentActivity() {
+ @SuppressLint("ObsoleteSdkInt")
+ private fun createNotificationChannel() {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ val name = getString(R.string.schedule_channel_name)
+ val description = getString(R.string.schedule_channel_description)
+ val importance = NotificationManager.IMPORTANCE_DEFAULT
+ val channel = NotificationChannel(SCHEDULE_UPDATE, name, importance)
+ channel.description = description
+
+ val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
+ notificationManager.createNotificationChannel(channel)
+ }
+ }
+
+ private val requestPermissionLauncher = registerForActivityResult(
+ ActivityResultContracts.RequestPermission(),
+ ) {
+ if (it) {
+ createNotificationChannel()
+ }
+ }
+
+ private fun hasNotificationPermission(): Boolean {
+ return (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU
+ || ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS)
+ == PackageManager.PERMISSION_GRANTED)
+ }
+
+ private fun askNotificationPermission() {
+ if (!hasNotificationPermission())
+ requestPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS)
+ }
+
+ class CacheUpdateWorker(context: Context, params: WorkerParameters) : Worker(context, params) {
+ override fun doWork(): Result {
+ runBlocking {
+ (applicationContext as PolytechnicApplication)
+ .container
+ .scheduleRepository
+ .getGroup()
+ }
+ return Result.success()
+ }
+ }
+
+ private fun schedulePeriodicRequest() {
+ val workRequest = PeriodicWorkRequest.Builder(
+ CacheUpdateWorker::class.java,
+ 15, TimeUnit.MINUTES
+ )
+ .addTag("schedule-update")
+ .build()
+
+ val workManager = WorkManager.getInstance(applicationContext)
+
+ workManager.cancelAllWorkByTag("schedule-update")
+ workManager.enqueue(workRequest)
+ }
+
override fun onCreate(savedInstanceState: Bundle?) {
enableEdgeToEdge()
WindowCompat.setDecorFitsSystemWindows(window, false)
super.onCreate(savedInstanceState)
+ schedulePeriodicRequest()
+ askNotificationPermission()
+
+ if (hasNotificationPermission())
+ createNotificationChannel()
+
setContent {
Box(Modifier.windowInsetsPadding(WindowInsets.safeContent.only(WindowInsetsSides.Top))) {
PolytechnicApp()
diff --git a/app/src/main/java/ru/n08i40k/polytechnic/next/ui/auth/AuthScreen.kt b/app/src/main/java/ru/n08i40k/polytechnic/next/ui/auth/AuthScreen.kt
index 0cea497..eb93c57 100644
--- a/app/src/main/java/ru/n08i40k/polytechnic/next/ui/auth/AuthScreen.kt
+++ b/app/src/main/java/ru/n08i40k/polytechnic/next/ui/auth/AuthScreen.kt
@@ -59,11 +59,9 @@ import kotlinx.coroutines.runBlocking
import ru.n08i40k.polytechnic.next.R
import ru.n08i40k.polytechnic.next.model.UserRole
import ru.n08i40k.polytechnic.next.model.UserRole.Companion.AcceptableUserRoles
-import ru.n08i40k.polytechnic.next.network.data.auth.LoginRequest
-import ru.n08i40k.polytechnic.next.network.data.auth.LoginRequestData
-import ru.n08i40k.polytechnic.next.network.data.auth.RegisterRequest
-import ru.n08i40k.polytechnic.next.network.data.auth.RegisterRequestData
-import ru.n08i40k.polytechnic.next.network.data.profile.UsersMeRequest
+import ru.n08i40k.polytechnic.next.network.request.auth.AuthLogin
+import ru.n08i40k.polytechnic.next.network.request.auth.AuthRegister
+import ru.n08i40k.polytechnic.next.network.request.profile.ProfileMe
import ru.n08i40k.polytechnic.next.settings.settingsDataStore
@Preview(showBackground = true)
@@ -368,7 +366,7 @@ fun tryLogin(
isLoading = true
- LoginRequest(LoginRequestData(username, password), context, {
+ AuthLogin(AuthLogin.RequestDto(username, password), context, {
runBlocking {
context.settingsDataStore.updateData { currentSettings ->
currentSettings
@@ -379,7 +377,7 @@ fun tryLogin(
}
}
- UsersMeRequest(context, {
+ ProfileMe(context, {
scope.launch { snackbarHostState.showSnackbar("Cool!") }
runBlocking {
@@ -437,8 +435,8 @@ fun tryRegister(
isLoading = true
- RegisterRequest(
- RegisterRequestData(
+ AuthRegister(
+ AuthRegister.RequestDto(
username,
password,
group,
diff --git a/app/src/main/java/ru/n08i40k/polytechnic/next/ui/main/profile/ChangeGroupDialog.kt b/app/src/main/java/ru/n08i40k/polytechnic/next/ui/main/profile/ChangeGroupDialog.kt
index e0af3d9..8b5e499 100644
--- a/app/src/main/java/ru/n08i40k/polytechnic/next/ui/main/profile/ChangeGroupDialog.kt
+++ b/app/src/main/java/ru/n08i40k/polytechnic/next/ui/main/profile/ChangeGroupDialog.kt
@@ -35,9 +35,8 @@ import com.android.volley.ClientError
import ru.n08i40k.polytechnic.next.R
import ru.n08i40k.polytechnic.next.data.users.impl.FakeProfileRepository
import ru.n08i40k.polytechnic.next.model.Profile
-import ru.n08i40k.polytechnic.next.network.data.profile.ChangeGroupRequest
-import ru.n08i40k.polytechnic.next.network.data.profile.ChangeGroupRequestData
-import ru.n08i40k.polytechnic.next.network.data.schedule.ScheduleGetGroupNamesReq
+import ru.n08i40k.polytechnic.next.network.request.profile.ProfileChangeGroup
+import ru.n08i40k.polytechnic.next.network.request.schedule.ScheduleGetGroupNames
private enum class ChangeGroupError {
NOT_EXISTS
@@ -49,7 +48,7 @@ private fun tryChangeGroup(
onError: (ChangeGroupError) -> Unit,
onSuccess: (String) -> Unit
) {
- ChangeGroupRequest(ChangeGroupRequestData(group), context, {
+ ProfileChangeGroup(ProfileChangeGroup.RequestDto(group), context, {
onSuccess(group)
}, {
if (it is ClientError && it.networkResponse.statusCode == 404)
@@ -65,7 +64,7 @@ private fun getGroups(context: Context): ArrayList {
val groups = remember { arrayListOf(groupPlaceholder) }
LaunchedEffect(groups) {
- ScheduleGetGroupNamesReq(context, {
+ ScheduleGetGroupNames(context, {
groups.clear()
groups.addAll(it.names)
}, {
diff --git a/app/src/main/java/ru/n08i40k/polytechnic/next/ui/main/profile/ChangePasswordDialog.kt b/app/src/main/java/ru/n08i40k/polytechnic/next/ui/main/profile/ChangePasswordDialog.kt
index 5ef1652..b190a11 100644
--- a/app/src/main/java/ru/n08i40k/polytechnic/next/ui/main/profile/ChangePasswordDialog.kt
+++ b/app/src/main/java/ru/n08i40k/polytechnic/next/ui/main/profile/ChangePasswordDialog.kt
@@ -26,8 +26,7 @@ import com.android.volley.ClientError
import ru.n08i40k.polytechnic.next.R
import ru.n08i40k.polytechnic.next.data.users.impl.FakeProfileRepository
import ru.n08i40k.polytechnic.next.model.Profile
-import ru.n08i40k.polytechnic.next.network.data.auth.ChangePasswordRequest
-import ru.n08i40k.polytechnic.next.network.data.auth.ChangePasswordRequestData
+import ru.n08i40k.polytechnic.next.network.request.auth.AuthChangePassword
private enum class ChangePasswordError {
INCORRECT_CURRENT_PASSWORD,
@@ -41,7 +40,7 @@ private fun tryChangePassword(
onError: (ChangePasswordError) -> Unit,
onSuccess: () -> Unit
) {
- ChangePasswordRequest(ChangePasswordRequestData(oldPassword, newPassword), context, {
+ AuthChangePassword(AuthChangePassword.RequestDto(oldPassword, newPassword), context, {
onSuccess()
}, {
if (it is ClientError && it.networkResponse.statusCode == 409)
diff --git a/app/src/main/java/ru/n08i40k/polytechnic/next/ui/main/profile/ChangeUsernameDialog.kt b/app/src/main/java/ru/n08i40k/polytechnic/next/ui/main/profile/ChangeUsernameDialog.kt
index 299fd18..70e718d 100644
--- a/app/src/main/java/ru/n08i40k/polytechnic/next/ui/main/profile/ChangeUsernameDialog.kt
+++ b/app/src/main/java/ru/n08i40k/polytechnic/next/ui/main/profile/ChangeUsernameDialog.kt
@@ -24,8 +24,7 @@ import com.android.volley.ClientError
import ru.n08i40k.polytechnic.next.R
import ru.n08i40k.polytechnic.next.data.users.impl.FakeProfileRepository
import ru.n08i40k.polytechnic.next.model.Profile
-import ru.n08i40k.polytechnic.next.network.data.profile.ChangeUsernameRequest
-import ru.n08i40k.polytechnic.next.network.data.profile.ChangeUsernameRequestData
+import ru.n08i40k.polytechnic.next.network.request.profile.ProfileChangeUsername
private enum class ChangeUsernameError {
INCORRECT_LENGTH,
@@ -38,7 +37,7 @@ private fun tryChangeUsername(
onError: (ChangeUsernameError) -> Unit,
onSuccess: () -> Unit
) {
- ChangeUsernameRequest(ChangeUsernameRequestData(username), context, {
+ ProfileChangeUsername(ProfileChangeUsername.RequestDto(username), context, {
onSuccess()
}, {
if (it is ClientError && it.networkResponse.statusCode == 409)
diff --git a/app/src/main/java/ru/n08i40k/polytechnic/next/ui/main/replacer/ReplacerScreen.kt b/app/src/main/java/ru/n08i40k/polytechnic/next/ui/main/replacer/ReplacerScreen.kt
index d00f03a..e2168b7 100644
--- a/app/src/main/java/ru/n08i40k/polytechnic/next/ui/main/replacer/ReplacerScreen.kt
+++ b/app/src/main/java/ru/n08i40k/polytechnic/next/ui/main/replacer/ReplacerScreen.kt
@@ -41,7 +41,7 @@ import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import ru.n08i40k.polytechnic.next.R
import ru.n08i40k.polytechnic.next.data.MockAppContainer
-import ru.n08i40k.polytechnic.next.data.schedule.impl.FakeScheduleReplacerRepository
+import ru.n08i40k.polytechnic.next.data.scheduleReplacer.impl.FakeScheduleReplacerRepository
import ru.n08i40k.polytechnic.next.model.ScheduleReplacer
import ru.n08i40k.polytechnic.next.ui.LoadingContent
import ru.n08i40k.polytechnic.next.ui.model.ScheduleReplacerUiState
diff --git a/app/src/main/java/ru/n08i40k/polytechnic/next/ui/main/schedule/DayCard.kt b/app/src/main/java/ru/n08i40k/polytechnic/next/ui/main/schedule/DayCard.kt
index eee3eca..60553b3 100644
--- a/app/src/main/java/ru/n08i40k/polytechnic/next/ui/main/schedule/DayCard.kt
+++ b/app/src/main/java/ru/n08i40k/polytechnic/next/ui/main/schedule/DayCard.kt
@@ -1,7 +1,5 @@
package ru.n08i40k.polytechnic.next.ui.main.schedule
-import android.os.Handler
-import android.os.Looper
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.background
import androidx.compose.foundation.border
@@ -17,12 +15,10 @@ import androidx.compose.material3.CardDefaults
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
-import androidx.compose.runtime.DisposableEffect
+import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
-import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource
@@ -30,6 +26,10 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
+import androidx.lifecycle.compose.collectAsStateWithLifecycle
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.flow
import ru.n08i40k.polytechnic.next.R
import ru.n08i40k.polytechnic.next.data.schedule.impl.FakeScheduleRepository
import ru.n08i40k.polytechnic.next.model.Day
@@ -44,26 +44,39 @@ private fun getCurrentMinutes(): Int {
}
@Composable
-private fun getMinutes(): Int {
- var value by remember { mutableIntStateOf(getCurrentMinutes()) }
-
- DisposableEffect(Unit) {
- val handler = Handler(Looper.getMainLooper())
-
- val runnable = {
- value = getCurrentMinutes()
- }
-
- handler.postDelayed(runnable, 60_000)
-
- onDispose {
- handler.removeCallbacks(runnable)
+private fun getMinutes(): Flow {
+ val value by remember {
+ derivedStateOf {
+ flow {
+ while (true) {
+ emit(getCurrentMinutes())
+ delay(5_000)
+ }
+ }
}
}
return value
}
+@Composable
+fun calculateCurrentLessonIdx(lessons: ArrayList): Int {
+ val currentMinutes by getMinutes().collectAsStateWithLifecycle(0)
+
+ val filteredLessons = lessons
+ .filterNotNull()
+ .filter {
+ it.time != null
+ && it.time.start >= currentMinutes
+ && it.time.end <= currentMinutes
+ }
+
+ if (filteredLessons.isEmpty())
+ return -1
+
+ return lessons.indexOf(filteredLessons[0])
+}
+
@Preview(showBackground = true)
@Composable
fun DayCard(
@@ -71,9 +84,26 @@ fun DayCard(
day: Day? = FakeScheduleRepository.exampleGroup.days[0],
current: Boolean = true
) {
+ val defaultCardColors = CardDefaults.cardColors(
+ containerColor = MaterialTheme.colorScheme.secondaryContainer,
+ contentColor = MaterialTheme.colorScheme.onSecondaryContainer,
+ )
+ val customCardColors = CardDefaults.cardColors(
+ containerColor = MaterialTheme.colorScheme.tertiaryContainer,
+ contentColor = MaterialTheme.colorScheme.onTertiaryContainer,
+ )
+ val noneCardColors = CardDefaults.cardColors(
+ containerColor = MaterialTheme.colorScheme.primaryContainer,
+ contentColor = MaterialTheme.colorScheme.onPrimaryContainer,
+ )
+
Card(
modifier = modifier,
- colors = CardDefaults.cardColors(containerColor = if (current) MaterialTheme.colorScheme.surfaceContainerHighest else MaterialTheme.colorScheme.surfaceContainerLowest)
+ colors = CardDefaults.cardColors(
+ containerColor =
+ if (current) MaterialTheme.colorScheme.surfaceContainerHighest
+ else MaterialTheme.colorScheme.surfaceContainerLowest
+ )
) {
if (day == null) {
Text(
@@ -92,87 +122,69 @@ fun DayCard(
text = day.name,
)
- val currentMinutes = getMinutes()
-
- val isCurrentLesson: (lesson: Lesson) -> Boolean = {
- current
- && it.time != null
- && currentMinutes >= it.time.start
- && currentMinutes <= it.time.end
- }
+ val currentLessonIdx = calculateCurrentLessonIdx(day.lessons)
Column(
- modifier = Modifier.fillMaxWidth(), verticalArrangement = Arrangement.spacedBy(0.5.dp)
+ modifier = Modifier.fillMaxWidth(),
+ verticalArrangement = Arrangement.spacedBy(0.5.dp)
) {
if (day.nonNullIndices.isEmpty()) {
Text("Can't get schedule!")
- } else {
- val defaultCardColors = CardDefaults.cardColors(
- containerColor = MaterialTheme.colorScheme.secondaryContainer,
- contentColor = MaterialTheme.colorScheme.onSecondaryContainer
- )
- val customCardColors = CardDefaults.cardColors(
- containerColor = MaterialTheme.colorScheme.tertiaryContainer,
- contentColor = MaterialTheme.colorScheme.onTertiaryContainer
- )
- val noneCardColors = CardDefaults.cardColors(
- containerColor = MaterialTheme.colorScheme.primaryContainer,
- contentColor = MaterialTheme.colorScheme.onPrimaryContainer,
+ return@Column
+ }
- )
+ for (i in day.nonNullIndices.first()..day.nonNullIndices.last()) {
+ val lesson = day.lessons[i]!!
- for (i in day.nonNullIndices.first()..day.nonNullIndices.last()) {
- val lesson = day.lessons[i]!!
+ val cardColors = when (lesson.type) {
+ LessonType.DEFAULT -> defaultCardColors
+ LessonType.CUSTOM -> customCardColors
+ }
- val cardColors = when (lesson.type) {
- LessonType.DEFAULT -> defaultCardColors
- LessonType.CUSTOM -> customCardColors
- }
+ val mutableExpanded = remember { mutableStateOf(false) }
- val mutableExpanded = remember { mutableStateOf(false) }
+ val lessonBoxModifier = remember {
+ Modifier
+ .padding(PaddingValues(2.5.dp, 0.dp))
+ .clickable { mutableExpanded.value = true }
+ .background(cardColors.containerColor)
+ }
- val lessonBoxModifier = remember {
- Modifier
- .padding(PaddingValues(2.5.dp, 0.dp))
- .clickable { mutableExpanded.value = true }
- .background(cardColors.containerColor)
- }
-
- Box(
- modifier = if (isCurrentLesson(lesson)) lessonBoxModifier.border(
- border = BorderStroke(
- 3.5.dp,
- Color(
- cardColors.containerColor.red * 0.5F,
- cardColors.containerColor.green * 0.5F,
- cardColors.containerColor.blue * 0.5F,
- 1F
- )
+ Box(
+ modifier =
+ if (i == currentLessonIdx) lessonBoxModifier.border(
+ border = BorderStroke(
+ 3.5.dp,
+ Color(
+ cardColors.containerColor.red * 0.5F,
+ cardColors.containerColor.green * 0.5F,
+ cardColors.containerColor.blue * 0.5F,
+ 1F
)
- ) else lessonBoxModifier
- ) {
- LessonRow(
- day, lesson, cardColors
)
- }
- if (i != day.nonNullIndices.last()) {
- Box(
- modifier = Modifier
- .padding(PaddingValues(2.5.dp, 0.dp))
- .background(noneCardColors.containerColor)
- ) {
- FreeLessonRow(
- lesson,
- day.lessons[day.nonNullIndices[day.nonNullIndices.indexOf(i) + 1]]!!,
- noneCardColors
- )
- }
- }
-
- if (mutableExpanded.value) LessonExtraInfo(
- lesson, mutableExpanded
+ )
+ else lessonBoxModifier
+ ) {
+ LessonRow(
+ day, lesson, cardColors
)
}
+ if (i != day.nonNullIndices.last()) {
+ Box(
+ modifier = Modifier
+ .padding(PaddingValues(2.5.dp, 0.dp))
+ .background(noneCardColors.containerColor)
+ ) {
+ FreeLessonRow(
+ lesson,
+ day.lessons[day.nonNullIndices[day.nonNullIndices.indexOf(i) + 1]]!!,
+ noneCardColors
+ )
+ }
+ }
+
+ if (mutableExpanded.value)
+ LessonExtraInfo(lesson, mutableExpanded)
}
}
}
diff --git a/app/src/main/java/ru/n08i40k/polytechnic/next/ui/main/schedule/ScheduleScreen.kt b/app/src/main/java/ru/n08i40k/polytechnic/next/ui/main/schedule/ScheduleScreen.kt
index 2fdaffe..73c23f0 100644
--- a/app/src/main/java/ru/n08i40k/polytechnic/next/ui/main/schedule/ScheduleScreen.kt
+++ b/app/src/main/java/ru/n08i40k/polytechnic/next/ui/main/schedule/ScheduleScreen.kt
@@ -6,26 +6,63 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.DisposableEffect
+import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
+import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.LifecycleEventObserver
+import androidx.lifecycle.LifecycleOwner
+import androidx.lifecycle.compose.LocalLifecycleOwner
import androidx.lifecycle.compose.collectAsStateWithLifecycle
+import kotlinx.coroutines.delay
import ru.n08i40k.polytechnic.next.R
import ru.n08i40k.polytechnic.next.data.MockAppContainer
import ru.n08i40k.polytechnic.next.ui.LoadingContent
import ru.n08i40k.polytechnic.next.ui.model.ScheduleUiState
import ru.n08i40k.polytechnic.next.ui.model.ScheduleViewModel
+@Composable
+private fun rememberUpdatedLifecycleOwner(): LifecycleOwner {
+ val lifecycleOwner = LocalLifecycleOwner.current
+ return remember { lifecycleOwner }
+}
+
@Preview(showBackground = true, showSystemUi = true)
@Composable
fun ScheduleScreen(
scheduleViewModel: ScheduleViewModel = ScheduleViewModel(MockAppContainer(LocalContext.current)),
- onRefreshSchedule: () -> Unit = {}
+ onRefresh: () -> Unit = {}
) {
val uiState by scheduleViewModel.uiState.collectAsStateWithLifecycle()
+ LaunchedEffect(uiState) {
+ delay(120_000)
+ onRefresh()
+ }
+
+ val lifecycleOwner = rememberUpdatedLifecycleOwner()
+
+ DisposableEffect(lifecycleOwner) {
+ val observer = LifecycleEventObserver { _, event ->
+ when (event) {
+ Lifecycle.Event.ON_RESUME -> {
+ onRefresh()
+ }
+ else -> Unit
+ }
+ }
+
+ lifecycleOwner.lifecycle.addObserver(observer)
+
+ onDispose {
+ lifecycleOwner.lifecycle.removeObserver(observer)
+ }
+ }
LoadingContent(
empty = when (uiState) {
@@ -33,13 +70,14 @@ fun ScheduleScreen(
is ScheduleUiState.HasSchedule -> false
},
loading = uiState.isLoading,
- onRefresh = { onRefreshSchedule() },
+ onRefresh = onRefresh,
verticalArrangement = Arrangement.Top
) {
when (uiState) {
is ScheduleUiState.HasSchedule -> {
Column {
val hasSchedule = uiState as ScheduleUiState.HasSchedule
+
UpdateInfo(hasSchedule.lastUpdateAt, hasSchedule.updateDates)
DayPager(hasSchedule.group)
}
@@ -47,7 +85,7 @@ fun ScheduleScreen(
is ScheduleUiState.NoSchedule -> {
if (!uiState.isLoading) {
- TextButton(onClick = onRefreshSchedule, modifier = Modifier.fillMaxSize()) {
+ TextButton(onClick = onRefresh, modifier = Modifier.fillMaxSize()) {
Text(stringResource(R.string.reload), textAlign = TextAlign.Center)
}
}
diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml
index 1d5faa3..0b2ecfb 100644
--- a/app/src/main/res/values-ru/strings.xml
+++ b/app/src/main/res/values-ru/strings.xml
@@ -40,4 +40,9 @@
байт
Удалить всё
Загрузить новое расписание
+ Обновления расписания
+ Информирует об обновлении расписания
+ Расписание обновлено.
+ Расписание было обновлено Администратором.
+ Расписание было обновлено на сайте политехникума.
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 8ed35e0..fe10ae3 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -40,4 +40,9 @@
bytes
Clear
Set new
+ Schedule update
+ Inform when schedule has been updated
+ Schedule has been updated.
+ Schedule was updated by Administrator.
+ Schedule was updated on polytechnic website.
\ No newline at end of file
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index cefa161..ad36080 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -1,7 +1,7 @@
[versions]
accompanistSwiperefresh = "0.36.0"
agp = "8.6.1"
-firebaseBom = "33.3.0"
+firebaseBom = "33.4.0"
hiltAndroid = "2.52"
hiltAndroidCompiler = "2.52"
hiltNavigationCompose = "1.2.0"
@@ -13,18 +13,22 @@ espressoCore = "3.6.1"
kotlinxSerializationJson = "1.7.3"
lifecycleRuntimeKtx = "2.8.6"
activityCompose = "1.9.2"
-composeBom = "2024.09.02"
+composeBom = "2024.09.03"
protobufLite = "3.0.1"
volley = "1.2.1"
datastore = "1.1.1"
-navigationCompose = "2.8.1"
-firebaseCrashlytics = "19.1.0"
+navigationCompose = "2.8.2"
+firebaseCrashlytics = "19.2.0"
googleFirebaseCrashlytics = "3.0.2"
+firebaseMessaging = "24.0.2"
+workRuntime = "2.9.1"
[libraries]
accompanist-swiperefresh = { module = "com.google.accompanist:accompanist-swiperefresh", version.ref = "accompanistSwiperefresh" }
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
androidx-hilt-navigation-compose = { module = "androidx.hilt:hilt-navigation-compose", version.ref = "hiltNavigationCompose" }
+androidx-work-runtime = { module = "androidx.work:work-runtime", version.ref = "workRuntime" }
+androidx-work-runtime-ktx = { module = "androidx.work:work-runtime-ktx", version.ref = "workRuntime" }
firebase-analytics = { module = "com.google.firebase:firebase-analytics" }
firebase-bom = { module = "com.google.firebase:firebase-bom", version.ref = "firebaseBom" }
hilt-android-compiler = { module = "com.google.dagger:hilt-android-compiler", version.ref = "hiltAndroidCompiler" }
@@ -40,7 +44,7 @@ androidx-ui = { group = "androidx.compose.ui", name = "ui" }
androidx-ui-graphics = { group = "androidx.compose.ui", name = "ui-graphics" }
androidx-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" }
androidx-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" }
-androidx-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest", version = "1.7.2" }
+androidx-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest", version = "1.7.3" }
androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" }
androidx-material3 = { group = "androidx.compose.material3", name = "material3" }
kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinxSerializationJson" }
@@ -48,6 +52,7 @@ protobuf-lite = { module = "com.google.protobuf:protobuf-lite", version.ref = "p
volley = { group = "com.android.volley", name = "volley", version.ref = "volley" }
androidx-navigation-compose = { group = "androidx.navigation", name = "navigation-compose", version.ref = "navigationCompose" }
firebase-crashlytics = { group = "com.google.firebase", name = "firebase-crashlytics", version.ref = "firebaseCrashlytics" }
+firebase-messaging = { group = "com.google.firebase", name = "firebase-messaging", version.ref = "firebaseMessaging" }
[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }