Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
12d891a0e4 | ||
|
|
3bac016a8b | ||
|
|
81e875bea8 | ||
|
|
aed00c0694 | ||
|
|
6cbe12fb10 | ||
|
|
992c0b4a34 | ||
|
|
d8bda87b38 | ||
|
|
cca561f11b | ||
|
|
7907429aea | ||
|
|
4cb07126e2 |
@@ -1,6 +1,6 @@
|
|||||||

|

|
||||||
# Zorientujte se rychleji v této odlehčené verzi Školy OnLine
|
# Zorientujte se rychleji v této odlehčené verzi Školy OnLine
|
||||||
# Odkaz na stažení aplikace pro Android [zde](https://gitlab.com/Odweta/solon/-/releases/2.4/downloads/app-release.apk) (verze 2.4)
|
# Odkaz na stažení aplikace pro Android [zde](https://gitlab.com/Odweta/solon/-/releases/2.5/downloads/app-release.apk) (verze 2.5)
|
||||||
[<img src="https://fdroid.gitlab.io/artwork/badge/get-it-on.png"
|
[<img src="https://fdroid.gitlab.io/artwork/badge/get-it-on.png"
|
||||||
alt="Nyní na F-Droidu"
|
alt="Nyní na F-Droidu"
|
||||||
height="80">](https://f-droid.org/packages/com.odweta.solon/)
|
height="80">](https://f-droid.org/packages/com.odweta.solon/)
|
||||||
@@ -28,7 +28,7 @@ echo
|
|||||||
echo
|
echo
|
||||||
echo "[signing]"
|
echo "[signing]"
|
||||||
echo
|
echo
|
||||||
~/Android/Sdk/build-tools/35.0.0/apksigner sign --alignment-preserved --ks ~/Documents/android-keystore.jks --ks-pass pass:$ks_pass app/build/outputs/apk/release/com.odweta.solon_$ver.apk
|
~/Android/Sdk/build-tools/35.0.1/apksigner sign --alignment-preserved --ks ~/Documents/android-keystore.jks --ks-pass pass:$ks_pass app/build/outputs/apk/release/com.odweta.solon_$ver.apk
|
||||||
|
|
||||||
# create the tag
|
# create the tag
|
||||||
echo
|
echo
|
||||||
|
|||||||
Executable
+24
@@ -0,0 +1,24 @@
|
|||||||
|
#!/data/data/com.termux/files/usr/bin/bash
|
||||||
|
|
||||||
|
cd mobile
|
||||||
|
|
||||||
|
INTERNAL_STORAGE=/data/data/com.termux/files/home/storage/downloads/..
|
||||||
|
|
||||||
|
echo -n 'keystore key for signing: '
|
||||||
|
read kskey
|
||||||
|
|
||||||
|
echo 'building the release bundle'
|
||||||
|
|
||||||
|
gradle bundleRelease
|
||||||
|
|
||||||
|
mkdir -p $INTERNAL_STORAGE/solon-bin/
|
||||||
|
|
||||||
|
cp $SOLON/mobile/app/build/outputs/bundle/release/app-release.aab $INTERNAL_STORAGE/solon-bin/
|
||||||
|
|
||||||
|
echo 'app-bundle.aab copied to \$INTERNAL_STORAGE/solon-bin'
|
||||||
|
|
||||||
|
apksigner sign --ks $INTERNAL_STORAGE/Documents/android-keystore.jks --ks-pass pass:$kskey --min-sdk-version=28 $INTERNAL_STORAGE/solon-bin/app-release.aab
|
||||||
|
|
||||||
|
echo 'aab signed with default android keystore'
|
||||||
|
|
||||||
|
cd ..
|
||||||
Generated
+1
@@ -1,3 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="jbr-21" project-jdk-type="JavaSDK">
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="jbr-21" project-jdk-type="JavaSDK">
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ tasks.register("printVersionName") {
|
|||||||
|
|
||||||
tasks.register("deploy") {
|
tasks.register("deploy") {
|
||||||
dependsOn("assembleDebug")
|
dependsOn("assembleDebug")
|
||||||
dependsOn("installDebug")
|
//dependsOn("installDebug")
|
||||||
doLast {
|
doLast {
|
||||||
exec {
|
exec {
|
||||||
commandLine("adb", "shell", "am", "start", "-n", "com.odweta.solon/.MainActivity")
|
commandLine("adb", "shell", "am", "start", "-n", "com.odweta.solon/.MainActivity")
|
||||||
@@ -32,8 +32,8 @@ android {
|
|||||||
applicationId = "com.odweta.solon"
|
applicationId = "com.odweta.solon"
|
||||||
minSdk = 28
|
minSdk = 28
|
||||||
targetSdk = 34
|
targetSdk = 34
|
||||||
versionCode = 211
|
versionCode = 213
|
||||||
versionName = "2.4"
|
versionName = "2.5"
|
||||||
|
|
||||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -199,8 +199,10 @@ enum class ScreenElement {
|
|||||||
class Global {
|
class Global {
|
||||||
lateinit var timetableJSON: JSONObject
|
lateinit var timetableJSON: JSONObject
|
||||||
lateinit var marksJSON: JSONObject
|
lateinit var marksJSON: JSONObject
|
||||||
|
lateinit var finalMarksJSON: JSONObject
|
||||||
lateinit var marks: MutableMap<String, MutableList<Mark>>
|
lateinit var marks: MutableMap<String, MutableList<Mark>>
|
||||||
lateinit var newMarks: MutableMap<String, MutableList<Mark>>
|
lateinit var newMarks: MutableMap<String, MutableList<Mark>>
|
||||||
|
lateinit var finalMarks: Map<String, Int>
|
||||||
lateinit var settings: SettingsData
|
lateinit var settings: SettingsData
|
||||||
lateinit var fileDir: File
|
lateinit var fileDir: File
|
||||||
|
|
||||||
@@ -237,6 +239,8 @@ class Global {
|
|||||||
var subjectToShow by mutableStateOf("")
|
var subjectToShow by mutableStateOf("")
|
||||||
var markToShow by mutableStateOf(Mark())
|
var markToShow by mutableStateOf(Mark())
|
||||||
|
|
||||||
|
var demoMode: Boolean = false
|
||||||
|
|
||||||
inner class FilePaths {
|
inner class FilePaths {
|
||||||
val accountData: String = "account_data.txt"
|
val accountData: String = "account_data.txt"
|
||||||
val timetable: String = "timetable.json"
|
val timetable: String = "timetable.json"
|
||||||
@@ -244,6 +248,7 @@ class Global {
|
|||||||
val marks: String = "marks.json"
|
val marks: String = "marks.json"
|
||||||
val settings: String = "settings.txt"
|
val settings: String = "settings.txt"
|
||||||
val lectureNotes: String = "lecture_notes.csv"
|
val lectureNotes: String = "lecture_notes.csv"
|
||||||
|
val finalMarks: String = "final_marks.txt"
|
||||||
}
|
}
|
||||||
val filePaths = FilePaths()
|
val filePaths = FilePaths()
|
||||||
|
|
||||||
@@ -253,6 +258,7 @@ class Global {
|
|||||||
val userData = "$apiBase/v1/user"
|
val userData = "$apiBase/v1/user"
|
||||||
val timetable = "$apiBase/v1/timeTable"
|
val timetable = "$apiBase/v1/timeTable"
|
||||||
var marks: String = "$apiBase/v1/students/<student id>/marks/list"
|
var marks: String = "$apiBase/v1/students/<student id>/marks/list"
|
||||||
|
var finalMarks: String ="$apiBase/v1/students/<student id>/marks/final"
|
||||||
}
|
}
|
||||||
val apiEndPoints = APIEndPoints()
|
val apiEndPoints = APIEndPoints()
|
||||||
|
|
||||||
|
|||||||
@@ -34,15 +34,18 @@ fun remoteLoad(ctx: Context) {
|
|||||||
// fetch remote data
|
// fetch remote data
|
||||||
global.timetableJSON = networkRequestFactory.perform(NetworkRequestType.Timetable)
|
global.timetableJSON = networkRequestFactory.perform(NetworkRequestType.Timetable)
|
||||||
global.marksJSON = networkRequestFactory.perform(NetworkRequestType.Marks)
|
global.marksJSON = networkRequestFactory.perform(NetworkRequestType.Marks)
|
||||||
|
global.finalMarksJSON = networkRequestFactory.perform(NetworkRequestType.FinalMarks)
|
||||||
|
|
||||||
// save to local for later local load
|
// save to local for later local load
|
||||||
Util.saveStringToFile(global.filePaths.timetable, global.timetableJSON.toString())
|
Util.saveStringToFile(global.filePaths.timetable, global.timetableJSON.toString())
|
||||||
Util.saveStringToFile(global.filePaths.marks, global.marksJSON.toString())
|
Util.saveStringToFile(global.filePaths.marks, global.marksJSON.toString())
|
||||||
|
Util.saveStringToFile(global.filePaths.finalMarks, global.finalMarksJSON.toString())
|
||||||
|
|
||||||
launchContinue(
|
launchContinue(
|
||||||
ctx,
|
ctx,
|
||||||
global.timetableJSON,
|
global.timetableJSON,
|
||||||
global.marksJSON
|
global.marksJSON,
|
||||||
|
global.finalMarksJSON
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -50,7 +53,8 @@ fun remoteLoad(ctx: Context) {
|
|||||||
launchContinue(
|
launchContinue(
|
||||||
ctx,
|
ctx,
|
||||||
networkRequestFactory.perform(NetworkRequestType.Timetable),
|
networkRequestFactory.perform(NetworkRequestType.Timetable),
|
||||||
networkRequestFactory.perform(NetworkRequestType.Marks)
|
networkRequestFactory.perform(NetworkRequestType.Marks),
|
||||||
|
networkRequestFactory.perform(NetworkRequestType.FinalMarks)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -61,39 +65,43 @@ fun localLoad(ctx: Context) {
|
|||||||
global.studentId = Parsing.getStudentId()
|
global.studentId = Parsing.getStudentId()
|
||||||
global.studentClass = Parsing.getStudentClass()
|
global.studentClass = Parsing.getStudentClass()
|
||||||
global.apiEndPoints.marks = "${global.apiEndPoints.apiBase}/v1/students/${global.studentId}/marks/list"
|
global.apiEndPoints.marks = "${global.apiEndPoints.apiBase}/v1/students/${global.studentId}/marks/list"
|
||||||
|
global.apiEndPoints.finalMarks = "${global.apiEndPoints.apiBase}/v1/students/${global.studentId}/marks/final"
|
||||||
val localTimetable = JSONObject(Util.fileToString(global.filePaths.timetable))
|
val localTimetable = JSONObject(Util.fileToString(global.filePaths.timetable))
|
||||||
val localMarks = JSONObject(Util.fileToString(global.filePaths.marks))
|
val localMarks = JSONObject(Util.fileToString(global.filePaths.marks))
|
||||||
|
val localFinalMarks = JSONObject(Util.fileToString(global.filePaths.finalMarks))
|
||||||
|
|
||||||
launchContinue(
|
launchContinue(
|
||||||
ctx,
|
ctx,
|
||||||
localTimetable,
|
localTimetable,
|
||||||
localMarks
|
localMarks,
|
||||||
|
localFinalMarks
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun launchContinue(
|
fun launchContinue(
|
||||||
ctx: Context,
|
ctx: Context,
|
||||||
timetable: JSONObject,
|
timetable: JSONObject,
|
||||||
marks: JSONObject
|
marks: JSONObject,
|
||||||
|
finalMarks: JSONObject
|
||||||
) {
|
) {
|
||||||
// parse timetable and marks
|
// parse timetable and marks
|
||||||
val parsedTimetable = Parsing.parseTimetable(timetable)
|
global.timetable = Parsing.parseTimetable(timetable)
|
||||||
global.timetable = parsedTimetable
|
global.marks = Parsing.parseMarks(marks)
|
||||||
val parsedMarks = Parsing.parseMarks(marks)
|
|
||||||
global.marks = parsedMarks
|
|
||||||
global.newMarks = Parsing.parseNewMarks(marks)
|
global.newMarks = Parsing.parseNewMarks(marks)
|
||||||
|
global.finalMarks = Parsing.parseFinalMarks(finalMarks)
|
||||||
// // load the settings
|
|
||||||
// global.settings = Util.fileToString(global.filePaths.settings).toSettingsData()
|
|
||||||
|
|
||||||
// load the lecture notes
|
// load the lecture notes
|
||||||
Util.loadLectureNotes()
|
//Util.loadLectureNotes()
|
||||||
Util.csvToLectureNotes()
|
//Util.csvToLectureNotes()
|
||||||
|
|
||||||
|
// load the settings
|
||||||
|
settings = Util.fileToString(global.filePaths.settings).toSettingsData()
|
||||||
|
|
||||||
// listen for internet availability in case of disconnection
|
// listen for internet availability in case of disconnection
|
||||||
if (!global.internetAwaitListenerRunning)
|
if (!global.internetAwaitListenerRunning)
|
||||||
setOnInternetAvailListener(ctx)
|
setOnInternetAvailListener(ctx)
|
||||||
|
|
||||||
|
// FIXME maybe? causes IndexOutOfBoundsException????? prob not tho
|
||||||
if (!global.launched) {
|
if (!global.launched) {
|
||||||
// show the default (main) screen
|
// show the default (main) screen
|
||||||
global.currentScreen = Screen.Main
|
global.currentScreen = Screen.Main
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.odweta.solon
|
package com.odweta.solon
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
import androidx.activity.compose.BackHandler
|
import androidx.activity.compose.BackHandler
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.border
|
import androidx.compose.foundation.border
|
||||||
@@ -25,6 +26,7 @@ import androidx.compose.material3.FloatingActionButton
|
|||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
@@ -121,7 +123,7 @@ fun NewMarksScreen() {
|
|||||||
modifier = Modifier.verticalScroll(ss)
|
modifier = Modifier.verticalScroll(ss)
|
||||||
) {
|
) {
|
||||||
for ((k, v) in global.newMarks) {
|
for ((k, v) in global.newMarks) {
|
||||||
if (v.size > 0) {
|
if (v.isNotEmpty()) {
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(horizontal = 10.dp)
|
.padding(horizontal = 10.dp)
|
||||||
@@ -242,14 +244,16 @@ fun FinalMarksScreen() {
|
|||||||
Column(
|
Column(
|
||||||
modifier = Modifier.verticalScroll(ss)
|
modifier = Modifier.verticalScroll(ss)
|
||||||
) {
|
) {
|
||||||
Text("test", color = Color.White)
|
Text(Util.fileToString(global.filePaths.finalMarks), color = Color.White)
|
||||||
Text("test", color = Color.White)
|
for ((subject, mark) in global.finalMarks) {
|
||||||
Text("test", color = Color.White)
|
// LaunchedEffect(Unit) {
|
||||||
Text("test", color = Color.White)
|
// Log.d("debug", networkRequestFactory.perform(NetworkRequestType.Apologies).body.string?.toString())
|
||||||
Text("test", color = Color.White)
|
//}
|
||||||
Text("test", color = Color.White)
|
Row {
|
||||||
Text("test", color = Color.White)
|
Text(subject, color = Color.White)
|
||||||
Text("test", color = Color.White)
|
Text(mark.toString(), color = Color.White, modifier = Modifier.padding(10.dp))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -337,8 +341,10 @@ fun MarksAll() {
|
|||||||
shape = RoundedCornerShape(global.dimens.roundedCorner)
|
shape = RoundedCornerShape(global.dimens.roundedCorner)
|
||||||
)
|
)
|
||||||
.clickable {
|
.clickable {
|
||||||
|
if (markList[0].grade != "0") {
|
||||||
global.marksDepthLevel = MarksDepthLevel.Subject
|
global.marksDepthLevel = MarksDepthLevel.Subject
|
||||||
global.subjectToShow = subject
|
global.subjectToShow = subject
|
||||||
|
} // else { isInDemo == true }
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Modifier
|
Modifier
|
||||||
@@ -349,8 +355,10 @@ fun MarksAll() {
|
|||||||
shape = RoundedCornerShape(global.dimens.roundedCorner)
|
shape = RoundedCornerShape(global.dimens.roundedCorner)
|
||||||
)
|
)
|
||||||
.clickable {
|
.clickable {
|
||||||
|
if (markList[0].grade != "0") {
|
||||||
global.marksDepthLevel = MarksDepthLevel.Subject
|
global.marksDepthLevel = MarksDepthLevel.Subject
|
||||||
global.subjectToShow = subject
|
global.subjectToShow = subject
|
||||||
|
} // else { isInDemo == true }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -463,7 +471,7 @@ fun MarksAll() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
FloatingActionButton(
|
/*FloatingActionButton(
|
||||||
onClick = { global.currentScreenElement = ScreenElement.FinalMarks },
|
onClick = { global.currentScreenElement = ScreenElement.FinalMarks },
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(10.dp)
|
.padding(10.dp)
|
||||||
@@ -479,7 +487,7 @@ fun MarksAll() {
|
|||||||
contentDescription = "Final marks",
|
contentDescription = "Final marks",
|
||||||
tint = PastelYellow // You can customize the icon color
|
tint = PastelYellow // You can customize the icon color
|
||||||
)
|
)
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ fun setupAPI() {
|
|||||||
global.studentId = Parsing.getStudentId()
|
global.studentId = Parsing.getStudentId()
|
||||||
|
|
||||||
global.apiEndPoints.marks = "${global.apiEndPoints.apiBase}/v1/students/${global.studentId}/marks/list"
|
global.apiEndPoints.marks = "${global.apiEndPoints.apiBase}/v1/students/${global.studentId}/marks/list"
|
||||||
|
global.apiEndPoints.finalMarks = "${global.apiEndPoints.apiBase}/v1/students/${global.studentId}/marks/final"
|
||||||
|
|
||||||
global.isAPISetUp = true
|
global.isAPISetUp = true
|
||||||
}
|
}
|
||||||
@@ -40,6 +41,7 @@ enum class NetworkRequestType {
|
|||||||
Token,
|
Token,
|
||||||
Timetable,
|
Timetable,
|
||||||
Marks,
|
Marks,
|
||||||
|
FinalMarks,
|
||||||
UserData
|
UserData
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,6 +73,7 @@ object NetworkRequestFactory: NetworkRequestInterface {
|
|||||||
}
|
}
|
||||||
NetworkRequestType.Timetable -> return getAPI(global.apiEndPoints.timetable)
|
NetworkRequestType.Timetable -> return getAPI(global.apiEndPoints.timetable)
|
||||||
NetworkRequestType.Marks -> return getAPI(global.apiEndPoints.marks)
|
NetworkRequestType.Marks -> return getAPI(global.apiEndPoints.marks)
|
||||||
|
NetworkRequestType.FinalMarks -> return getAPI(global.apiEndPoints.finalMarks)
|
||||||
NetworkRequestType.UserData -> return getAPI(global.apiEndPoints.userData)
|
NetworkRequestType.UserData -> return getAPI(global.apiEndPoints.userData)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -82,7 +85,13 @@ object NetworkRequestFactory: NetworkRequestInterface {
|
|||||||
.get()
|
.get()
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
return client.newCall(request).execute()
|
return try {
|
||||||
|
client.newCall(request).execute()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Response.Builder()
|
||||||
|
.code(500)
|
||||||
|
.build()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun post(url: String, headers: Headers, body: FormBody): Response {
|
private fun post(url: String, headers: Headers, body: FormBody): Response {
|
||||||
@@ -92,7 +101,13 @@ object NetworkRequestFactory: NetworkRequestInterface {
|
|||||||
.post(body)
|
.post(body)
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
return client.newCall(request).execute()
|
return try {
|
||||||
|
client.newCall(request).execute()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Response.Builder()
|
||||||
|
.code(500)
|
||||||
|
.build()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getAPI(url: String): JSONObject {
|
private fun getAPI(url: String): JSONObject {
|
||||||
|
|||||||
@@ -386,16 +386,6 @@ class Parsing {
|
|||||||
|
|
||||||
for (i in 0..<marksJSONArray.length()) {
|
for (i in 0..<marksJSONArray.length()) {
|
||||||
marksList.add(marksJSONArray.getJSONObject(i))
|
marksList.add(marksJSONArray.getJSONObject(i))
|
||||||
marksList.add(marksJSONArray.getJSONObject(i))
|
|
||||||
marksList.add(marksJSONArray.getJSONObject(i))
|
|
||||||
marksList.add(marksJSONArray.getJSONObject(i))
|
|
||||||
marksList.add(marksJSONArray.getJSONObject(i))
|
|
||||||
marksList.add(marksJSONArray.getJSONObject(i))
|
|
||||||
marksList.add(marksJSONArray.getJSONObject(i))
|
|
||||||
marksList.add(marksJSONArray.getJSONObject(i))
|
|
||||||
marksList.add(marksJSONArray.getJSONObject(i))
|
|
||||||
marksList.add(marksJSONArray.getJSONObject(i))
|
|
||||||
marksList.add(marksJSONArray.getJSONObject(i))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (subj in subjectMap.values) {
|
for (subj in subjectMap.values) {
|
||||||
@@ -416,6 +406,14 @@ class Parsing {
|
|||||||
return marks
|
return marks
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun parseFinalMarks(json: JSONObject): Map<String, Int> {
|
||||||
|
return mapOf(
|
||||||
|
"AJ" to 1,
|
||||||
|
"B" to 5,
|
||||||
|
"Pr" to 1
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fun getStudentClass(): String {
|
fun getStudentClass(): String {
|
||||||
return if (!userIsParent()) {
|
return if (!userIsParent()) {
|
||||||
global.userData
|
global.userData
|
||||||
|
|||||||
@@ -45,7 +45,9 @@ fun SettingsScreen() {
|
|||||||
|
|
||||||
// load the settings dat every time the settings screen is opened,
|
// load the settings dat every time the settings screen is opened,
|
||||||
// maybe i can add a flag that determines if the settings are up to date?
|
// maybe i can add a flag that determines if the settings are up to date?
|
||||||
|
if (!global.demoMode) {
|
||||||
settings = Util.fileToString(global.filePaths.settings).toSettingsData()
|
settings = Util.fileToString(global.filePaths.settings).toSettingsData()
|
||||||
|
}
|
||||||
|
|
||||||
val scrollState = rememberScrollState()
|
val scrollState = rememberScrollState()
|
||||||
|
|
||||||
@@ -60,7 +62,9 @@ fun SettingsScreen() {
|
|||||||
|
|
||||||
SettingsTableRow(settings.useAmoledMode)
|
SettingsTableRow(settings.useAmoledMode)
|
||||||
|
|
||||||
|
if (!global.demoMode) {
|
||||||
SettingsTableRow(settings.showRefreshButton)
|
SettingsTableRow(settings.showRefreshButton)
|
||||||
|
}
|
||||||
|
|
||||||
SettingsTableRow(settings.useAnimations)
|
SettingsTableRow(settings.useAnimations)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,6 +89,10 @@ fun signInButtonCallback(ctx: Context, usernameText: String, passwordText: Strin
|
|||||||
}
|
}
|
||||||
|
|
||||||
CoroutineScope(Dispatchers.IO).launch {
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
if (global.username == "demo" && global.password == "Demo1234") {
|
||||||
|
// start the demo
|
||||||
|
launchDemo(ctx)
|
||||||
|
} else {
|
||||||
val valid = Account.isValid(acc)
|
val valid = Account.isValid(acc)
|
||||||
|
|
||||||
checked = true
|
checked = true
|
||||||
@@ -108,6 +112,31 @@ fun signInButtonCallback(ctx: Context, usernameText: String, passwordText: Strin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun launchDemo(ctx: Context) {
|
||||||
|
global.demoMode = true
|
||||||
|
|
||||||
|
settings = Util.fileToString(global.filePaths.settings).toSettingsData()
|
||||||
|
settings.showRefreshButton.checked.value = false
|
||||||
|
|
||||||
|
val d = Day()
|
||||||
|
d.name = "demoday"
|
||||||
|
d.date = "1. 1."
|
||||||
|
d.subjects = listOf(Subject.empty())
|
||||||
|
global.timetable = listOf(d)
|
||||||
|
|
||||||
|
global.marks = mutableMapOf("demomarks" to mutableListOf(Mark().none()))
|
||||||
|
|
||||||
|
global.newMarks = global.marks
|
||||||
|
|
||||||
|
global.status = "demo"
|
||||||
|
|
||||||
|
global.launched = true
|
||||||
|
global.refreshed = true
|
||||||
|
global.currentScreen = Screen.Main
|
||||||
|
global.currentScreenElement = ScreenElement.Timetable
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun SignInScreen() {
|
fun SignInScreen() {
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import androidx.compose.foundation.layout.height
|
|||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.width
|
import androidx.compose.foundation.layout.width
|
||||||
import androidx.compose.foundation.pager.HorizontalPager
|
import androidx.compose.foundation.pager.HorizontalPager
|
||||||
|
import androidx.compose.foundation.pager.PagerState
|
||||||
import androidx.compose.foundation.pager.rememberPagerState
|
import androidx.compose.foundation.pager.rememberPagerState
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
@@ -65,8 +66,11 @@ import com.odweta.solon.ui.theme.PastelRed
|
|||||||
import com.odweta.solon.ui.theme.PastelRedTransparent
|
import com.odweta.solon.ui.theme.PastelRedTransparent
|
||||||
import com.odweta.solon.ui.theme.PastelYellow
|
import com.odweta.solon.ui.theme.PastelYellow
|
||||||
import com.odweta.solon.ui.theme.PastelYellowTransparent
|
import com.odweta.solon.ui.theme.PastelYellowTransparent
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
import java.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
import java.time.LocalTime
|
import java.time.LocalTime
|
||||||
@@ -74,16 +78,65 @@ import java.time.format.DateTimeFormatter
|
|||||||
|
|
||||||
var showDetailDialog by mutableStateOf(false)
|
var showDetailDialog by mutableStateOf(false)
|
||||||
|
|
||||||
|
@OptIn(ExperimentalFoundationApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun TimetableScreen() {
|
fun TimetableScreen() {
|
||||||
|
val pagerState = rememberPagerState(pageCount = { if (global.timetable.isNotEmpty()) global.timetable.size else 6 }) // FIXME
|
||||||
|
Column {
|
||||||
|
//QuickDays(pagerState)
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
contentAlignment = Alignment.BottomCenter
|
contentAlignment = Alignment.BottomCenter
|
||||||
) {
|
) {
|
||||||
DayPager()
|
DayPager(pagerState)
|
||||||
if (showDetailDialog) DetailDialog()
|
if (showDetailDialog) DetailDialog()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalFoundationApi::class)
|
||||||
|
@Composable
|
||||||
|
fun QuickDays(pagerState: PagerState) {
|
||||||
|
@Composable
|
||||||
|
fun QuickDay(day: Day, modifier: Modifier, idx: Int) {
|
||||||
|
val scope = rememberCoroutineScope()
|
||||||
|
Column(
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
|
verticalArrangement = Arrangement.Center,
|
||||||
|
modifier = modifier.padding(5.dp).background(
|
||||||
|
shape = RoundedCornerShape(global.dimens.roundedCorner),
|
||||||
|
color = PastelYellowTransparent
|
||||||
|
).clickable(onClick = {
|
||||||
|
scope.launch {
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
pagerState.animateScrollToPage(idx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "${day.name[0]}${day.name[1]}",
|
||||||
|
color = Color.White,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
fontWeight = FontWeight.Bold
|
||||||
|
)
|
||||||
|
Spacer(Modifier.height(5.dp))
|
||||||
|
Text(
|
||||||
|
text = day.date,
|
||||||
|
color = Color.White,
|
||||||
|
textAlign = TextAlign.Center
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Row(
|
||||||
|
Modifier.fillMaxWidth().padding(bottom = 15.dp).padding(horizontal = 5.dp)
|
||||||
|
) {
|
||||||
|
for ((idx, day) in global.timetable.withIndex()) {
|
||||||
|
QuickDay(day, Modifier.weight(1f), idx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressLint("UnrememberedMutableState")
|
@SuppressLint("UnrememberedMutableState")
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@@ -227,13 +280,28 @@ fun DetailDialog() {
|
|||||||
|
|
||||||
@OptIn(ExperimentalFoundationApi::class)
|
@OptIn(ExperimentalFoundationApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun DayPager() {
|
fun DayPager(pagerState: PagerState) {
|
||||||
val pagerState = rememberPagerState(pageCount = { if (global.timetable.isNotEmpty()) global.timetable.size else 6 }) // FIXME
|
|
||||||
HorizontalPager(
|
HorizontalPager(
|
||||||
state = pagerState,
|
state = pagerState,
|
||||||
modifier = Modifier.fillMaxSize()
|
modifier = Modifier.fillMaxSize()
|
||||||
) { pageIndex ->
|
) { pageIndex ->
|
||||||
|
if (global.timetable.isNotEmpty()) {
|
||||||
DayScreen(global.timetable[pageIndex])
|
DayScreen(global.timetable[pageIndex])
|
||||||
|
} else {
|
||||||
|
NoDayScreen()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun NoDayScreen() {
|
||||||
|
Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
|
||||||
|
Text(
|
||||||
|
"Zatím žádný rozvrh.",
|
||||||
|
color = Color.White,
|
||||||
|
fontSize = 30.sp,
|
||||||
|
fontStyle = FontStyle.Italic
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -258,6 +326,7 @@ private fun getSubjectColor(s: Subject, transparent: Boolean): Color {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isTimeBetweenT(givenTime: LocalTime, startTime: LocalTime, endTime: LocalTime): Boolean {
|
fun isTimeBetweenT(givenTime: LocalTime, startTime: LocalTime, endTime: LocalTime): Boolean {
|
||||||
// Check if the given time is between startTime and endTime
|
// Check if the given time is between startTime and endTime
|
||||||
return givenTime.isAfter(startTime) && givenTime.isBefore(endTime)
|
return givenTime.isAfter(startTime) && givenTime.isBefore(endTime)
|
||||||
@@ -534,10 +603,10 @@ private fun DayScreen(day: Day) {
|
|||||||
Box(modifier = Modifier
|
Box(modifier = Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.zIndex(99f)
|
.zIndex(99f)
|
||||||
.clickable {
|
/*.clickable {
|
||||||
global.selectedLecture = lectureId
|
global.selectedLecture = lectureId
|
||||||
showDetailDialog = true
|
showDetailDialog = true
|
||||||
})
|
}*/)
|
||||||
|
|
||||||
if (
|
if (
|
||||||
(global.lectureNotes[global.selectedLecture] != null &&
|
(global.lectureNotes[global.selectedLecture] != null &&
|
||||||
|
|||||||
Reference in New Issue
Block a user