10 Commits
13 changed files with 234 additions and 72 deletions
+2 -2
View File
@@ -1,6 +1,6 @@
![solon-logo](solon_logo.png) ![solon-logo](solon_logo.png)
# 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/)
+1 -1
View File
@@ -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
+24
View File
@@ -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 ..
+1
View File
@@ -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">
+3 -3
View File
@@ -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 {
global.marksDepthLevel = MarksDepthLevel.Subject if (markList[0].grade != "0") {
global.subjectToShow = subject global.marksDepthLevel = MarksDepthLevel.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 {
global.marksDepthLevel = MarksDepthLevel.Subject if (markList[0].grade != "0") {
global.subjectToShow = subject global.marksDepthLevel = MarksDepthLevel.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?
settings = Util.fileToString(global.filePaths.settings).toSettingsData() if (!global.demoMode) {
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)
SettingsTableRow(settings.showRefreshButton) if (!global.demoMode) {
SettingsTableRow(settings.showRefreshButton)
}
SettingsTableRow(settings.useAnimations) SettingsTableRow(settings.useAnimations)
} }
@@ -89,26 +89,55 @@ fun signInButtonCallback(ctx: Context, usernameText: String, passwordText: Strin
} }
CoroutineScope(Dispatchers.IO).launch { CoroutineScope(Dispatchers.IO).launch {
val valid = Account.isValid(acc) if (global.username == "demo" && global.password == "Demo1234") {
// start the demo
checked = true launchDemo(ctx)
if (valid) {
Account.save(acc)
global.currentScreen = Screen.Splash
launchStart(ctx)
} else { } else {
withContext(Dispatchers.Main) { val valid = Account.isValid(acc)
Toast.makeText(
ctx, checked = true
"Neplatné přihlašovací údaje nebo nejste připojeni k internetu, zkuste to znovu.",
Toast.LENGTH_LONG if (valid) {
).show() Account.save(acc)
global.currentScreen = Screen.Splash
launchStart(ctx)
} else {
withContext(Dispatchers.Main) {
Toast.makeText(
ctx,
"Neplatné přihlašovací údaje nebo nejste připojeni k internetu, zkuste to znovu.",
Toast.LENGTH_LONG
).show()
}
} }
} }
} }
} }
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() {
// handle the back gesture (back swipe form side or back button on bottom android navbar) // handle the back gesture (back swipe form side or back button on bottom android navbar)
@@ -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,14 +78,63 @@ import java.time.format.DateTimeFormatter
var showDetailDialog by mutableStateOf(false) var showDetailDialog by mutableStateOf(false)
@OptIn(ExperimentalFoundationApi::class)
@Composable @Composable
fun TimetableScreen() { fun TimetableScreen() {
Box( val pagerState = rememberPagerState(pageCount = { if (global.timetable.isNotEmpty()) global.timetable.size else 6 }) // FIXME
modifier = Modifier.fillMaxSize(), Column {
contentAlignment = Alignment.BottomCenter //QuickDays(pagerState)
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.BottomCenter
) {
DayPager(pagerState)
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)
) { ) {
DayPager() for ((idx, day) in global.timetable.withIndex()) {
if (showDetailDialog) DetailDialog() QuickDay(day, Modifier.weight(1f), idx)
}
} }
} }
@@ -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 ->
DayScreen(global.timetable[pageIndex]) if (global.timetable.isNotEmpty()) {
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 &&