Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4f43154a13 | ||
|
|
24dbb3969c | ||
|
|
c7dacbf1bd | ||
|
|
af96914ec7 | ||
|
|
8ddbdc43f9 | ||
|
|
3bb5ce5ca7 | ||
|
|
bda937095c | ||
|
|
67392ccb3d | ||
|
|
a163d6b285 | ||
|
|
e67f87864c | ||
|
|
8e9693bfe6 |
@@ -1,3 +1,3 @@
|
|||||||

|

|
||||||
# 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/-/raw/master/release/com.odweta.solon_2.1.apk?ref_type=heads&inline=false) (verze 2.1)
|
# Odkaz na stažení aplikace pro Android [zde](https://gitlab.com/Odweta/solon/-/raw/master/release/com.odweta.solon_2.2.1.apk?ref_type=heads&inline=false) (verze 2.2.1)
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ android {
|
|||||||
applicationId = "com.odweta.solon"
|
applicationId = "com.odweta.solon"
|
||||||
minSdk = 28
|
minSdk = 28
|
||||||
targetSdk = 34
|
targetSdk = 34
|
||||||
versionCode = 204
|
versionCode = 206
|
||||||
versionName = "2.1"
|
versionName = "2.2.1"
|
||||||
|
|
||||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import androidx.compose.foundation.layout.height
|
|||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.runtime.MutableState
|
import androidx.compose.runtime.MutableState
|
||||||
|
import androidx.compose.runtime.mutableIntStateOf
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
@@ -41,6 +42,7 @@ const val timeTableFilePath: String = "timetable.json"
|
|||||||
const val userDataFilePath: String = "userdata.json"
|
const val userDataFilePath: String = "userdata.json"
|
||||||
const val marksFilePath: String = "marks.json"
|
const val marksFilePath: String = "marks.json"
|
||||||
const val settingsDataFilePath: String = "settings.txt"
|
const val settingsDataFilePath: String = "settings.txt"
|
||||||
|
const val lectureNotesFilePath: String = "lecture_notes.csv"
|
||||||
lateinit var fileDir: File
|
lateinit var fileDir: File
|
||||||
var width: Int = 0
|
var width: Int = 0
|
||||||
var height: Int = 0
|
var height: Int = 0
|
||||||
@@ -85,7 +87,9 @@ class Setting(auxId: SettingsId, auxName: String, auxChecked: Boolean) {
|
|||||||
enum class SettingsId {
|
enum class SettingsId {
|
||||||
Svoboda,
|
Svoboda,
|
||||||
Amoled,
|
Amoled,
|
||||||
RefreshButton
|
RefreshButton,
|
||||||
|
TagNewMarks,
|
||||||
|
DeleteLocalData
|
||||||
}
|
}
|
||||||
|
|
||||||
class SettingsData {
|
class SettingsData {
|
||||||
@@ -107,13 +111,21 @@ class SettingsData {
|
|||||||
true
|
true
|
||||||
)
|
)
|
||||||
|
|
||||||
override fun toString() = "$useSvobodaMode\n$useAmoledMode\n$showRefreshButton"
|
var tagNewMarks: Setting = Setting(
|
||||||
|
SettingsId.TagNewMarks,
|
||||||
|
"Označit nové známky",
|
||||||
|
true
|
||||||
|
)
|
||||||
|
|
||||||
|
override fun toString() = "$useSvobodaMode\n$useAmoledMode\n$showRefreshButton\n$tagNewMarks"
|
||||||
}
|
}
|
||||||
|
|
||||||
var settings : SettingsData = SettingsData()
|
var settings : SettingsData = SettingsData()
|
||||||
|
|
||||||
var done: Boolean = false
|
var done: Boolean = false
|
||||||
|
|
||||||
|
var internetAwaitListenerRunning: Boolean = false
|
||||||
|
|
||||||
var timeTableAvailOffline: Boolean = false
|
var timeTableAvailOffline: Boolean = false
|
||||||
var marksAvailOffline: Boolean = false
|
var marksAvailOffline: Boolean = false
|
||||||
|
|
||||||
@@ -135,6 +147,50 @@ var resetNav: Boolean = false
|
|||||||
|
|
||||||
var isAPISetUp: Boolean = false
|
var isAPISetUp: Boolean = false
|
||||||
|
|
||||||
|
enum class LectureNoteType {
|
||||||
|
Normal, // obycejna poznamka
|
||||||
|
Writing, // pisemny test
|
||||||
|
Speaking, // ustni zkouseni
|
||||||
|
Other // cokoliv jineho
|
||||||
|
}
|
||||||
|
|
||||||
|
fun String.toLectureNoteType(): LectureNoteType {
|
||||||
|
return when(this) {
|
||||||
|
"Normal" -> LectureNoteType.Normal
|
||||||
|
"Writing" -> LectureNoteType.Writing
|
||||||
|
"Speaking" -> LectureNoteType.Speaking
|
||||||
|
"Other" -> LectureNoteType.Other
|
||||||
|
else -> LectureNoteType.Normal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class LectureNote(
|
||||||
|
id: Int,
|
||||||
|
note: MutableState<String>,
|
||||||
|
type: MutableState<LectureNoteType>,
|
||||||
|
number: MutableState<Int>,
|
||||||
|
lectureName: MutableState<String>
|
||||||
|
) {
|
||||||
|
var id: Int = 0
|
||||||
|
var note: MutableState<String> =
|
||||||
|
mutableStateOf("")
|
||||||
|
var type: MutableState<LectureNoteType> =
|
||||||
|
mutableStateOf(LectureNoteType.Normal)
|
||||||
|
var number: MutableState<Int> = mutableIntStateOf(0)
|
||||||
|
var lectureName: MutableState<String> = mutableStateOf("")
|
||||||
|
|
||||||
|
init {
|
||||||
|
this.id = id
|
||||||
|
this.note = note
|
||||||
|
this.type = type
|
||||||
|
this.number = number
|
||||||
|
this.lectureName = lectureName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var lectureNotes: HashMap<Int, MutableState<LectureNote>> = hashMapOf()
|
||||||
|
var selectedLecture: Int = 0
|
||||||
|
|
||||||
var selectedDay: Int = 0
|
var selectedDay: Int = 0
|
||||||
var dayEndString: String = ""
|
var dayEndString: String = ""
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ private var toast2Shown: Boolean = false
|
|||||||
private lateinit var coscope_: CoroutineScope
|
private lateinit var coscope_: CoroutineScope
|
||||||
|
|
||||||
private fun setOnInternetAvailListener(ctx: Context, coscope: CoroutineScope) {
|
private fun setOnInternetAvailListener(ctx: Context, coscope: CoroutineScope) {
|
||||||
|
internetAwaitListenerRunning = true
|
||||||
coscope.launch {
|
coscope.launch {
|
||||||
while (true) {
|
while (true) {
|
||||||
if (Util.internetAvail(ctx) && !internetAvail) {
|
if (Util.internetAvail(ctx) && !internetAvail) {
|
||||||
@@ -140,7 +141,9 @@ private suspend fun launchPhase1(ctx: Context) {
|
|||||||
|
|
||||||
if (!timeTableAvailOffline || !marksAvailOffline || internetAvail) {
|
if (!timeTableAvailOffline || !marksAvailOffline || internetAvail) {
|
||||||
// set up the API (required for later uses of it)
|
// set up the API (required for later uses of it)
|
||||||
Network.setupAPI()
|
if (!isAPISetUp) {
|
||||||
|
Network.setupAPI()
|
||||||
|
}
|
||||||
|
|
||||||
if (internetAvail) {
|
if (internetAvail) {
|
||||||
// cancel a toast, if any
|
// cancel a toast, if any
|
||||||
@@ -272,10 +275,14 @@ private fun launchPhase2(ctx: Context) {
|
|||||||
dayList.add(day)
|
dayList.add(day)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Util.loadLectureIds()
|
||||||
|
|
||||||
loaded = true
|
loaded = true
|
||||||
|
|
||||||
coscope_.launch {
|
coscope_.launch {
|
||||||
setOnInternetAvailListener(ctx, coscope_)
|
if (!internetAwaitListenerRunning) {
|
||||||
|
setOnInternetAvailListener(ctx, coscope_)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val role = if (Parsing.userIsParent()) {
|
val role = if (Parsing.userIsParent()) {
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import androidx.compose.foundation.shape.RoundedCornerShape
|
|||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.ArrowBackIosNew
|
import androidx.compose.material.icons.filled.ArrowBackIosNew
|
||||||
|
import androidx.compose.material.icons.filled.AutoAwesome
|
||||||
import androidx.compose.material3.Button
|
import androidx.compose.material3.Button
|
||||||
import androidx.compose.material3.ButtonDefaults
|
import androidx.compose.material3.ButtonDefaults
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
@@ -45,6 +46,8 @@ 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 java.time.LocalDate
|
||||||
|
import java.time.format.DateTimeFormatter
|
||||||
|
|
||||||
enum class MarksShow {
|
enum class MarksShow {
|
||||||
All,
|
All,
|
||||||
@@ -183,6 +186,16 @@ fun MarksAll() {
|
|||||||
Box(modifier = Modifier.height(10.dp))
|
Box(modifier = Modifier.height(10.dp))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// only add if mark date is not older than one week
|
||||||
|
var subjectContainsNewMark = false
|
||||||
|
for (mark in markList) {
|
||||||
|
if (LocalDate.parse(mark.date, DateTimeFormatter.ISO_LOCAL_DATE_TIME)
|
||||||
|
.isAfter(LocalDate.now().minusWeeks(1))
|
||||||
|
) {
|
||||||
|
subjectContainsNewMark = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Row(
|
Row(
|
||||||
modifier = amoledModifierBackground
|
modifier = amoledModifierBackground
|
||||||
) {
|
) {
|
||||||
@@ -221,17 +234,30 @@ fun MarksAll() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier.fillMaxSize().weight(1f),
|
||||||
.weight(1f)
|
contentAlignment = Alignment.TopStart
|
||||||
.fillMaxHeight()
|
|
||||||
.padding(horizontal = 10.dp),
|
|
||||||
contentAlignment = Alignment.Center
|
|
||||||
) {
|
) {
|
||||||
Text(
|
if (subjectContainsNewMark && settings.tagNewMarks.checked.value) {
|
||||||
text = marksString,
|
Icon(
|
||||||
fontSize = 22.sp,
|
modifier = Modifier.padding(start = 4.dp, top = 4.dp),
|
||||||
color = Color.White
|
imageVector = Icons.Default.AutoAwesome,
|
||||||
)
|
contentDescription = "New marks in subject",
|
||||||
|
tint = Color.White // You can customize the icon color
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.padding(horizontal = 10.dp),
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = marksString,
|
||||||
|
fontSize = 22.sp,
|
||||||
|
color = Color.White
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -342,7 +368,7 @@ fun MarksSubject() {
|
|||||||
},
|
},
|
||||||
shape = RoundedCornerShape(roundedCornerDimen)
|
shape = RoundedCornerShape(roundedCornerDimen)
|
||||||
)
|
)
|
||||||
.padding(vertical = 20.dp)
|
.padding(vertical = 20.dp, horizontal = 10.dp)
|
||||||
) // subject
|
) // subject
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(20.dp))
|
Spacer(modifier = Modifier.height(20.dp))
|
||||||
@@ -353,50 +379,66 @@ fun MarksSubject() {
|
|||||||
Spacer(modifier = Modifier.height(10.dp))
|
Spacer(modifier = Modifier.height(10.dp))
|
||||||
}
|
}
|
||||||
|
|
||||||
Row(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier.fillMaxWidth(),
|
||||||
.fillMaxWidth()
|
contentAlignment = Alignment.TopStart
|
||||||
.padding(horizontal = 5.dp)
|
) {
|
||||||
.background(color = if (settings.useAmoledMode.checked.value) {
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(horizontal = 5.dp)
|
||||||
|
.background(color = if (settings.useAmoledMode.checked.value) {
|
||||||
Color.Black
|
Color.Black
|
||||||
} else {
|
} else {
|
||||||
getAvgColor(
|
getAvgColor(mark.grade)
|
||||||
Util.avg(marks[subjectToShow]!!)
|
|
||||||
)
|
|
||||||
|
|
||||||
},
|
},
|
||||||
shape = RoundedCornerShape(roundedCornerDimen)
|
shape = RoundedCornerShape(roundedCornerDimen)
|
||||||
)
|
)
|
||||||
.padding(vertical = 10.dp)
|
.padding(vertical = 10.dp)
|
||||||
.clickable {
|
.clickable {
|
||||||
markToShow = mark
|
markToShow = mark
|
||||||
marksShow.value = MarksShow.Detail
|
marksShow.value = MarksShow.Detail
|
||||||
}
|
}
|
||||||
) {
|
|
||||||
Box(
|
|
||||||
modifier = Modifier
|
|
||||||
.width(70.dp)
|
|
||||||
.align(Alignment.CenterVertically),
|
|
||||||
contentAlignment = Alignment.Center
|
|
||||||
) {
|
) {
|
||||||
Text(
|
Box(
|
||||||
text = mark.grade,
|
modifier = Modifier
|
||||||
color = Color.White,
|
.width(70.dp)
|
||||||
fontSize = 30.sp
|
.align(Alignment.CenterVertically),
|
||||||
) // grade
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = mark.grade,
|
||||||
|
color = Color.White,
|
||||||
|
fontSize = 30.sp
|
||||||
|
) // grade
|
||||||
|
}
|
||||||
|
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.align(Alignment.CenterVertically)
|
||||||
|
.weight(1f),
|
||||||
|
contentAlignment = Alignment.CenterStart
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = mark.theme,
|
||||||
|
color = Color.White,
|
||||||
|
fontSize = 20.sp
|
||||||
|
) // theme
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Box(
|
// only add if mark date is not older than one week
|
||||||
modifier = Modifier
|
if ((LocalDate
|
||||||
.align(Alignment.CenterVertically)
|
.parse(mark.date, DateTimeFormatter.ISO_LOCAL_DATE_TIME)
|
||||||
.weight(1f),
|
.isAfter(LocalDate.now().minusWeeks(1))
|
||||||
contentAlignment = Alignment.CenterStart
|
) && settings.tagNewMarks.checked.value
|
||||||
) {
|
) {
|
||||||
Text(
|
Icon(
|
||||||
text = mark.theme,
|
modifier = Modifier.padding(start = 7.dp, top = 4.dp),
|
||||||
color = Color.White,
|
imageVector = Icons.Default.AutoAwesome,
|
||||||
fontSize = 20.sp
|
contentDescription = "A new mark",
|
||||||
) // theme
|
tint = Color.White // You can customize the icon color
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -434,7 +476,7 @@ fun MarksDetail() {
|
|||||||
),
|
),
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.border(
|
.border(
|
||||||
width = 5.dp,
|
width = borderWidthDimen,
|
||||||
shape = RoundedCornerShape(roundedCornerDimen),
|
shape = RoundedCornerShape(roundedCornerDimen),
|
||||||
color = PastelYellow
|
color = PastelYellow
|
||||||
)
|
)
|
||||||
@@ -455,9 +497,9 @@ fun MarksDetail() {
|
|||||||
.width(70.dp)
|
.width(70.dp)
|
||||||
.height(70.dp)
|
.height(70.dp)
|
||||||
.border(
|
.border(
|
||||||
width = 5.dp,
|
width = borderWidthDimen,
|
||||||
color = getAvgColor(
|
color = getAvgColor(
|
||||||
Util.avg(marks[subjectToShow]!!),
|
Util.avg(mutableListOf(markToShow)),
|
||||||
true
|
true
|
||||||
),
|
),
|
||||||
shape = RoundedCornerShape(roundedCornerDimen)
|
shape = RoundedCornerShape(roundedCornerDimen)
|
||||||
@@ -467,7 +509,7 @@ fun MarksDetail() {
|
|||||||
Color.Black
|
Color.Black
|
||||||
} else {
|
} else {
|
||||||
getAvgColor(
|
getAvgColor(
|
||||||
Util.avg(marks[subjectToShow]!!)
|
Util.avg(mutableListOf(markToShow))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -486,28 +528,26 @@ fun MarksDetail() {
|
|||||||
Spacer(modifier = Modifier.height(20.dp))
|
Spacer(modifier = Modifier.height(20.dp))
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
//Box(modifier = Modifier.height(70.dp)) {
|
Text(
|
||||||
Text(
|
text = markToShow.theme,
|
||||||
text = markToShow.theme,
|
color = Color.White,
|
||||||
color = Color.White,
|
textAlign = TextAlign.Center,
|
||||||
textAlign = TextAlign.Center,
|
fontSize = 30.sp,
|
||||||
fontSize = 30.sp,
|
modifier = Modifier
|
||||||
modifier = Modifier
|
.fillMaxWidth()
|
||||||
.fillMaxWidth()
|
.border(
|
||||||
.border(
|
width = 5.dp,
|
||||||
width = 5.dp,
|
color = PastelYellow,
|
||||||
color = PastelYellow,
|
shape = RoundedCornerShape(roundedCornerDimen)
|
||||||
shape = RoundedCornerShape(roundedCornerDimen)
|
)
|
||||||
)
|
.background(if (settings.useAmoledMode.checked.value) {
|
||||||
.background(if (settings.useAmoledMode.checked.value) {
|
Color.Black
|
||||||
Color.Black
|
} else {
|
||||||
} else {
|
PastelYellowTransparent
|
||||||
PastelYellowTransparent
|
}
|
||||||
}
|
)
|
||||||
)
|
.padding(vertical = 20.dp)
|
||||||
.padding(vertical = 20.dp)
|
) // description
|
||||||
) // description
|
|
||||||
//}
|
|
||||||
} // description
|
} // description
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(20.dp))
|
Spacer(modifier = Modifier.height(20.dp))
|
||||||
|
|||||||
@@ -88,6 +88,10 @@ fun SettingsScreen(modifier: Modifier = Modifier) {
|
|||||||
Spacer(Modifier.height(10.dp))
|
Spacer(Modifier.height(10.dp))
|
||||||
|
|
||||||
SettingsTableRow(settings.showRefreshButton)
|
SettingsTableRow(settings.showRefreshButton)
|
||||||
|
|
||||||
|
Spacer(Modifier.height(10.dp))
|
||||||
|
|
||||||
|
SettingsTableRow(settings.tagNewMarks)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,6 +121,8 @@ fun SettingsTableRow(setting: Setting) {
|
|||||||
SettingsId.Svoboda -> settings.useSvobodaMode = setting
|
SettingsId.Svoboda -> settings.useSvobodaMode = setting
|
||||||
SettingsId.Amoled -> settings.useAmoledMode = setting
|
SettingsId.Amoled -> settings.useAmoledMode = setting
|
||||||
SettingsId.RefreshButton -> settings.showRefreshButton = setting
|
SettingsId.RefreshButton -> settings.showRefreshButton = setting
|
||||||
|
SettingsId.TagNewMarks -> settings.tagNewMarks = setting
|
||||||
|
else -> {}
|
||||||
}
|
}
|
||||||
Util.saveStringToFile(settingsDataFilePath, settings.toString())
|
Util.saveStringToFile(settingsDataFilePath, settings.toString())
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -2,54 +2,75 @@ package com.odweta.solon
|
|||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||||
|
import androidx.compose.foundation.Image
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.border
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.fillMaxHeight
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.Image
|
|
||||||
import androidx.compose.foundation.border
|
|
||||||
import androidx.compose.foundation.layout.Box
|
|
||||||
import androidx.compose.foundation.layout.Spacer
|
|
||||||
import androidx.compose.foundation.layout.fillMaxHeight
|
|
||||||
import androidx.compose.foundation.layout.size
|
|
||||||
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.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
|
||||||
|
import androidx.compose.foundation.text.selection.TextSelectionColors
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.Refresh
|
import androidx.compose.material.icons.filled.AutoAwesome
|
||||||
|
import androidx.compose.material.icons.filled.EditNote
|
||||||
import androidx.compose.material3.Button
|
import androidx.compose.material3.Button
|
||||||
import androidx.compose.material3.ButtonDefaults
|
import androidx.compose.material3.ButtonColors
|
||||||
|
import androidx.compose.material3.DropdownMenu
|
||||||
|
import androidx.compose.material3.DropdownMenuItem
|
||||||
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.TextField
|
||||||
|
import androidx.compose.material3.TextFieldDefaults
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableIntStateOf
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.focus.focusModifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.text.font.FontStyle
|
import androidx.compose.ui.text.font.FontStyle
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
|
import androidx.compose.ui.window.Dialog
|
||||||
|
import androidx.compose.ui.window.DialogProperties
|
||||||
|
import androidx.compose.ui.window.PopupProperties
|
||||||
|
import androidx.compose.ui.zIndex
|
||||||
import com.odweta.solon.ui.theme.PastelGreen
|
import com.odweta.solon.ui.theme.PastelGreen
|
||||||
import com.odweta.solon.ui.theme.PastelGreenTransparent
|
import com.odweta.solon.ui.theme.PastelGreenTransparent
|
||||||
import com.odweta.solon.ui.theme.PastelRed
|
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.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
import java.time.LocalTime
|
import java.time.LocalTime
|
||||||
import java.time.format.DateTimeFormatter
|
import java.time.format.DateTimeFormatter
|
||||||
|
|
||||||
|
var showDetailDialog = mutableStateOf(false)
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun TimetableScreen() {
|
fun TimetableScreen() {
|
||||||
Box(
|
Box(
|
||||||
@@ -58,15 +79,165 @@ fun TimetableScreen() {
|
|||||||
contentAlignment = Alignment.BottomCenter
|
contentAlignment = Alignment.BottomCenter
|
||||||
) {
|
) {
|
||||||
DayPager()
|
DayPager()
|
||||||
//if (settings.showRefreshButton.checked.value) {
|
if (showDetailDialog.value) {
|
||||||
// RefreshButton()
|
DetailDialog()
|
||||||
//}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("UnrememberedMutableState")
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
@Composable
|
||||||
|
fun DetailDialog() {
|
||||||
|
Dialog(
|
||||||
|
onDismissRequest = { showDetailDialog.value = false }, // Close the dialog on dismiss
|
||||||
|
properties = DialogProperties(
|
||||||
|
dismissOnBackPress = true,
|
||||||
|
dismissOnClickOutside = true
|
||||||
|
),
|
||||||
|
content = {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(horizontal = 20.dp)
|
||||||
|
.background(
|
||||||
|
color = Color.Black,
|
||||||
|
shape = RoundedCornerShape(roundedCornerDimen)
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "" +
|
||||||
|
lectureNotes[selectedLecture]?.value?.number?.value.toString() +
|
||||||
|
" – " +
|
||||||
|
lectureNotes[selectedLecture]?.value?.lectureName?.value.toString(),
|
||||||
|
color = Color.White,
|
||||||
|
textAlign = TextAlign.Left
|
||||||
|
)
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
var isExpanded by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
|
Button(
|
||||||
|
modifier = Modifier.background(
|
||||||
|
color = Color.Black,
|
||||||
|
shape = RoundedCornerShape(roundedCornerDimen)
|
||||||
|
),
|
||||||
|
onClick = { isExpanded = true },
|
||||||
|
colors = ButtonColors(
|
||||||
|
containerColor = Color.Black,
|
||||||
|
contentColor = Color.White,
|
||||||
|
disabledContainerColor = Color.Black,
|
||||||
|
disabledContentColor = Color.White
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
val type = when (lectureNotes[selectedLecture]?.value?.type?.value) {
|
||||||
|
LectureNoteType.Normal -> "Normální"
|
||||||
|
LectureNoteType.Writing -> "Písemný test"
|
||||||
|
LectureNoteType.Speaking -> "Ústní zkoušení"
|
||||||
|
LectureNoteType.Other -> "Jiné"
|
||||||
|
else -> "Jiné"
|
||||||
|
}
|
||||||
|
Text("Typ poznámky: $type")
|
||||||
|
}
|
||||||
|
|
||||||
|
DropdownMenu(
|
||||||
|
modifier = Modifier.background(color = Color.Black),
|
||||||
|
onDismissRequest = { isExpanded = false },
|
||||||
|
expanded = isExpanded,
|
||||||
|
properties = PopupProperties(
|
||||||
|
excludeFromSystemGesture = false,
|
||||||
|
dismissOnClickOutside = true,
|
||||||
|
dismissOnBackPress = true,
|
||||||
|
focusable = true
|
||||||
|
),
|
||||||
|
) {
|
||||||
|
DropdownMenuItem(
|
||||||
|
enabled = true,
|
||||||
|
onClick = {
|
||||||
|
isExpanded = false
|
||||||
|
lectureNotes[selectedLecture]?.value?.type?.value =
|
||||||
|
LectureNoteType.Normal
|
||||||
|
},
|
||||||
|
text = { Text("Normální poznámka", color = Color.White) }
|
||||||
|
)
|
||||||
|
|
||||||
|
DropdownMenuItem(
|
||||||
|
enabled = true,
|
||||||
|
onClick = {
|
||||||
|
isExpanded = false
|
||||||
|
lectureNotes[selectedLecture]?.value?.type?.value =
|
||||||
|
LectureNoteType.Writing
|
||||||
|
},
|
||||||
|
text = { Text("Písemný test", color = Color.White) }
|
||||||
|
)
|
||||||
|
|
||||||
|
DropdownMenuItem(
|
||||||
|
enabled = true,
|
||||||
|
onClick = {
|
||||||
|
isExpanded = false
|
||||||
|
lectureNotes[selectedLecture]?.value?.type?.value =
|
||||||
|
LectureNoteType.Speaking
|
||||||
|
},
|
||||||
|
text = { Text("Ústní zkoušení", color = Color.White) }
|
||||||
|
)
|
||||||
|
|
||||||
|
DropdownMenuItem(
|
||||||
|
enabled = true,
|
||||||
|
onClick = {
|
||||||
|
isExpanded = false
|
||||||
|
lectureNotes[selectedLecture]?.value?.type?.value =
|
||||||
|
LectureNoteType.Other
|
||||||
|
},
|
||||||
|
text = { Text("Jiné", color = Color.White) }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////
|
||||||
|
|
||||||
|
if (lectureNotes[selectedLecture] == null) {
|
||||||
|
lectureNotes[selectedLecture] = mutableStateOf(
|
||||||
|
LectureNote(
|
||||||
|
id = 0,
|
||||||
|
note = mutableStateOf(""),
|
||||||
|
type = mutableStateOf(LectureNoteType.Normal),
|
||||||
|
number = mutableIntStateOf(0),
|
||||||
|
lectureName = mutableStateOf("N/A")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
TextField(
|
||||||
|
value = lectureNotes[selectedLecture]?.value?.note?.value ?: "",
|
||||||
|
onValueChange = { newText: String ->
|
||||||
|
lectureNotes[selectedLecture]?.value?.note?.value = newText
|
||||||
|
Util.saveLectureIds()
|
||||||
|
},
|
||||||
|
placeholder = { Text("Sem můžete napsat poznámky k\u00A0této hodině.") }, //
|
||||||
|
colors = TextFieldDefaults.textFieldColors(
|
||||||
|
focusedTextColor = Color.White,
|
||||||
|
containerColor = Color.Black,
|
||||||
|
selectionColors = TextSelectionColors(
|
||||||
|
handleColor = PastelYellow,
|
||||||
|
backgroundColor = PastelYellowTransparent
|
||||||
|
),
|
||||||
|
cursorColor = PastelYellow,
|
||||||
|
focusedIndicatorColor = PastelYellow,
|
||||||
|
unfocusedIndicatorColor = PastelYellowTransparent
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalFoundationApi::class)
|
@OptIn(ExperimentalFoundationApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun DayPager(modifier: Modifier = Modifier) {
|
fun DayPager() {
|
||||||
val pagerState = rememberPagerState(pageCount = { days.size })
|
val pagerState = rememberPagerState(pageCount = { days.size })
|
||||||
HorizontalPager(
|
HorizontalPager(
|
||||||
state = pagerState,
|
state = pagerState,
|
||||||
@@ -76,45 +247,6 @@ fun DayPager(modifier: Modifier = Modifier) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//@Composable
|
|
||||||
/*fun RefreshButton(modifier: Modifier = Modifier) {
|
|
||||||
val coscope = rememberCoroutineScope()
|
|
||||||
val ctx = LocalContext.current
|
|
||||||
|
|
||||||
Box(
|
|
||||||
modifier = Modifier
|
|
||||||
.padding(bottom = 10.dp)
|
|
||||||
.background(color = Color.Black, shape = RoundedCornerShape(roundedCornerDimen))
|
|
||||||
) {
|
|
||||||
Button(
|
|
||||||
onClick = {
|
|
||||||
coscope.launch {
|
|
||||||
fetchNewData(ctx, coscope)
|
|
||||||
|
|
||||||
}
|
|
||||||
},
|
|
||||||
colors = ButtonDefaults.buttonColors(
|
|
||||||
contentColor = Color.White,
|
|
||||||
containerColor = Color.Black
|
|
||||||
),
|
|
||||||
modifier = Modifier
|
|
||||||
.border(
|
|
||||||
width = 5.dp,
|
|
||||||
shape = RoundedCornerShape(roundedCornerDimen),
|
|
||||||
color = PastelYellow
|
|
||||||
)
|
|
||||||
.padding(vertical = 10.dp)
|
|
||||||
) {
|
|
||||||
Icon(
|
|
||||||
imageVector = Icons.Default.Refresh,
|
|
||||||
contentDescription = "Refresh icon",
|
|
||||||
modifier = Modifier.size(25.dp)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
private fun getSubjectColor(s: Subject, transparent: Boolean): Color {
|
private fun getSubjectColor(s: Subject, transparent: Boolean): Color {
|
||||||
return if (s.free) {
|
return if (s.free) {
|
||||||
if (transparent) {
|
if (transparent) {
|
||||||
@@ -198,6 +330,7 @@ fun subjectModifier(d: Day, s: Subject, lectureNumber: Int): Modifier {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("UnrememberedMutableState")
|
||||||
@Composable
|
@Composable
|
||||||
private fun DayScreen(day: Day) {
|
private fun DayScreen(day: Day) {
|
||||||
val scrollState = rememberScrollState()
|
val scrollState = rememberScrollState()
|
||||||
@@ -228,7 +361,19 @@ private fun DayScreen(day: Day) {
|
|||||||
.padding(horizontal = 5.dp)
|
.padding(horizontal = 5.dp)
|
||||||
.verticalScroll(scrollState)
|
.verticalScroll(scrollState)
|
||||||
) {
|
) {
|
||||||
for (subject in day.subjects) {
|
for ((subjectIndex, subject) in day.subjects.withIndex()) {
|
||||||
|
val lectureId = Util.getLectureId(day.date, subjectIndex)
|
||||||
|
if (lectureNotes[lectureId] == null) {
|
||||||
|
lectureNotes[lectureId] = mutableStateOf(LectureNote(
|
||||||
|
id = lectureId,
|
||||||
|
note = mutableStateOf(""),
|
||||||
|
type = mutableStateOf(LectureNoteType.Normal),
|
||||||
|
number = mutableIntStateOf(0),
|
||||||
|
lectureName = mutableStateOf("N/A")
|
||||||
|
))
|
||||||
|
}
|
||||||
|
lectureNotes[lectureId]?.value?.number?.value = subject.number.toInt()
|
||||||
|
lectureNotes[lectureId]?.value?.lectureName?.value = subject.name
|
||||||
val amoledModifier = if (settings.useAmoledMode.checked.value) {
|
val amoledModifier = if (settings.useAmoledMode.checked.value) {
|
||||||
Modifier
|
Modifier
|
||||||
.width(50.dp)
|
.width(50.dp)
|
||||||
@@ -270,137 +415,159 @@ private fun DayScreen(day: Day) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Row(
|
Box (
|
||||||
modifier = subjectModifier(day, subject, subject.number.toInt())
|
modifier = subjectModifier(day, subject, subject.number.toInt()),
|
||||||
|
contentAlignment = Alignment.TopStart
|
||||||
) {
|
) {
|
||||||
if (subject.substitute != "2") {
|
Row {
|
||||||
Box(
|
if (subject.substitute != "2") {
|
||||||
modifier = amoledModifier,
|
Box(
|
||||||
contentAlignment = Alignment.Center
|
modifier = amoledModifier,
|
||||||
) {
|
contentAlignment = Alignment.Center
|
||||||
Text(
|
) {
|
||||||
text = subject.number,
|
Text(
|
||||||
fontSize = 30.sp,
|
text = subject.number,
|
||||||
color = Color.White
|
fontSize = 30.sp,
|
||||||
)
|
color = Color.White
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (subject.substitute != "2") {
|
if (subject.substitute != "2") {
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxHeight()
|
.fillMaxHeight()
|
||||||
.padding(start = 20.dp),
|
.padding(start = 20.dp),
|
||||||
verticalArrangement = Arrangement.Center,
|
verticalArrangement = Arrangement.Center,
|
||||||
horizontalAlignment = Alignment.Start
|
horizontalAlignment = Alignment.Start
|
||||||
) {
|
) {
|
||||||
if (!subject.free) {
|
if (!subject.free) {
|
||||||
if (subject.substitute == "1") {
|
if (subject.substitute == "1") {
|
||||||
Row {
|
Row {
|
||||||
|
Text(
|
||||||
|
text = subject.name.uppercase(),
|
||||||
|
color = Color.White,
|
||||||
|
fontSize = 25.sp,
|
||||||
|
fontWeight = FontWeight.Bold
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.width(10.dp))
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = " supl ",
|
||||||
|
color = Color.Black,
|
||||||
|
modifier = Modifier.background(color = Color.White)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
Text(
|
Text(
|
||||||
text = subject.name.uppercase(),
|
text = subject.name.uppercase(),
|
||||||
color = Color.White,
|
color = Color.White,
|
||||||
fontSize = 25.sp,
|
fontSize = 25.sp,
|
||||||
fontWeight = FontWeight.Bold
|
fontWeight = FontWeight.Bold
|
||||||
)
|
)
|
||||||
|
|
||||||
Spacer(modifier = Modifier.width(10.dp))
|
|
||||||
|
|
||||||
Text(
|
|
||||||
text = " supl ",
|
|
||||||
color = Color.Black,
|
|
||||||
modifier = Modifier.background(color = Color.White)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
Text(
|
|
||||||
text = subject.name.uppercase(),
|
|
||||||
color = Color.White,
|
|
||||||
fontSize = 25.sp,
|
|
||||||
fontWeight = FontWeight.Bold
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Text(
|
|
||||||
text = subject.place,
|
|
||||||
color = Color.White,
|
|
||||||
fontSize = 21.sp
|
|
||||||
)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Column(
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxHeight()
|
|
||||||
.padding(start = 20.dp),
|
|
||||||
verticalArrangement = Arrangement.Center,
|
|
||||||
horizontalAlignment = Alignment.CenterHorizontally
|
|
||||||
) {
|
|
||||||
Text(
|
|
||||||
text = subject.name,
|
|
||||||
color = Color.White,
|
|
||||||
fontSize = 20.sp,
|
|
||||||
fontWeight = FontWeight.Bold
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Box(
|
|
||||||
modifier = Modifier
|
|
||||||
.weight(1f)
|
|
||||||
.fillMaxHeight()
|
|
||||||
.padding(vertical = 5.dp),
|
|
||||||
contentAlignment = Alignment.Center
|
|
||||||
) {
|
|
||||||
if (settings.useSvobodaMode.checked.value) {
|
|
||||||
if (
|
|
||||||
subject.teacher == "Jindřich Svoboda" &&
|
|
||||||
studentClass == "5. G"
|
|
||||||
) {
|
|
||||||
Image(
|
|
||||||
painter = painterResource(R.drawable.spock),
|
|
||||||
contentDescription = "Spock",
|
|
||||||
modifier = Modifier.fillMaxSize()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (subject.substitute != "2") {
|
|
||||||
Column(
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxHeight()
|
|
||||||
.padding(end = 20.dp),
|
|
||||||
verticalArrangement = Arrangement.Center,
|
|
||||||
horizontalAlignment = Alignment.End
|
|
||||||
) {
|
|
||||||
// show only for non prepended free lectures
|
|
||||||
if ((subject.free && subject.start != "00:00" && subject.end != "00:00") || !subject.free) {
|
|
||||||
Text(
|
Text(
|
||||||
text = "${subject.start}–${subject.end}",
|
text = subject.place,
|
||||||
color = Color.White,
|
color = Color.White,
|
||||||
fontSize = 21.sp
|
fontSize = 21.sp
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxHeight()
|
||||||
|
.padding(start = 20.dp),
|
||||||
|
verticalArrangement = Arrangement.Center,
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = subject.name,
|
||||||
|
color = Color.White,
|
||||||
|
fontSize = 20.sp,
|
||||||
|
fontWeight = FontWeight.Bold
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!subject.free) {
|
Box(
|
||||||
Box (
|
modifier = Modifier
|
||||||
contentAlignment = Alignment.BottomEnd
|
.weight(1f)
|
||||||
|
.fillMaxHeight()
|
||||||
|
.padding(vertical = 5.dp),
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
if (settings.useSvobodaMode.checked.value) {
|
||||||
|
if (
|
||||||
|
subject.teacher == "Jindřich Svoboda" &&
|
||||||
|
studentClass == "5. G"
|
||||||
) {
|
) {
|
||||||
Text(
|
Image(
|
||||||
text = subject.teacher,
|
painter = painterResource(R.drawable.spock),
|
||||||
color = Color.White,
|
contentDescription = "Spock",
|
||||||
fontSize = 12.sp
|
modifier = Modifier.fillMaxSize()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (subject.substitute != "2") {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxHeight()
|
||||||
|
.padding(end = 10.dp),
|
||||||
|
verticalArrangement = Arrangement.Center,
|
||||||
|
horizontalAlignment = Alignment.End
|
||||||
|
) {
|
||||||
|
// show only for non prepended free lectures
|
||||||
|
if ((subject.free && subject.start != "00:00" && subject.end != "00:00") || !subject.free) {
|
||||||
|
Text(
|
||||||
|
text = "${subject.start}–${subject.end}",
|
||||||
|
color = Color.White,
|
||||||
|
fontSize = 21.sp
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!subject.free) {
|
||||||
|
Box (
|
||||||
|
contentAlignment = Alignment.BottomEnd
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = subject.teacher,
|
||||||
|
color = Color.White,
|
||||||
|
fontSize = 12.sp
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Box(modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.zIndex(99f)
|
||||||
|
.clickable {
|
||||||
|
selectedLecture = lectureId
|
||||||
|
showDetailDialog.value = true
|
||||||
|
})
|
||||||
|
|
||||||
|
if (
|
||||||
|
lectureNotes[lectureId] == null ||
|
||||||
|
(lectureNotes[lectureId] != null && lectureNotes[lectureId]?.value?.note?.value != "") ||
|
||||||
|
(lectureNotes[lectureId] != null && lectureNotes[lectureId]?.value?.type?.value != LectureNoteType.Normal) &&
|
||||||
|
(lectureNotes[lectureId] != null && lectureNotes[lectureId]?.value?.type?.value != LectureNoteType.Other)
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
modifier = Modifier.padding(start = 3.dp, top = 1.dp),
|
||||||
|
imageVector = Icons.Default.EditNote,
|
||||||
|
contentDescription = "Lecture has note",
|
||||||
|
tint = Color.White // You can customize the icon color
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//if (settings.showRefreshButton.checked.value) {
|
|
||||||
// Spacer(modifier = Modifier.height(90.dp))
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -8,10 +8,15 @@ import android.net.NetworkCapabilities
|
|||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.util.DisplayMetrics
|
import android.util.DisplayMetrics
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
|
import androidx.compose.runtime.MutableState
|
||||||
|
import androidx.compose.runtime.mutableIntStateOf
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.core.content.pm.PackageInfoCompat
|
import androidx.core.content.pm.PackageInfoCompat
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.nio.charset.Charset
|
import java.nio.charset.Charset
|
||||||
|
import java.security.MessageDigest
|
||||||
|
import kotlin.math.abs
|
||||||
import kotlin.math.round
|
import kotlin.math.round
|
||||||
|
|
||||||
class Util {
|
class Util {
|
||||||
@@ -115,12 +120,14 @@ class Util {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun isAppInForeground(context: Context, packageName: String): Boolean {
|
fun isAppInForeground(context: Context, packageName: String): Boolean {
|
||||||
val activityManager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
|
val activityManager =
|
||||||
|
context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
|
||||||
val runningAppProcesses = activityManager.runningAppProcesses ?: return false
|
val runningAppProcesses = activityManager.runningAppProcesses ?: return false
|
||||||
|
|
||||||
for (processInfo in runningAppProcesses) {
|
for (processInfo in runningAppProcesses) {
|
||||||
if (processInfo.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND &&
|
if (processInfo.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND &&
|
||||||
processInfo.processName == packageName) {
|
processInfo.processName == packageName
|
||||||
|
) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -147,7 +154,7 @@ class Util {
|
|||||||
weights.add(mark.weight.toFloat())
|
weights.add(mark.weight.toFloat())
|
||||||
}
|
}
|
||||||
|
|
||||||
return "${Math.round(sum/sum(weights) * 100f) / 100f}".replace(",", ".")
|
return "${Math.round(sum / sum(weights) * 100f) / 100f}".replace(",", ".")
|
||||||
//return String.format("%.2f", (sum / sum(weights))).replace(',', '.')
|
//return String.format("%.2f", (sum / sum(weights))).replace(',', '.')
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -215,7 +222,10 @@ class Util {
|
|||||||
val packageManager = context.packageManager
|
val packageManager = context.packageManager
|
||||||
val packageName = context.packageName
|
val packageName = context.packageName
|
||||||
val packageInfo = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
val packageInfo = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||||
packageManager.getPackageInfo(packageName, PackageManager.PackageInfoFlags.of(0))
|
packageManager.getPackageInfo(
|
||||||
|
packageName,
|
||||||
|
PackageManager.PackageInfoFlags.of(0)
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
packageManager.getPackageInfo(packageName, 0)
|
packageManager.getPackageInfo(packageName, 0)
|
||||||
}
|
}
|
||||||
@@ -249,5 +259,67 @@ class Util {
|
|||||||
|
|
||||||
return auxSettingsData
|
return auxSettingsData
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getLectureId(date: String, subjectIndex: Int): Int {
|
||||||
|
val concat = "$date[$subjectIndex]"
|
||||||
|
val bytes = concat.toByteArray()
|
||||||
|
val md5AsBytes = MessageDigest.getInstance("MD5").digest(bytes)
|
||||||
|
return abs(md5AsBytes.take(4).fold(0) { acc, byte ->
|
||||||
|
(acc shl 8) or (byte.toInt() and 0xff)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fun csvToHashMap(filePath: String): HashMap<Int, MutableState<LectureNote>> {
|
||||||
|
val hashMap = HashMap<Int, MutableState<LectureNote>>()
|
||||||
|
val lines = fileToString(filePath).lines()
|
||||||
|
for (line in lines) {
|
||||||
|
if (line.isBlank()) continue
|
||||||
|
|
||||||
|
val parts = line.split(",")
|
||||||
|
|
||||||
|
if (parts.size == 5) {
|
||||||
|
val id = parts[0].trim().toInt()
|
||||||
|
val note = parts[1].trim()
|
||||||
|
val type = parts[2].trim().toLectureNoteType()
|
||||||
|
val number = parts[3].trim().toInt()
|
||||||
|
val lectureName = parts[4].trim()
|
||||||
|
|
||||||
|
val lectureNote = LectureNote(
|
||||||
|
id,
|
||||||
|
mutableStateOf(note),
|
||||||
|
mutableStateOf(type),
|
||||||
|
mutableIntStateOf(number),
|
||||||
|
mutableStateOf(lectureName)
|
||||||
|
)
|
||||||
|
|
||||||
|
hashMap[id] = mutableStateOf(lectureNote)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return hashMap
|
||||||
|
}
|
||||||
|
|
||||||
|
fun hashMapToCsv(hashMap: HashMap<Int, MutableState<LectureNote>>): String {
|
||||||
|
var result = ""
|
||||||
|
for ((key, lectureNote) in hashMap) {
|
||||||
|
result +=
|
||||||
|
"$key," +
|
||||||
|
"${lectureNote.value.note.value}," +
|
||||||
|
"${lectureNote.value.type.value}," +
|
||||||
|
"${lectureNote.value.number.value}," +
|
||||||
|
lectureNote.value.lectureName.value +
|
||||||
|
"\n"
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
fun loadLectureIds() {
|
||||||
|
lectureNotes = csvToHashMap(lectureNotesFilePath)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun saveLectureIds() {
|
||||||
|
val toSave = hashMapToCsv(lectureNotes)
|
||||||
|
saveStringToFile(lectureNotesFilePath, toSave)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -21,4 +21,4 @@ kotlin.code.style=official
|
|||||||
# resources declared in the library itself and none from the library's dependencies,
|
# resources declared in the library itself and none from the library's dependencies,
|
||||||
# thereby reducing the size of the R class for that library
|
# thereby reducing the size of the R class for that library
|
||||||
android.nonTransitiveRClass=true
|
android.nonTransitiveRClass=true
|
||||||
sdk.dir=/home/thinker/Android/Sdk
|
sdk.dir=~/Android/Sdk
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user