From f9d4ff562d5be24f329add9dd11e31ff640b4413 Mon Sep 17 00:00:00 2001 From: Odweta Date: Fri, 20 Dec 2024 17:31:28 +0100 Subject: [PATCH] refined the launch proccess and improved the architecture of global variables --- .../src/main/java/com/odweta/solon/About.kt | 36 +----- .../com/odweta/solon/BackButtonFactory.kt | 75 ++++++++++++ .../src/main/java/com/odweta/solon/Global.kt | 50 +++++++- .../src/main/java/com/odweta/solon/Launch2.kt | 111 ++++++++++++++++++ .../java/com/odweta/solon/MainActivity.kt | 2 +- .../src/main/java/com/odweta/solon/Marks.kt | 72 ++---------- .../src/main/java/com/odweta/solon/Menu.kt | 4 +- .../src/main/java/com/odweta/solon/Navbar.kt | 8 +- .../src/main/java/com/odweta/solon/Network.kt | 75 +++++++++++- .../src/main/java/com/odweta/solon/Parsing.kt | 43 ++++++- .../main/java/com/odweta/solon/Settings.kt | 26 +++- .../src/main/java/com/odweta/solon/SignIn.kt | 6 +- .../src/main/java/com/odweta/solon/Toolbar.kt | 4 + .../src/main/java/com/odweta/solon/Util.kt | 4 +- 14 files changed, 403 insertions(+), 113 deletions(-) create mode 100644 mobile/app/src/main/java/com/odweta/solon/BackButtonFactory.kt create mode 100644 mobile/app/src/main/java/com/odweta/solon/Launch2.kt diff --git a/mobile/app/src/main/java/com/odweta/solon/About.kt b/mobile/app/src/main/java/com/odweta/solon/About.kt index ef097d0..d8978e7 100644 --- a/mobile/app/src/main/java/com/odweta/solon/About.kt +++ b/mobile/app/src/main/java/com/odweta/solon/About.kt @@ -38,10 +38,10 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp @Composable -fun AboutScreen(modifier: Modifier = Modifier) { +fun AboutScreen() { // handle the back gesture (back swipe form side or back button on bottom android navbar) BackHandler { - isShowing.value = IsShowing.Menu + isShowing = IsShowing.Menu } Column( @@ -50,35 +50,7 @@ fun AboutScreen(modifier: Modifier = Modifier) { verticalArrangement = Arrangement.Top, horizontalAlignment = Alignment.Start ) { - Box( - modifier = Modifier - .fillMaxWidth() - .padding(start = 5.dp) - ) { - Button( - onClick = { - isShowing.value = IsShowing.Menu - }, - colors = ButtonDefaults.buttonColors( - contentColor = Color.White, - containerColor = Color.Black - ), - modifier = Modifier - .border( - width = 5.dp, - shape = RoundedCornerShape(roundedCornerDimen), - color = PastelYellow - ) - .width(70.dp) - .height(70.dp) - ) { - Icon( - imageVector = Icons.Default.ArrowBackIosNew, - contentDescription = "Back icon", - modifier = Modifier.size(40.dp) - ) - } - } + backButtonFactory.get(BackButtonType.Menu)() Column( modifier = Modifier.fillMaxWidth(), @@ -126,7 +98,7 @@ fun AboutScreen(modifier: Modifier = Modifier) { } @Composable -fun HorizontalLine(modifier: Modifier = Modifier) { +fun HorizontalLine() { Spacer(modifier = Modifier.height(20.dp)) Spacer(modifier = Modifier diff --git a/mobile/app/src/main/java/com/odweta/solon/BackButtonFactory.kt b/mobile/app/src/main/java/com/odweta/solon/BackButtonFactory.kt new file mode 100644 index 0000000..f9a89a4 --- /dev/null +++ b/mobile/app/src/main/java/com/odweta/solon/BackButtonFactory.kt @@ -0,0 +1,75 @@ +package com.odweta.solon + +import androidx.compose.foundation.border +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.ArrowBackIosNew +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.Icon +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.dp +import com.odweta.solon.ui.theme.PastelYellow + +enum class BackButtonType { + Menu, + MarksSubject, + MarksAll +} + +interface BackButtonFactoryInterface { + @Composable + fun get(type: BackButtonType): @Composable () -> Unit +} + +@Composable +fun BackButton(onClick: () -> Unit) { + Box( + modifier = Modifier + .fillMaxWidth() + .padding(start = 5.dp) + ) { + Button( + onClick = onClick, + colors = ButtonDefaults.buttonColors( + contentColor = Color.White, + containerColor = Color.Black + ), + modifier = Modifier + .border( + width = 5.dp, + shape = RoundedCornerShape(roundedCornerDimen), + color = PastelYellow + ) + .width(70.dp) + .height(70.dp) + ) { + Icon( + imageVector = Icons.Default.ArrowBackIosNew, + contentDescription = "Back icon", + modifier = Modifier.size(40.dp) + ) + } + } +} + +object BackButtonFactory: BackButtonFactoryInterface { + @Composable + override fun get(type: BackButtonType): @Composable () -> Unit { + return when (type) { + BackButtonType.Menu -> { { BackButton({ isShowing = IsShowing.Menu }) } } + BackButtonType.MarksAll -> { { BackButton({ marksShow = MarksShow.All }) } } + BackButtonType.MarksSubject -> { { BackButton({ marksShow = MarksShow.Subject }) } } + } + } +} + +val backButtonFactory = BackButtonFactory \ No newline at end of file diff --git a/mobile/app/src/main/java/com/odweta/solon/Global.kt b/mobile/app/src/main/java/com/odweta/solon/Global.kt index a3c9caa..f4e1012 100644 --- a/mobile/app/src/main/java/com/odweta/solon/Global.kt +++ b/mobile/app/src/main/java/com/odweta/solon/Global.kt @@ -7,14 +7,16 @@ import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.runtime.MutableState -import androidx.compose.runtime.mutableIntStateOf +import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.toArgb import androidx.compose.ui.unit.dp import com.odweta.solon.ui.theme.PastelYellow import okhttp3.OkHttpClient +import org.json.JSONObject import java.io.File // Global values (dimens, modifiers, ...) @@ -72,7 +74,7 @@ var screenToShow: MutableState = mutableStateOf(Screen.Main) var signedInAndReadyToLaunch: MutableState = mutableStateOf(false) -var isShowing: MutableState = mutableStateOf(IsShowing.Timetable) +var isShowing by mutableStateOf(IsShowing.Timetable) var toolbarText: MutableState = mutableStateOf("") @@ -280,4 +282,46 @@ class Mark { return mark } -} \ No newline at end of file +} + +object FilePaths { + const val accountData: String = "account_data.txt" + const val timeTable: String = "timetable.json" + const val userData: String = "userdata.json" + const val marks: String = "marks.json" + const val settings: String = "settings.txt" + const val lectureNotes: String = "lecture_notes.csv" +} + +object APIEndpoints { + const val apiBaseUrl = "https://aplikace.skolaonline.cz/solapi/api" + const val tokenUrl = "$apiBaseUrl/connect/token" + lateinit var token: String + const val userDataUrl = "$apiBaseUrl/v1/user" + lateinit var userData: String + lateinit var studentId: String + const val timeTableUrl = "$apiBaseUrl/v1/timeTable" + var marksUrl = "$apiBaseUrl/v1/students/$studentId/marks/list?SemesterId=$syid" +} + +enum class MainElement { + Timetable, + Marks, + Menu +} + +object Global { + lateinit var token: String + lateinit var userData: JSONObject + lateinit var timetable: List + lateinit var marks: MutableMap> + var noSignInBackHandle: Boolean = false + val filePaths: FilePaths = FilePaths + val apiEndPoints: APIEndpoints = APIEndpoints + lateinit var settings: SettingsData + var lectureNotes: HashMap = hashMapOf() + var currentScreen by mutableStateOf(Screen.Main) + var currentMainElement by mutableStateOf(MainElement.Timetable) +} + +val global = Global \ No newline at end of file diff --git a/mobile/app/src/main/java/com/odweta/solon/Launch2.kt b/mobile/app/src/main/java/com/odweta/solon/Launch2.kt new file mode 100644 index 0000000..67f3e95 --- /dev/null +++ b/mobile/app/src/main/java/com/odweta/solon/Launch2.kt @@ -0,0 +1,111 @@ +package com.odweta.solon + +import android.content.Context +import androidx.compose.runtime.mutableStateOf +import com.odweta.solon.Util.Companion.getLectureId +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import org.json.JSONObject + +fun launchStart(ctx: Context) { + if (Account.haveSaved()) { + if (Util.internetAvail(ctx)) { + remoteLoad(ctx) + } else { + localLoad(ctx) + } + } else { + global.noSignInBackHandle = true + screenToShow.value = Screen.SignIn + } +} + +fun remoteLoad(ctx: Context) { + if (!isAPISetUp) + CoroutineScope(Dispatchers.IO) + .launch { Network.setupAPI() } + + lateinit var token: String + CoroutineScope(Dispatchers.IO) + .launch { token = Network.getToken() } + global.token = token + + lateinit var userData: JSONObject + CoroutineScope(Dispatchers.IO) + .launch { userData = Network.getUserData() } + global.userData = userData + + lateinit var remoteTimetable: JSONObject + CoroutineScope(Dispatchers.IO) + .launch { remoteTimetable = Network.getTimeTable() } + + lateinit var remoteMarks: JSONObject + CoroutineScope(Dispatchers.IO) + .launch { remoteMarks = Network.getMarks() } + + launchContinue( + ctx, + remoteTimetable, + remoteMarks + ) +} + +fun localLoad(ctx: Context) { + val localTimetable = JSONObject(Util.fileToString(timeTableFilePath)) + val localMarks = JSONObject(Util.fileToString(marksFilePath)) + + launchContinue( + ctx, + localTimetable, + localMarks + ) +} + +fun launchContinue( + ctx: Context, + timetable: JSONObject, + marks: JSONObject +) { + // parse timetable and marks + val parsedTimetable = Parsing.parseTimetable(timetable) + global.timetable = parsedTimetable + val parsedMarks = Parsing.parseMarks(marks) + global.marks = parsedMarks + + // load the settings + val settingsData = Util.fileToString(global.filePaths.settings).toSettingsData() + global.settings = settingsData + + // load the lecture notes + val lectureNotes = Util.fileToString(global.filePaths.lectureNotes) + Parsing.parseLectureNotes(lectureNotes) + + // listen for internet availability in case of disconnection + if (!internetAwaitListenerRunning) + setOnInternetAvailListener(ctx) + + // show the default (main) screen + global.currentScreen = Screen.Main + + // inside show the timetable + global.currentMainElement = MainElement.Timetable +} + +private fun setOnInternetAvailListener(ctx: Context) { + internetAwaitListenerRunning = true + CoroutineScope(Dispatchers.IO).launch { + while (true) { + if (Util.internetAvail(ctx)) { + CoroutineScope(Dispatchers.IO).launch { + remoteLoad(ctx) + } + } else { + showStatus("Bez připojení k internetu.") + } + + delay(1000) // Check for internet availability every second + } + } +} \ No newline at end of file diff --git a/mobile/app/src/main/java/com/odweta/solon/MainActivity.kt b/mobile/app/src/main/java/com/odweta/solon/MainActivity.kt index bcec57d..0a2620a 100644 --- a/mobile/app/src/main/java/com/odweta/solon/MainActivity.kt +++ b/mobile/app/src/main/java/com/odweta/solon/MainActivity.kt @@ -64,7 +64,7 @@ class MainActivity : ComponentActivity() { .fillMaxWidth() .weight(1f) ) { - when (isShowing.value) { + when (isShowing) { IsShowing.Timetable -> TimetableScreen() IsShowing.Marks -> MarksScreen() IsShowing.Menu -> MenuScreen() diff --git a/mobile/app/src/main/java/com/odweta/solon/Marks.kt b/mobile/app/src/main/java/com/odweta/solon/Marks.kt index d334499..000d4a8 100644 --- a/mobile/app/src/main/java/com/odweta/solon/Marks.kt +++ b/mobile/app/src/main/java/com/odweta/solon/Marks.kt @@ -14,21 +14,18 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.ArrowBackIosNew import androidx.compose.material.icons.filled.AutoAwesome -import androidx.compose.material3.Button -import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.Icon import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.MutableState +import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color @@ -55,13 +52,13 @@ enum class MarksShow { Detail } -var marksShow: MutableState = mutableStateOf(MarksShow.All) +var marksShow by mutableStateOf(MarksShow.All) private var subjectToShow: String = "" private var markToShow: Mark = Mark() @Composable fun MarksScreen() { - when (marksShow.value) { + when (marksShow) { MarksShow.All -> MarksAll() MarksShow.Subject -> MarksSubject() MarksShow.Detail -> MarksDetail() @@ -145,7 +142,7 @@ fun MarksAll() { shape = RoundedCornerShape(roundedCornerDimen) ) .clickable { - marksShow.value = MarksShow.Subject + marksShow = MarksShow.Subject subjectToShow = subject } } else { @@ -157,7 +154,7 @@ fun MarksAll() { shape = RoundedCornerShape(roundedCornerDimen) ) .clickable { - marksShow.value = MarksShow.Subject + marksShow = MarksShow.Subject subjectToShow = subject } } @@ -268,7 +265,7 @@ fun MarksAll() { fun MarksSubject() { // handle the back gesture (back swipe form side or back button on bottom android navbar) BackHandler { - marksShow.value = MarksShow.All + marksShow = MarksShow.All } val scrollState = rememberScrollState() @@ -283,29 +280,7 @@ fun MarksSubject() { Row( modifier = Modifier.fillMaxWidth() ) { - Button( - onClick = { - marksShow.value = MarksShow.All - }, - colors = ButtonDefaults.buttonColors( - contentColor = Color.White, - containerColor = Color.Black - ), - modifier = Modifier - .border( - width = 5.dp, - shape = RoundedCornerShape(roundedCornerDimen), - color = PastelYellow - ) - .width(70.dp) - .height(70.dp) - ) { - Icon( - imageVector = Icons.Default.ArrowBackIosNew, - contentDescription = "Back icon", - modifier = Modifier.size(40.dp) - ) - } + backButtonFactory.get(BackButtonType.MarksAll)() Box(modifier = Modifier.weight(1f)) @@ -397,7 +372,7 @@ fun MarksSubject() { .padding(vertical = 10.dp) .clickable { markToShow = mark - marksShow.value = MarksShow.Detail + marksShow = MarksShow.Detail } ) { Box( @@ -450,7 +425,7 @@ fun MarksSubject() { fun MarksDetail() { // handle the back gesture (back swipe form side or back button on bottom android navbar) BackHandler { - marksShow.value = MarksShow.Subject + marksShow = MarksShow.Subject } val scrollState = rememberScrollState() @@ -466,29 +441,7 @@ fun MarksDetail() { Row( modifier = Modifier.fillMaxWidth() ) { - Button( - onClick = { - marksShow.value = MarksShow.Subject - }, - colors = ButtonDefaults.buttonColors( - contentColor = Color.White, - containerColor = Color.Black - ), - modifier = Modifier - .border( - width = borderWidthDimen, - shape = RoundedCornerShape(roundedCornerDimen), - color = PastelYellow - ) - .width(70.dp) - .height(70.dp) - ) { - Icon( - imageVector = Icons.Default.ArrowBackIosNew, - contentDescription = "Back icon", - modifier = Modifier.size(40.dp) - ) - } + backButtonFactory.get(BackButtonType.MarksSubject)() Box(modifier = Modifier.weight(1f)) @@ -540,7 +493,8 @@ fun MarksDetail() { color = PastelYellow, shape = RoundedCornerShape(roundedCornerDimen) ) - .background(if (settings.useAmoledMode.checked.value) { + .background( + if (settings.useAmoledMode.checked.value) { Color.Black } else { PastelYellowTransparent diff --git a/mobile/app/src/main/java/com/odweta/solon/Menu.kt b/mobile/app/src/main/java/com/odweta/solon/Menu.kt index ff67d7d..5c1f417 100644 --- a/mobile/app/src/main/java/com/odweta/solon/Menu.kt +++ b/mobile/app/src/main/java/com/odweta/solon/Menu.kt @@ -44,11 +44,11 @@ fun MenuScreen(modifier: Modifier = Modifier) { Spacer(modifier = Modifier.height(80.dp)) - MenuButton({ isShowing.value = IsShowing.About }, "O aplikaci") + MenuButton({ isShowing = IsShowing.About }, "O aplikaci") Spacer(modifier = Modifier.height(80.dp)) - MenuButton({ isShowing.value = IsShowing.Settings }, "Nastavení") + MenuButton({ isShowing = IsShowing.Settings }, "Nastavení") } // Dialog implementation diff --git a/mobile/app/src/main/java/com/odweta/solon/Navbar.kt b/mobile/app/src/main/java/com/odweta/solon/Navbar.kt index a304641..83d3d02 100644 --- a/mobile/app/src/main/java/com/odweta/solon/Navbar.kt +++ b/mobile/app/src/main/java/com/odweta/solon/Navbar.kt @@ -67,7 +67,7 @@ fun NavbarScreen(modifier: Modifier = Modifier) { Button( onClick = { - isShowing.value = IsShowing.Timetable + isShowing = IsShowing.Timetable timetableColor.value = PastelYellow marksColor.value = Color.White menuColor.value = Color.White @@ -88,11 +88,11 @@ fun NavbarScreen(modifier: Modifier = Modifier) { Button( onClick = { - isShowing.value = IsShowing.Marks + isShowing = IsShowing.Marks timetableColor.value = Color.White marksColor.value = PastelYellow menuColor.value = Color.White - marksShow.value = MarksShow.All + marksShow = MarksShow.All }, colors = ButtonDefaults.buttonColors( contentColor = marksColor.value, @@ -110,7 +110,7 @@ fun NavbarScreen(modifier: Modifier = Modifier) { Button( onClick = { - isShowing.value = IsShowing.Menu + isShowing = IsShowing.Menu timetableColor.value = Color.White marksColor.value = Color.White menuColor.value = PastelYellow diff --git a/mobile/app/src/main/java/com/odweta/solon/Network.kt b/mobile/app/src/main/java/com/odweta/solon/Network.kt index 4ac03e7..26d1cde 100644 --- a/mobile/app/src/main/java/com/odweta/solon/Network.kt +++ b/mobile/app/src/main/java/com/odweta/solon/Network.kt @@ -29,8 +29,12 @@ class Network { try { val resp = client.newCall(request).execute() - val respString = resp.body?.string() - respString.toString() + val respString = resp.body?.string().toString() + if (JSONObject(respString).has("access_token")) { + JSONObject(respString).getString("access_token") + } else { + """"error": "network"""" + } //val respJson = respString?.let { JSONObject(it) } //respJson.toString() } catch (e: JSONException) { @@ -138,6 +142,27 @@ class Network { } } + suspend fun getUserData(): JSONObject { + return withContext(Dispatchers.IO) { + val request = Request.Builder() + .url(userDataUrl) + .header("Content-Type", "application/x-www-form-urlencoded") + .header("Authorization", "Bearer $token") // using Bearer auth token + .get() + .build() + + try { + val resp = client.newCall(request).execute() + val respString = resp.body?.string().toString() + JSONObject(respString) + } catch (e: JSONException) { + JSONObject("""{"error": "json"}""") + } catch (e: IOException) { + JSONObject("""{"error": "network"}""") + } + } + } + suspend fun getTimeTableJSON(): String { return withContext(Dispatchers.IO) { val userIsParent = Parsing.userIsParent() @@ -162,6 +187,32 @@ class Network { } } + suspend fun getTimeTable(): JSONObject { + return withContext(Dispatchers.IO) { + val userIsParent = Parsing.userIsParent() + var url = timeTableUrl + if (userIsParent) { + url += "?studentId=$studentId" + } + + val request = Request.Builder() + .url(url) + .header("Content-Type", "application/x-www-form-urlencoded") + .header("Authorization", "Bearer $token") + .get() + .build() + + try { + val resp = client.newCall(request).execute() + JSONObject(resp.body?.string().toString()) + } catch (e: JSONException) { + JSONObject("""{"error": "json"}""") + } catch (e: IOException) { + JSONObject("""{"error": "network"}""") + } + } + } + suspend fun getMarksJSON(): String { return withContext(Dispatchers.IO) { val request = Request.Builder() @@ -179,5 +230,25 @@ class Network { } } } + + suspend fun getMarks(): JSONObject { + return withContext(Dispatchers.IO) { + val request = Request.Builder() + .url(marksUrl) + .header("Content-Type", "application/x-www-form-urlencoded") + .header("Authorization", "Bearer $token") + .get() + .build() + + try { + val resp = client.newCall(request).execute() + JSONObject(resp.body?.string().toString()) + } catch (e: JSONException) { + JSONObject("""{"error": "json"}""") + } catch (e: IOException) { + JSONObject("""{"error": "network"}""") + } + } + } } } \ No newline at end of file diff --git a/mobile/app/src/main/java/com/odweta/solon/Parsing.kt b/mobile/app/src/main/java/com/odweta/solon/Parsing.kt index c882182..3037971 100644 --- a/mobile/app/src/main/java/com/odweta/solon/Parsing.kt +++ b/mobile/app/src/main/java/com/odweta/solon/Parsing.kt @@ -1,5 +1,7 @@ package com.odweta.solon +import androidx.compose.runtime.mutableStateOf +import com.odweta.solon.Util.Companion.getLectureId import org.json.JSONObject import java.time.LocalDateTime import java.time.format.DateTimeFormatter @@ -49,8 +51,8 @@ class Parsing { else false } - fun parseTimeTableJSON(jsonString: String): List { - val jsonObject = JSONObject(jsonString) + fun parseTimetable(jsonString: JSONObject): List { + val jsonObject = jsonString /* * return a List that looks like this: @@ -320,9 +322,9 @@ class Parsing { return week } - fun parseMarksJSON(jsonString: String): MutableMap> { + fun parseMarks(jsonString: JSONObject): MutableMap> { // no marks - val json = JSONObject(jsonString) + val json = jsonString if (json.has("marks") && json.getJSONArray("marks").length() == 0) { val noMarks = mutableMapOf>() val list = mutableListOf() @@ -379,5 +381,38 @@ class Parsing { return marks } + + fun parseLectureNotes(lectureNotes: String) { + for (day in global.timetable) { + for ((subjectIndex, subject) in day.subjects.withIndex()) { + val id = getLectureId(day.date, subjectIndex) + global.lectureNotes[id] = LectureNote( + id = id, + type = mutableStateOf(LectureNoteType.Normal), + note = mutableStateOf(""), + number = subject.number.toInt(), + lectureName = subject.name + ) + } + } + val lines = lectureNotes.lines() + for (line in lines) { + if (line.isBlank()) continue + + val parts = line.split(",") + + if (parts.size >= 3) { + val id = parts[0].trim().toInt() + val type = parts[1].trim().toLectureNoteType() + var note = parts[2].trim() + for (part in 3.until(parts.size)) { + note += ",${parts[part]}" + } + + global.lectureNotes[id]?.note = mutableStateOf(note) + global.lectureNotes[id]?.type = mutableStateOf(type) + } + } + } } } \ No newline at end of file diff --git a/mobile/app/src/main/java/com/odweta/solon/Settings.kt b/mobile/app/src/main/java/com/odweta/solon/Settings.kt index a5f8173..db2673e 100644 --- a/mobile/app/src/main/java/com/odweta/solon/Settings.kt +++ b/mobile/app/src/main/java/com/odweta/solon/Settings.kt @@ -37,7 +37,7 @@ import com.odweta.solon.ui.theme.PastelYellow fun SettingsScreen(modifier: Modifier = Modifier) { // handle the back gesture (back swipe form side or back button on bottom android navbar) BackHandler { - isShowing.value = IsShowing.Menu + isShowing = IsShowing.Menu } val scrollState = rememberScrollState() @@ -54,7 +54,7 @@ fun SettingsScreen(modifier: Modifier = Modifier) { ) { Button( onClick = { - isShowing.value = IsShowing.Menu + isShowing = IsShowing.Menu }, colors = ButtonDefaults.buttonColors( contentColor = Color.White, @@ -146,4 +146,26 @@ fun SettingsTableRow(setting: Setting) { ) ) } +} + +fun String.toSettingsData(): SettingsData { + val settings = this.split("\n") + val auxSettingsData = SettingsData() + val useSvobodaMode = settings[0].split("#") + val useAmoledMode = settings[1].split("#") + val showRefreshButton = settings[2].split("#") + + auxSettingsData.useSvobodaMode.id = SettingsId.Svoboda + auxSettingsData.useSvobodaMode.name = useSvobodaMode[1] + auxSettingsData.useSvobodaMode.checked.value = useSvobodaMode[2].toBoolean() + + auxSettingsData.useAmoledMode.id = SettingsId.Amoled + auxSettingsData.useAmoledMode.name = useAmoledMode[1] + auxSettingsData.useAmoledMode.checked.value = useAmoledMode[2].toBoolean() + + auxSettingsData.showRefreshButton.id = SettingsId.RefreshButton + auxSettingsData.showRefreshButton.name = showRefreshButton[1] + auxSettingsData.showRefreshButton.checked.value = showRefreshButton[2].toBoolean() + + return auxSettingsData } \ No newline at end of file diff --git a/mobile/app/src/main/java/com/odweta/solon/SignIn.kt b/mobile/app/src/main/java/com/odweta/solon/SignIn.kt index 5b676d5..36c1349 100644 --- a/mobile/app/src/main/java/com/odweta/solon/SignIn.kt +++ b/mobile/app/src/main/java/com/odweta/solon/SignIn.kt @@ -109,8 +109,10 @@ fun signInButtonCallback(ctx: Context, coscope: CoroutineScope, buttonText: Stri @Composable fun SignInScreen() { // handle the back gesture (back swipe form side or back button on bottom android navbar) - BackHandler { - screenToShow.value = Screen.Main + if (!global.noSignInBackHandle) { + BackHandler { + screenToShow.value = Screen.Main + } } var usernameText by remember { mutableStateOf("") } diff --git a/mobile/app/src/main/java/com/odweta/solon/Toolbar.kt b/mobile/app/src/main/java/com/odweta/solon/Toolbar.kt index 4a1186d..870432a 100644 --- a/mobile/app/src/main/java/com/odweta/solon/Toolbar.kt +++ b/mobile/app/src/main/java/com/odweta/solon/Toolbar.kt @@ -43,4 +43,8 @@ fun ToolbarScreen() { color = Color.White ) } +} + +fun showStatus(text: String) { + toolbarText.value = text } \ No newline at end of file diff --git a/mobile/app/src/main/java/com/odweta/solon/Util.kt b/mobile/app/src/main/java/com/odweta/solon/Util.kt index 0ec0743..cf02188 100644 --- a/mobile/app/src/main/java/com/odweta/solon/Util.kt +++ b/mobile/app/src/main/java/com/odweta/solon/Util.kt @@ -265,7 +265,7 @@ class Util { }) } - private fun csvToLectureNotes() { + fun csvToLectureNotes() { val lines = fileToString(lectureNotesFilePath).lines() for (line in lines) { if (line.isBlank()) continue @@ -286,7 +286,7 @@ class Util { } } - private fun lectureNotesToCsvString(hashMap: HashMap): String { + fun lectureNotesToCsvString(hashMap: HashMap): String { var result = "" for ((key, lectureNote) in hashMap) { result +=