From 4029e937685c5da6022b398932f8e6d8bd1bd48b Mon Sep 17 00:00:00 2001 From: michael Date: Tue, 18 Apr 2023 01:07:53 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A1=D1=82=D0=B0=D0=B1=D0=B8=D0=BB=D1=8C?= =?UTF-8?q?=D0=BD=D0=B0=D1=8F=20=D0=B0=D1=83=D0=BD=D1=82=D0=B8=D1=84=D0=B8?= =?UTF-8?q?=D0=BA=D0=B0=D1=86=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/java/ru/megboyzz/dnevnik/App.kt | 6 +- .../java/ru/megboyzz/dnevnik/MainActivity.kt | 9 +- .../authorization/AuthorizationManager.kt | 83 ++++++++++++++---- .../authorization/AuthorizationStatus.kt | 4 +- .../ru/megboyzz/dnevnik/db/AppDataBase.kt | 19 ++++ .../dnevnik/db/CredentialsDataBase.kt | 16 ---- .../db/converters/DataStructureConverter.kt | 24 ++++++ .../megboyzz/dnevnik/db/dao/CredentialsDao.kt | 1 - .../dnevnik/db/dao/GlobalUserContextDao.kt | 24 ++++++ .../dnevnik/entities/context/GroupType.kt | 5 ++ .../dnevnik/entities/context/PeriodGroup.kt | 2 +- .../dnevnik/entities/context/PeriodInfo.kt | 2 +- .../dnevnik/entities/context/PersonContext.kt | 2 +- .../dnevnik/entities/context/SchoolInfo.kt | 3 +- .../dnevnik/entities/context/SchoolType.kt | 6 ++ .../context/marks/init/state/Group.kt | 8 ++ .../marks/init/state/GroupHistorical.kt | 9 ++ .../context/marks/init/state/MarksContext.kt | 6 ++ .../context/marks/init/state/Period.kt | 9 ++ .../marks/init/state/SchoolMembership.kt | 17 ++++ .../context/marks/init/state/SchoolType.kt | 8 ++ .../context/marks/init/state/UserContext.kt | 8 ++ .../dnevnik/entities/db/GlobalUserContext.kt | 17 ++++ .../dnevnik/entities/response/UserContext.kt | 1 + .../megboyzz/dnevnik/navigation/AppNavHost.kt | 17 +++- .../megboyzz/dnevnik/screens/LoginScreen.kt | 11 ++- .../megboyzz/dnevnik/screens/ui/Components.kt | 86 +++++++++++++++++-- .../megboyzz/dnevnik/screens/ui/Previews.kt | 9 ++ .../dnevnik/screens/ui/main/Drawer.kt | 73 ++++++++++++++-- .../dnevnik/screens/ui/main/Scaffolds.kt | 16 ++-- .../dnevnik/service/ContextService.kt | 12 +++ .../megboyzz/dnevnik/service/TokenService.kt | 18 ---- .../viewmodel/AuthorizationViewModel.kt | 4 +- .../dnevnik/viewmodel/ProfileViewModel.kt | 65 ++++++++++++++ .../viewmodel/model/UserProfileModel.kt | 13 +++ app/src/main/res/values-en-rUS/strings.xml | 6 ++ app/src/main/res/values/strings.xml | 6 ++ 37 files changed, 528 insertions(+), 97 deletions(-) create mode 100644 app/src/main/java/ru/megboyzz/dnevnik/db/AppDataBase.kt delete mode 100644 app/src/main/java/ru/megboyzz/dnevnik/db/CredentialsDataBase.kt create mode 100644 app/src/main/java/ru/megboyzz/dnevnik/db/converters/DataStructureConverter.kt create mode 100644 app/src/main/java/ru/megboyzz/dnevnik/db/dao/GlobalUserContextDao.kt create mode 100644 app/src/main/java/ru/megboyzz/dnevnik/entities/context/GroupType.kt create mode 100644 app/src/main/java/ru/megboyzz/dnevnik/entities/context/SchoolType.kt create mode 100644 app/src/main/java/ru/megboyzz/dnevnik/entities/context/marks/init/state/Group.kt create mode 100644 app/src/main/java/ru/megboyzz/dnevnik/entities/context/marks/init/state/GroupHistorical.kt create mode 100644 app/src/main/java/ru/megboyzz/dnevnik/entities/context/marks/init/state/MarksContext.kt create mode 100644 app/src/main/java/ru/megboyzz/dnevnik/entities/context/marks/init/state/Period.kt create mode 100644 app/src/main/java/ru/megboyzz/dnevnik/entities/context/marks/init/state/SchoolMembership.kt create mode 100644 app/src/main/java/ru/megboyzz/dnevnik/entities/context/marks/init/state/SchoolType.kt create mode 100644 app/src/main/java/ru/megboyzz/dnevnik/entities/context/marks/init/state/UserContext.kt create mode 100644 app/src/main/java/ru/megboyzz/dnevnik/entities/db/GlobalUserContext.kt create mode 100644 app/src/main/java/ru/megboyzz/dnevnik/service/ContextService.kt delete mode 100644 app/src/main/java/ru/megboyzz/dnevnik/service/TokenService.kt create mode 100644 app/src/main/java/ru/megboyzz/dnevnik/viewmodel/ProfileViewModel.kt create mode 100644 app/src/main/java/ru/megboyzz/dnevnik/viewmodel/model/UserProfileModel.kt diff --git a/app/src/main/java/ru/megboyzz/dnevnik/App.kt b/app/src/main/java/ru/megboyzz/dnevnik/App.kt index 6d05b9d..a32f157 100644 --- a/app/src/main/java/ru/megboyzz/dnevnik/App.kt +++ b/app/src/main/java/ru/megboyzz/dnevnik/App.kt @@ -2,18 +2,18 @@ package ru.megboyzz.dnevnik import android.app.Application import androidx.room.Room -import ru.megboyzz.dnevnik.db.CredentialsDataBase +import ru.megboyzz.dnevnik.db.AppDataBase class App : Application() { - lateinit var database: CredentialsDataBase + lateinit var database: AppDataBase private set override fun onCreate() { super.onCreate() instance = this - database = Room.databaseBuilder(this, CredentialsDataBase::class.java, "database") + database = Room.databaseBuilder(this, AppDataBase::class.java, "database") .build() } diff --git a/app/src/main/java/ru/megboyzz/dnevnik/MainActivity.kt b/app/src/main/java/ru/megboyzz/dnevnik/MainActivity.kt index 3857d49..7472a8f 100644 --- a/app/src/main/java/ru/megboyzz/dnevnik/MainActivity.kt +++ b/app/src/main/java/ru/megboyzz/dnevnik/MainActivity.kt @@ -4,6 +4,7 @@ import android.app.Application import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent +import androidx.compose.foundation.Image import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material.Surface import androidx.compose.runtime.Composable @@ -52,10 +53,12 @@ class MainActivity : ComponentActivity() { GlobalScope.launch(Dispatchers.IO) { val credentialsDao = app.database.credentialsDao() - val credentials = credentialsDao.getCredentials() - if(!credentials.rememberMe) - credentialsDao.deleteCredentials() + if(credentialsDao.credentialsIsExists()) { + val credentials = credentialsDao.getCredentials() + if (!credentials.rememberMe) + credentialsDao.deleteCredentials() + } } } diff --git a/app/src/main/java/ru/megboyzz/dnevnik/authorization/AuthorizationManager.kt b/app/src/main/java/ru/megboyzz/dnevnik/authorization/AuthorizationManager.kt index 73a6aeb..8e1b295 100644 --- a/app/src/main/java/ru/megboyzz/dnevnik/authorization/AuthorizationManager.kt +++ b/app/src/main/java/ru/megboyzz/dnevnik/authorization/AuthorizationManager.kt @@ -1,30 +1,54 @@ package ru.megboyzz.dnevnik.authorization -import android.util.Log +import com.google.gson.Gson import okhttp3.HttpUrl.Companion.toHttpUrlOrNull import org.jsoup.Connection import org.jsoup.Jsoup -import ru.megboyzz.dnevnik.db.dao.CredentialsDao +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import ru.megboyzz.dnevnik.db.AppDataBase +import ru.megboyzz.dnevnik.entities.context.marks.init.state.MarksContext +import ru.megboyzz.dnevnik.entities.context.marks.init.state.SchoolType import ru.megboyzz.dnevnik.entities.db.Credentials +import ru.megboyzz.dnevnik.entities.db.GlobalUserContext +import ru.megboyzz.dnevnik.service.ContextService import java.net.URL -class AuthorizationManager(private val credentialsDao: CredentialsDao) { +class AuthorizationManager(dataBase: AppDataBase) { private val returnUrl = "https://login.dnevnik.ru/oauth2?response_type=token&client_id=bb97b3e445a340b9b9cab4b9ea0dbd6f&scope=CommonInfo,ContactInfo,FriendsAndRelatives,EducationalInfo" private val baseUrl = "https://login.dnevnik.ru/login/" + private val apiUrl = "https://api.dnevnik.ru" + + private val retrofit = Retrofit + .Builder() + .baseUrl(apiUrl) + .addConverterFactory(GsonConverterFactory.create()) + .build() + + private val contextService = retrofit.create(ContextService::class.java) + + private val marksState = "https://dnevnik.ru/marks" + + private val credentialsDao = dataBase.credentialsDao() + + private val userContextDao = dataBase.globalUserContextDao() + private var credentials = Credentials(token = "", cookies = mapOf(), rememberMe = false) + private val gson = Gson() + fun login( login: String, password: String, rememberMe: Boolean ): AuthorizationStatus { - val execute = runCatching { + runCatching { Jsoup .connect(baseUrl) .method(Connection.Method.POST) @@ -34,26 +58,15 @@ class AuthorizationManager(private val credentialsDao: CredentialsDao) { .followRedirects(true) .execute() }.onFailure { - - Log.i("AuthorizationManager", "No internet") return AuthorizationStatus.NO_INTERNET - } - - val response = execute.getOrNull() - - if(response != null){ - - if(response.statusCode() != 200) { - Log.i("AuthorizationManager", "Maintain") + }.onSuccess { response -> + if(response.statusCode() != 200) return AuthorizationStatus.MAINTAIN - } val url = response.url() - if(url.getResult() != "success") { - Log.i("AuthorizationManager", "Wrong login") + if(url.getResult() != "success") return AuthorizationStatus.WRONG_CREDENTIALS - } //Безопасная зона val cookies = response.cookies() @@ -64,7 +77,39 @@ class AuthorizationManager(private val credentialsDao: CredentialsDao) { ) dbUpdate() - }else return AuthorizationStatus.NO_INTERNET //Может быть опасно + kotlin.runCatching { + + Jsoup + .connect(marksState) + .method(Connection.Method.GET) + .cookies(cookies) + .ignoreContentType(true) + .followRedirects(true) + .execute() + + }.onFailure { + return AuthorizationStatus.NO_INTERNET + }.onSuccess { response1 -> + val htmlByLines = response1.body().split("\n") + val contextLine = htmlByLines.find { it.contains("window.__MARKS__INITIAL__STATE__") } + val marksContextStr = + contextLine?.substring(contextLine.indexOf("{"), contextLine.length - 2) + val marksContext = gson.fromJson(marksContextStr, MarksContext::class.java) + + val context = contextService.getContext(credentials.token, marksContext.context.userId).execute() + + + + if(context.isSuccessful){ + val body = context.body() ?: return AuthorizationStatus.UNKNOWN_ERROR + userContextDao.setGlobalUserContext(GlobalUserContext( + apiUserContext = body, + marksInitStateUserContext = marksContext + )) + } else return AuthorizationStatus.UNKNOWN_ERROR + } + + } return AuthorizationStatus.LOGGED diff --git a/app/src/main/java/ru/megboyzz/dnevnik/authorization/AuthorizationStatus.kt b/app/src/main/java/ru/megboyzz/dnevnik/authorization/AuthorizationStatus.kt index 5f4cb7a..60591fd 100644 --- a/app/src/main/java/ru/megboyzz/dnevnik/authorization/AuthorizationStatus.kt +++ b/app/src/main/java/ru/megboyzz/dnevnik/authorization/AuthorizationStatus.kt @@ -7,6 +7,8 @@ enum class AuthorizationStatus { WRONG_CREDENTIALS, NO_INTERNET, MAINTAIN, - NOTHING + CREDENTIALS_LOADING, + NOTHING, + UNKNOWN_ERROR } \ No newline at end of file diff --git a/app/src/main/java/ru/megboyzz/dnevnik/db/AppDataBase.kt b/app/src/main/java/ru/megboyzz/dnevnik/db/AppDataBase.kt new file mode 100644 index 0000000..dc24a16 --- /dev/null +++ b/app/src/main/java/ru/megboyzz/dnevnik/db/AppDataBase.kt @@ -0,0 +1,19 @@ +package ru.megboyzz.dnevnik.db + +import androidx.room.Database +import androidx.room.RoomDatabase +import ru.megboyzz.dnevnik.db.dao.CredentialsDao +import ru.megboyzz.dnevnik.db.dao.GlobalUserContextDao +import ru.megboyzz.dnevnik.entities.db.Credentials +import ru.megboyzz.dnevnik.entities.db.GlobalUserContext + +@Database( + entities = [Credentials::class, GlobalUserContext::class], + version = 1 +) +abstract class AppDataBase: RoomDatabase() { + + abstract fun credentialsDao(): CredentialsDao + abstract fun globalUserContextDao(): GlobalUserContextDao + +} \ No newline at end of file diff --git a/app/src/main/java/ru/megboyzz/dnevnik/db/CredentialsDataBase.kt b/app/src/main/java/ru/megboyzz/dnevnik/db/CredentialsDataBase.kt deleted file mode 100644 index 671c3a0..0000000 --- a/app/src/main/java/ru/megboyzz/dnevnik/db/CredentialsDataBase.kt +++ /dev/null @@ -1,16 +0,0 @@ -package ru.megboyzz.dnevnik.db - -import androidx.room.Database -import androidx.room.RoomDatabase -import ru.megboyzz.dnevnik.db.dao.CredentialsDao -import ru.megboyzz.dnevnik.entities.db.Credentials - -@Database( - entities = [Credentials::class], - version = 1 -) -abstract class CredentialsDataBase: RoomDatabase() { - - abstract fun credentialsDao(): CredentialsDao - -} \ No newline at end of file diff --git a/app/src/main/java/ru/megboyzz/dnevnik/db/converters/DataStructureConverter.kt b/app/src/main/java/ru/megboyzz/dnevnik/db/converters/DataStructureConverter.kt new file mode 100644 index 0000000..6e5b850 --- /dev/null +++ b/app/src/main/java/ru/megboyzz/dnevnik/db/converters/DataStructureConverter.kt @@ -0,0 +1,24 @@ +package ru.megboyzz.dnevnik.db.converters + +import androidx.room.TypeConverter +import com.google.gson.Gson +import ru.megboyzz.dnevnik.entities.context.marks.init.state.MarksContext +import ru.megboyzz.dnevnik.entities.response.UserContext + +class DataStructureConverter { + + val gson = Gson() + + @TypeConverter + fun fromUserContext(userContext: UserContext): String = gson.toJson(userContext) + + @TypeConverter + fun toUserContext(savedUserContext: String): UserContext = gson.fromJson(savedUserContext, UserContext::class.java) + + @TypeConverter + fun fromMarksContext(marksContext: MarksContext): String = gson.toJson(marksContext) + + @TypeConverter + fun toMarksContext(savedMarksContext: String): MarksContext = gson.fromJson(savedMarksContext, MarksContext::class.java) + +} \ No newline at end of file diff --git a/app/src/main/java/ru/megboyzz/dnevnik/db/dao/CredentialsDao.kt b/app/src/main/java/ru/megboyzz/dnevnik/db/dao/CredentialsDao.kt index dab0cf7..182bbef 100644 --- a/app/src/main/java/ru/megboyzz/dnevnik/db/dao/CredentialsDao.kt +++ b/app/src/main/java/ru/megboyzz/dnevnik/db/dao/CredentialsDao.kt @@ -10,7 +10,6 @@ import ru.megboyzz.dnevnik.entities.db.Credentials @Dao interface CredentialsDao { - @Query("SELECT EXISTS(SELECT * FROM Credentials WHERE id = 0)") fun credentialsIsExists(): Boolean @Query("SELECT * FROM Credentials WHERE id = 0") diff --git a/app/src/main/java/ru/megboyzz/dnevnik/db/dao/GlobalUserContextDao.kt b/app/src/main/java/ru/megboyzz/dnevnik/db/dao/GlobalUserContextDao.kt new file mode 100644 index 0000000..654a6dc --- /dev/null +++ b/app/src/main/java/ru/megboyzz/dnevnik/db/dao/GlobalUserContextDao.kt @@ -0,0 +1,24 @@ +package ru.megboyzz.dnevnik.db.dao + +import androidx.room.Dao +import androidx.room.Insert +import androidx.room.OnConflictStrategy +import androidx.room.Query +import ru.megboyzz.dnevnik.entities.db.GlobalUserContext + +@Dao +interface GlobalUserContextDao { + + @Query("SELECT EXISTS(SELECT * FROM GlobalUserContext WHERE id = 0)") + fun globalUserContextIsExists(): Boolean + + @Query("SELECT * FROM GlobalUserContext WHERE id = 0") + fun getGlobalUserContext(): GlobalUserContext + + @Query("DELETE FROM GlobalUserContext WHERE id = 0") + fun deleteGlobalUserContext() + + @Insert(onConflict = OnConflictStrategy.REPLACE) + fun setGlobalUserContext(profile: GlobalUserContext) + +} \ No newline at end of file diff --git a/app/src/main/java/ru/megboyzz/dnevnik/entities/context/GroupType.kt b/app/src/main/java/ru/megboyzz/dnevnik/entities/context/GroupType.kt new file mode 100644 index 0000000..d2fd661 --- /dev/null +++ b/app/src/main/java/ru/megboyzz/dnevnik/entities/context/GroupType.kt @@ -0,0 +1,5 @@ +package ru.megboyzz.dnevnik.entities.context + +enum class GroupType { + Quarter +} \ No newline at end of file diff --git a/app/src/main/java/ru/megboyzz/dnevnik/entities/context/PeriodGroup.kt b/app/src/main/java/ru/megboyzz/dnevnik/entities/context/PeriodGroup.kt index f16e465..be64bb7 100644 --- a/app/src/main/java/ru/megboyzz/dnevnik/entities/context/PeriodGroup.kt +++ b/app/src/main/java/ru/megboyzz/dnevnik/entities/context/PeriodGroup.kt @@ -2,6 +2,6 @@ package ru.megboyzz.dnevnik.entities.context data class PeriodGroup( val id: Long, - val type: String, //Обычно равен "Quarter", то есть Четверть, но как будет семестр у них???? + val type: GroupType, //Обычно равен "Quarter", то есть Четверть, но как будет семестр у них???? val periods: List ) diff --git a/app/src/main/java/ru/megboyzz/dnevnik/entities/context/PeriodInfo.kt b/app/src/main/java/ru/megboyzz/dnevnik/entities/context/PeriodInfo.kt index 81f8031..158ee6f 100644 --- a/app/src/main/java/ru/megboyzz/dnevnik/entities/context/PeriodInfo.kt +++ b/app/src/main/java/ru/megboyzz/dnevnik/entities/context/PeriodInfo.kt @@ -3,7 +3,7 @@ package ru.megboyzz.dnevnik.entities.context data class PeriodInfo( val id: Long, val number: Short, - val type: String, + val type: GroupType, val dateStart: Long, val dateFinish: Long, val studyYear: Short, diff --git a/app/src/main/java/ru/megboyzz/dnevnik/entities/context/PersonContext.kt b/app/src/main/java/ru/megboyzz/dnevnik/entities/context/PersonContext.kt index 79cc26c..087d6ef 100644 --- a/app/src/main/java/ru/megboyzz/dnevnik/entities/context/PersonContext.kt +++ b/app/src/main/java/ru/megboyzz/dnevnik/entities/context/PersonContext.kt @@ -8,7 +8,7 @@ data class PersonContext( val middleName: String, val lastName: String, val avatarUrl: String, - val schoolInfo: SchoolInfo, + val school: SchoolInfo, val group: GroupInfo, val reportingPeriodGroup: PeriodGroup ) diff --git a/app/src/main/java/ru/megboyzz/dnevnik/entities/context/SchoolInfo.kt b/app/src/main/java/ru/megboyzz/dnevnik/entities/context/SchoolInfo.kt index 2260596..96ea564 100644 --- a/app/src/main/java/ru/megboyzz/dnevnik/entities/context/SchoolInfo.kt +++ b/app/src/main/java/ru/megboyzz/dnevnik/entities/context/SchoolInfo.kt @@ -3,5 +3,6 @@ package ru.megboyzz.dnevnik.entities.context data class SchoolInfo( val id: Long, val name: String, - val avatarUrl: String + val avatarUrl: String, + val type: SchoolType ) diff --git a/app/src/main/java/ru/megboyzz/dnevnik/entities/context/SchoolType.kt b/app/src/main/java/ru/megboyzz/dnevnik/entities/context/SchoolType.kt new file mode 100644 index 0000000..0558151 --- /dev/null +++ b/app/src/main/java/ru/megboyzz/dnevnik/entities/context/SchoolType.kt @@ -0,0 +1,6 @@ +package ru.megboyzz.dnevnik.entities.context + +enum class SchoolType { + Additional, + Regular +} \ No newline at end of file diff --git a/app/src/main/java/ru/megboyzz/dnevnik/entities/context/marks/init/state/Group.kt b/app/src/main/java/ru/megboyzz/dnevnik/entities/context/marks/init/state/Group.kt new file mode 100644 index 0000000..0e17d7e --- /dev/null +++ b/app/src/main/java/ru/megboyzz/dnevnik/entities/context/marks/init/state/Group.kt @@ -0,0 +1,8 @@ +package ru.megboyzz.dnevnik.entities.context.marks.init.state + +data class Group( + val groupId: String, + val groupName: String, + val reportingPeriodNotSet: Boolean, + val periodTabName: String +) diff --git a/app/src/main/java/ru/megboyzz/dnevnik/entities/context/marks/init/state/GroupHistorical.kt b/app/src/main/java/ru/megboyzz/dnevnik/entities/context/marks/init/state/GroupHistorical.kt new file mode 100644 index 0000000..7a3fcc5 --- /dev/null +++ b/app/src/main/java/ru/megboyzz/dnevnik/entities/context/marks/init/state/GroupHistorical.kt @@ -0,0 +1,9 @@ +package ru.megboyzz.dnevnik.entities.context.marks.init.state + +data class GroupHistorical( + val id: String, + val name: String, + val studyYear: Int, + val periods: List, + val periodTabName: String +) diff --git a/app/src/main/java/ru/megboyzz/dnevnik/entities/context/marks/init/state/MarksContext.kt b/app/src/main/java/ru/megboyzz/dnevnik/entities/context/marks/init/state/MarksContext.kt new file mode 100644 index 0000000..ba59992 --- /dev/null +++ b/app/src/main/java/ru/megboyzz/dnevnik/entities/context/marks/init/state/MarksContext.kt @@ -0,0 +1,6 @@ +package ru.megboyzz.dnevnik.entities.context.marks.init.state + +data class MarksContext( + val apiUrl: String, + val context: UserContext +) diff --git a/app/src/main/java/ru/megboyzz/dnevnik/entities/context/marks/init/state/Period.kt b/app/src/main/java/ru/megboyzz/dnevnik/entities/context/marks/init/state/Period.kt new file mode 100644 index 0000000..0e8b33b --- /dev/null +++ b/app/src/main/java/ru/megboyzz/dnevnik/entities/context/marks/init/state/Period.kt @@ -0,0 +1,9 @@ +package ru.megboyzz.dnevnik.entities.context.marks.init.state + +data class Period( + val id: String, + val name: String, + val shortName: String, + val number: Int, + val isDefault: Boolean +) diff --git a/app/src/main/java/ru/megboyzz/dnevnik/entities/context/marks/init/state/SchoolMembership.kt b/app/src/main/java/ru/megboyzz/dnevnik/entities/context/marks/init/state/SchoolMembership.kt new file mode 100644 index 0000000..94a234d --- /dev/null +++ b/app/src/main/java/ru/megboyzz/dnevnik/entities/context/marks/init/state/SchoolMembership.kt @@ -0,0 +1,17 @@ +package ru.megboyzz.dnevnik.entities.context.marks.init.state + +data class SchoolMembership( + val personId: String, + val firstName: String, + val lastName: String, + val avatarUrl: String, + val schoolId: String, + val schoolName: String, + val isOdo: Boolean, + val isTermReportEnabled: Boolean, + val studyYear: Int, + val schoolType: SchoolType, + val groups: List, + val holidays: List, + val groupHistory: List +) diff --git a/app/src/main/java/ru/megboyzz/dnevnik/entities/context/marks/init/state/SchoolType.kt b/app/src/main/java/ru/megboyzz/dnevnik/entities/context/marks/init/state/SchoolType.kt new file mode 100644 index 0000000..9ba301c --- /dev/null +++ b/app/src/main/java/ru/megboyzz/dnevnik/entities/context/marks/init/state/SchoolType.kt @@ -0,0 +1,8 @@ +package ru.megboyzz.dnevnik.entities.context.marks.init.state + +enum class SchoolType { + + Regular, + Additional + +} \ No newline at end of file diff --git a/app/src/main/java/ru/megboyzz/dnevnik/entities/context/marks/init/state/UserContext.kt b/app/src/main/java/ru/megboyzz/dnevnik/entities/context/marks/init/state/UserContext.kt new file mode 100644 index 0000000..31388fa --- /dev/null +++ b/app/src/main/java/ru/megboyzz/dnevnik/entities/context/marks/init/state/UserContext.kt @@ -0,0 +1,8 @@ +package ru.megboyzz.dnevnik.entities.context.marks.init.state + + +data class UserContext( + val userId: String, + val role: String, + val schoolMemberships: List, +) diff --git a/app/src/main/java/ru/megboyzz/dnevnik/entities/db/GlobalUserContext.kt b/app/src/main/java/ru/megboyzz/dnevnik/entities/db/GlobalUserContext.kt new file mode 100644 index 0000000..6f8941c --- /dev/null +++ b/app/src/main/java/ru/megboyzz/dnevnik/entities/db/GlobalUserContext.kt @@ -0,0 +1,17 @@ +package ru.megboyzz.dnevnik.entities.db + +import androidx.room.Entity +import androidx.room.PrimaryKey +import androidx.room.TypeConverters +import ru.megboyzz.dnevnik.db.converters.DataStructureConverter +import ru.megboyzz.dnevnik.entities.context.marks.init.state.MarksContext +import ru.megboyzz.dnevnik.entities.response.UserContext + +@Entity +@TypeConverters(DataStructureConverter::class) +data class GlobalUserContext( + @PrimaryKey + val id: Int = 0, + val apiUserContext: UserContext, // Обычный контекст из API + val marksInitStateUserContext: MarksContext //window.__MARKS__INITIAL__STATE__ +) diff --git a/app/src/main/java/ru/megboyzz/dnevnik/entities/response/UserContext.kt b/app/src/main/java/ru/megboyzz/dnevnik/entities/response/UserContext.kt index 5702b12..cd88f31 100644 --- a/app/src/main/java/ru/megboyzz/dnevnik/entities/response/UserContext.kt +++ b/app/src/main/java/ru/megboyzz/dnevnik/entities/response/UserContext.kt @@ -3,6 +3,7 @@ package ru.megboyzz.dnevnik.entities.response import ru.megboyzz.dnevnik.entities.context.PersonContext import ru.megboyzz.dnevnik.entities.context.UserInfo + data class UserContext( val info: UserInfo, val contextPersons: List diff --git a/app/src/main/java/ru/megboyzz/dnevnik/navigation/AppNavHost.kt b/app/src/main/java/ru/megboyzz/dnevnik/navigation/AppNavHost.kt index bd8f8a5..d6ec8ac 100644 --- a/app/src/main/java/ru/megboyzz/dnevnik/navigation/AppNavHost.kt +++ b/app/src/main/java/ru/megboyzz/dnevnik/navigation/AppNavHost.kt @@ -1,5 +1,6 @@ package ru.megboyzz.dnevnik.navigation +import androidx.compose.material.CircularProgressIndicator import androidx.compose.material.rememberScaffoldState import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect @@ -18,6 +19,7 @@ import ru.megboyzz.dnevnik.collectAsMutableState import ru.megboyzz.dnevnik.screens.* import ru.megboyzz.dnevnik.viewmodel.AuthorizationViewModel import ru.megboyzz.dnevnik.viewmodel.AuthorizationViewModelFactory +import ru.megboyzz.dnevnik.navigate sealed class BaseNavRote(open val route: String) @@ -52,11 +54,18 @@ fun AppNavHost(){ ){ composable(AppNavRoute.Splash.route) { - if(loginStatus.value != AuthorizationStatus.LOGGED){ - navController.navigate(AppNavRoute.Login.route) - }else - navController.navigate(AppNavRoute.Marks.route) + when(loginStatus.value){ + AuthorizationStatus.CREDENTIALS_LOADING -> { CircularProgressIndicator() } + AuthorizationStatus.LOGGED -> { + navController.navigate(AppNavRoute.Marks) + } + AuthorizationStatus.NOTHING -> { + navController.navigate(AppNavRoute.Login) + } + else -> {} + + } } composable(AppNavRoute.Login.route) { LoginScreen(navController) } diff --git a/app/src/main/java/ru/megboyzz/dnevnik/screens/LoginScreen.kt b/app/src/main/java/ru/megboyzz/dnevnik/screens/LoginScreen.kt index a790382..08f2081 100644 --- a/app/src/main/java/ru/megboyzz/dnevnik/screens/LoginScreen.kt +++ b/app/src/main/java/ru/megboyzz/dnevnik/screens/LoginScreen.kt @@ -7,6 +7,7 @@ import androidx.navigation.NavController import ru.megboyzz.dnevnik.MainActivity import ru.megboyzz.dnevnik.authorization.AuthorizationStatus import ru.megboyzz.dnevnik.collectAsMutableState +import ru.megboyzz.dnevnik.navigate import ru.megboyzz.dnevnik.navigation.AppNavRoute import ru.megboyzz.dnevnik.screens.ui.AlertMessageBox import ru.megboyzz.dnevnik.screens.ui.LoginScreenContent @@ -35,6 +36,12 @@ fun LoginScreen(navController: NavController) { mutableStateOf(true) } + var isLoading by remember { + mutableStateOf(false) + } + + if(loginStatus.value == AuthorizationStatus.LOGGING) isLoading = true + if(loginStatus.value == AuthorizationStatus.WRONG_CREDENTIALS && isError) { AlertMessageBox( title = "Информация", @@ -44,7 +51,7 @@ fun LoginScreen(navController: NavController) { } if(loginStatus.value == AuthorizationStatus.LOGGED) - navController.navigate(AppNavRoute.Marks.route) + navController.navigate(AppNavRoute.Marks) LoginScreenContent( login = login.value, @@ -56,7 +63,7 @@ fun LoginScreen(navController: NavController) { isError = loginStatus.value == AuthorizationStatus.WRONG_CREDENTIALS, onErrorChange = { }, - isLoading = loginStatus.value == AuthorizationStatus.LOGGING, + isLoading = isLoading, isRememberMe = rememberMe.value, onRememberChange = { rememberMe.value = it }, diff --git a/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/Components.kt b/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/Components.kt index 34be277..a8daecc 100644 --- a/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/Components.kt +++ b/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/Components.kt @@ -1,5 +1,6 @@ package ru.megboyzz.dnevnik.screens.ui +import android.app.AlertDialog import androidx.compose.animation.* import androidx.compose.animation.core.tween import androidx.compose.foundation.* @@ -8,6 +9,7 @@ import androidx.compose.foundation.lazy.grid.GridCells import androidx.compose.foundation.lazy.grid.LazyVerticalGrid import androidx.compose.foundation.lazy.grid.items import androidx.compose.foundation.selection.toggleable +import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material.* @@ -20,11 +22,13 @@ import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip +import androidx.compose.ui.draw.clipToBounds import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.focus.onFocusChanged import androidx.compose.ui.graphics.* import androidx.compose.ui.graphics.painter.Painter +import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.semantics.Role import androidx.compose.ui.text.input.KeyboardType @@ -33,9 +37,11 @@ import androidx.compose.ui.text.input.VisualTransformation import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.* +import coil.compose.AsyncImage import ru.megboyzz.dnevnik.* import ru.megboyzz.dnevnik.R import ru.megboyzz.dnevnik.ui.theme.* +import ru.megboyzz.dnevnik.viewmodel.model.UserProfileModel //Рефакторинг компонентов: разбиение файла с компонентами на отдельные файлы @@ -73,25 +79,29 @@ fun AlmostOutlinedText( @Composable fun ProfileCard( textColor: Color = white, - painter: Painter + userProfileModel: UserProfileModel ) { Row( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.Start ) { - Image( - modifier = Modifier.padding(10.dp, 15.dp, 20.dp, 15.dp), - painter = painter, //TODO заменить динмической картинкой - contentDescription = "chel" + AsyncImage( + modifier = Modifier + .padding(10.dp, 15.dp, 20.dp, 15.dp) + .clip(RoundedCornerShape(25.dp)) + .size(50.dp), + contentScale = ContentScale.Crop, + model = userProfileModel.avatarUrl, + contentDescription = "" ) Column(verticalArrangement = Arrangement.spacedBy(5.dp)) { Text( - text = "Имя и фамилия", + text = userProfileModel.toString(), style = H1, color = textColor ) Text( - text = "Класс/Группа", + text = userProfileModel.groupName, style = H1, color = textColor ) @@ -640,3 +650,65 @@ fun AlertMessageBox( ) } + + +@Composable +fun LeaveAlert( + isLoading: Boolean = false, + onAgree: () -> Unit, + onCancel: () -> Unit, +){ + BaseAlertBox( + title = R.string.tile_leave.AsString(), + onDismissRequest = onCancel, + content = { + Row(horizontalArrangement = Arrangement.spacedBy(10.dp)) { + Text( + text = R.string.text_leave.AsString(), + style = H2, + color = dark + ) + if(isLoading) CircularProgressIndicator() + } + }, + buttons = { + Row( + horizontalArrangement = Arrangement.Center, + modifier = Modifier.fillMaxWidth() + ) { + AlertButton( + title = R.string.title_cancel.AsString(), + onClick = onCancel + ) + SpacerWidth(width = 10.dp) + AlertButton( + title = R.string.title_button_leave.AsString(), + onClick = onAgree + ) + + } + } + ) +} + +@Composable +fun AlertButton( + title: String, + onClick: () -> Unit +) { + Button( + onClick = onClick, + shape = RoundedCornerShape(8.dp), + colors = ButtonDefaults.buttonColors( + backgroundColor = mainBlue, + contentColor = white + ), + modifier = Modifier + .padding(bottom = 30.dp) + ){ + Text( + text = title, + style = H1 + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/Previews.kt b/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/Previews.kt index a14d56a..0b525ef 100644 --- a/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/Previews.kt +++ b/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/Previews.kt @@ -392,4 +392,13 @@ fun Test1() { onClick = { /*TODO*/ } ) +} + +@Preview +@Composable +fun AlertTest() { + LeaveAlert(onAgree = { /*TODO*/ }) { + + } + } \ No newline at end of file diff --git a/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/main/Drawer.kt b/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/main/Drawer.kt index e041815..70e382d 100644 --- a/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/main/Drawer.kt +++ b/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/main/Drawer.kt @@ -5,12 +5,8 @@ import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.Divider -import androidx.compose.material.ScaffoldState -import androidx.compose.material.Surface -import androidx.compose.material.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.material.* +import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip @@ -20,24 +16,34 @@ import androidx.compose.ui.geometry.Rect import androidx.compose.ui.geometry.RoundRect import androidx.compose.ui.geometry.Size import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.ImageBitmap import androidx.compose.ui.graphics.Outline import androidx.compose.ui.graphics.Shape +import androidx.compose.ui.graphics.painter.BitmapPainter import androidx.compose.ui.graphics.painter.Painter +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.imageResource import androidx.compose.ui.unit.Density import androidx.compose.ui.unit.LayoutDirection import androidx.compose.ui.unit.dp import androidx.compose.ui.zIndex +import androidx.lifecycle.viewmodel.compose.viewModel import androidx.navigation.NavController +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import ru.megboyzz.dnevnik.* import ru.megboyzz.dnevnik.R import ru.megboyzz.dnevnik.navigation.AppNavRoute import ru.megboyzz.dnevnik.screens.ui.AlmostOutlinedText +import ru.megboyzz.dnevnik.screens.ui.LeaveAlert import ru.megboyzz.dnevnik.screens.ui.ProfileCard import ru.megboyzz.dnevnik.ui.theme.H2 import ru.megboyzz.dnevnik.ui.theme.Shapes import ru.megboyzz.dnevnik.ui.theme.mainBlue import ru.megboyzz.dnevnik.ui.theme.white +import ru.megboyzz.dnevnik.viewmodel.ProfileViewModel +import ru.megboyzz.dnevnik.viewmodel.ProfileViewModelFactory +import ru.megboyzz.dnevnik.viewmodel.model.UserProfileModel @Composable @@ -77,7 +83,43 @@ fun DrawerContent( scaffoldState: ScaffoldState ) { + val app = (LocalContext.current as MainActivity).app + + val profileViewModel: ProfileViewModel = viewModel( + factory = ProfileViewModelFactory(app) + ) + + val profile = profileViewModel.profile.collectAsState() + + val dao = app.database.credentialsDao() + + + var leaveAlertIsOpened by remember { + mutableStateOf(false) + } + + var isLeavingProcess by remember { + mutableStateOf(false) + } + val scope = rememberCoroutineScope() + + if(leaveAlertIsOpened){ + LeaveAlert( + isLoading = isLeavingProcess, + onAgree = { + scope.launch(Dispatchers.IO) { + isLeavingProcess = true + dao.deleteCredentials() + leaveAlertIsOpened = false + this.launch(Dispatchers.Main) { navController.navigate(AppNavRoute.Login) } + scaffoldState.drawerState.close() + } + }, + onCancel = { leaveAlertIsOpened = false } + ) + } + NiceContainerForDrawer { Column( modifier = Modifier @@ -88,9 +130,20 @@ fun DrawerContent( horizontalAlignment = Alignment.Start, ) { SpacerHeight(10.dp) - ProfileCard(painter = R.drawable.ic_author.AsPainter()) + if(profile.value == null) + CircularProgressIndicator() + else + ProfileCard(userProfileModel = profile.value!!) SpacerHeight(15.dp) - AlmostOutlinedText(text = "Идет 3-я четверть") + if(profile.value == null) + CircularProgressIndicator() + else + AlmostOutlinedText( + text = if(profile.value!!.isTerm) + String.format(R.string.title_quatter_format.AsString(), profile.value!!.term) + else + String.format(R.string.title_sem_format.AsString(), profile.value!!.term) + ) SpacerHeight(20.dp) Column( verticalArrangement = Arrangement.spacedBy(5.dp), @@ -135,7 +188,9 @@ fun DrawerContent( DrawerMainButton( icon = R.drawable.ic_exit.AsPainter(), text = R.string.title_leave_from_acconut.AsString() - ) { /* TODO */ } + ) { + leaveAlertIsOpened = true + } } } } diff --git a/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/main/Scaffolds.kt b/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/main/Scaffolds.kt index d294e11..b51cf1f 100644 --- a/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/main/Scaffolds.kt +++ b/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/main/Scaffolds.kt @@ -1,10 +1,7 @@ package ru.megboyzz.dnevnik.screens.ui.main import androidx.compose.foundation.Image -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.* import androidx.compose.material.* import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.ArrowBack @@ -25,6 +22,7 @@ import ru.megboyzz.dnevnik.SpacerWidth import ru.megboyzz.dnevnik.ui.theme.mainBlue import ru.megboyzz.dnevnik.ui.theme.white import ru.megboyzz.dnevnik.R +import ru.megboyzz.dnevnik.viewmodel.model.UserProfileModel @Composable fun MainScaffold( @@ -32,7 +30,7 @@ fun MainScaffold( title: String, navController: NavController, scaffoldState: ScaffoldState, - content: (@Composable (it: PaddingValues) -> Unit), + content: @Composable (PaddingValues) -> Unit, ) { val scope = rememberCoroutineScope() @@ -52,6 +50,9 @@ fun MainScaffold( navController = navController, scaffoldState = scaffoldState, bottomBar = { BottomBar(navController) }, + drawerContent = { + DrawerContent(navController, scaffoldState) + }, content = content ) } @@ -65,6 +66,7 @@ fun BaseScaffold( navController: NavController, scaffoldState: ScaffoldState, bottomBar: @Composable () -> Unit, + drawerContent: @Composable (ColumnScope) -> Unit = {}, content: (@Composable (it: PaddingValues) -> Unit), ) { Scaffold( @@ -100,9 +102,7 @@ fun BaseScaffold( drawerContentColor = Color.Transparent, //drawerShape = drawerShape, drawerElevation = 0.dp, - drawerContent = { - DrawerContent(navController, scaffoldState) - }, + drawerContent = drawerContent, bottomBar = bottomBar ) } diff --git a/app/src/main/java/ru/megboyzz/dnevnik/service/ContextService.kt b/app/src/main/java/ru/megboyzz/dnevnik/service/ContextService.kt new file mode 100644 index 0000000..cff2fad --- /dev/null +++ b/app/src/main/java/ru/megboyzz/dnevnik/service/ContextService.kt @@ -0,0 +1,12 @@ +package ru.megboyzz.dnevnik.service + +import retrofit2.Call +import retrofit2.http.* +import ru.megboyzz.dnevnik.entities.response.UserContext + +interface ContextService{ + + @GET("/mobile/v4/users/{personId}/context") + fun getContext(@Header("Access-Token") accessToken: String, @Path("personId") personId: String): Call + +} \ No newline at end of file diff --git a/app/src/main/java/ru/megboyzz/dnevnik/service/TokenService.kt b/app/src/main/java/ru/megboyzz/dnevnik/service/TokenService.kt deleted file mode 100644 index 8ac8561..0000000 --- a/app/src/main/java/ru/megboyzz/dnevnik/service/TokenService.kt +++ /dev/null @@ -1,18 +0,0 @@ -package ru.megboyzz.dnevnik.service - - -import okhttp3.ResponseBody -import org.jsoup.Jsoup -import retrofit2.http.POST -import retrofit2.http.Query - -interface TokenService{ - - @POST("/") - suspend fun getToken( - @Query("login") login: String, - @Query("password") password: String, - @Query("ReturnUrl") returnUrl: String = "https://login.dnevnik.ru/oauth2?response_type=token&client_id=bb97b3e445a340b9b9cab4b9ea0dbd6f&scope=CommonInfo,ContactInfo,FriendsAndRelatives,EducationalInfo" - ): retrofit2.Call - -} \ No newline at end of file diff --git a/app/src/main/java/ru/megboyzz/dnevnik/viewmodel/AuthorizationViewModel.kt b/app/src/main/java/ru/megboyzz/dnevnik/viewmodel/AuthorizationViewModel.kt index 885a38f..f2608dd 100644 --- a/app/src/main/java/ru/megboyzz/dnevnik/viewmodel/AuthorizationViewModel.kt +++ b/app/src/main/java/ru/megboyzz/dnevnik/viewmodel/AuthorizationViewModel.kt @@ -19,8 +19,8 @@ class AuthorizationViewModel(application: App) : AndroidViewModel(application) { val password = MutableStateFlow("") val rememberMe = MutableStateFlow(false) - val loginStatus = MutableStateFlow(AuthorizationStatus.NOTHING) - private val authManager = AuthorizationManager(application.database.credentialsDao()) + val loginStatus = MutableStateFlow(AuthorizationStatus.CREDENTIALS_LOADING) + private val authManager = AuthorizationManager(application.database) init { viewModelScope.launch(Dispatchers.IO) { diff --git a/app/src/main/java/ru/megboyzz/dnevnik/viewmodel/ProfileViewModel.kt b/app/src/main/java/ru/megboyzz/dnevnik/viewmodel/ProfileViewModel.kt new file mode 100644 index 0000000..a8976c2 --- /dev/null +++ b/app/src/main/java/ru/megboyzz/dnevnik/viewmodel/ProfileViewModel.kt @@ -0,0 +1,65 @@ +package ru.megboyzz.dnevnik.viewmodel + +import androidx.lifecycle.AndroidViewModel +import androidx.lifecycle.ViewModel +import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.launch +import ru.megboyzz.dnevnik.App +import ru.megboyzz.dnevnik.entities.context.GroupType +import ru.megboyzz.dnevnik.entities.context.SchoolType +import ru.megboyzz.dnevnik.entities.db.GlobalUserContext +import ru.megboyzz.dnevnik.viewmodel.model.UserProfileModel +import java.lang.IllegalArgumentException + +class ProfileViewModel(application: App) : AndroidViewModel(application) { + + val profile = MutableStateFlow(null) + + val userContextDao = application.database.globalUserContextDao() + + init{ + viewModelScope.launch(Dispatchers.IO) { + val globalUserContext = userContextDao.getGlobalUserContext() + val convertedProfile = convertGlobalUserContextToProfile(globalUserContext) + profile.emit(convertedProfile) + } + } + + private fun convertGlobalUserContextToProfile( + globalUserContext: GlobalUserContext + ): UserProfileModel{ + val info = globalUserContext.apiUserContext.info + + val personContext = globalUserContext.apiUserContext.contextPersons.find { + it.school.type == SchoolType.Regular + } ?: globalUserContext.apiUserContext.contextPersons[0] + + val term = personContext.reportingPeriodGroup.periods.find { + it.isCurrent + } ?: personContext.reportingPeriodGroup.periods[0] + + return UserProfileModel( + firstName = info.firstName, + middleName = info.middleName, + lastName = info.lastName, + groupName = personContext.group.name, + term = term.number + 1, + isTerm = term.type == GroupType.Quarter, + avatarUrl = info.avatarUrl + ) + } + +} + +class ProfileViewModelFactory(private val application: App) : ViewModelProvider.Factory { + + override fun create(modelClass: Class): T { + if (modelClass.isAssignableFrom(ProfileViewModel::class.java)) + return ProfileViewModel(application) as T + throw IllegalArgumentException("Unknown ViewModel Class") + } + +} \ No newline at end of file diff --git a/app/src/main/java/ru/megboyzz/dnevnik/viewmodel/model/UserProfileModel.kt b/app/src/main/java/ru/megboyzz/dnevnik/viewmodel/model/UserProfileModel.kt new file mode 100644 index 0000000..9b1f4c2 --- /dev/null +++ b/app/src/main/java/ru/megboyzz/dnevnik/viewmodel/model/UserProfileModel.kt @@ -0,0 +1,13 @@ +package ru.megboyzz.dnevnik.viewmodel.model + +data class UserProfileModel( + val firstName: String, + val middleName: String, + val lastName: String, + val groupName: String, + val term: Int, + val isTerm: Boolean, + val avatarUrl: String +){ + override fun toString() = "$lastName ${firstName.first()}. ${middleName.first()}." +} diff --git a/app/src/main/res/values-en-rUS/strings.xml b/app/src/main/res/values-en-rUS/strings.xml index 5cad793..55b5c25 100644 --- a/app/src/main/res/values-en-rUS/strings.xml +++ b/app/src/main/res/values-en-rUS/strings.xml @@ -72,4 +72,10 @@ " Select the icons for subjects" Enable notify ОК + Leave + Are you sure you want to exit the diary? + Leave + Cancel + Quatter %d + Semester %d \ 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 24d6a11..7e1a582 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -71,4 +71,10 @@ Выбрать иконки для предметов Включить уведомления о новых оценках Ясно + Выход + Вы точно хотите выйти из дневника? Авторизационные данные будут удалены. + Выйти + Отмена + Идет %d-я четверть + Идет %d-ий семестр \ No newline at end of file