remade new marks into a FAB

This commit is contained in:
Odweta
2024-12-22 16:16:07 +01:00
parent 49a28b0064
commit da890ea180
6 changed files with 229 additions and 82 deletions
@@ -14,6 +14,8 @@ import androidx.compose.ui.unit.dp
import com.odweta.solon.ui.theme.PastelYellow
import org.json.JSONObject
import java.io.File
import java.time.LocalDate
import java.time.LocalDateTime
enum class Screen {
Main,
@@ -32,8 +34,7 @@ class Setting(auxId: SettingsId, auxName: String, auxChecked: Boolean) {
enum class SettingsId {
Svoboda,
Amoled,
RefreshButton,
TagNewMarks
RefreshButton
}
class SettingsData {
@@ -55,13 +56,7 @@ class SettingsData {
true
)
var tagNewMarks: Setting = Setting(
SettingsId.TagNewMarks,
"Označit nové známky",
true
)
override fun toString() = "$useSvobodaMode\n$useAmoledMode\n$showRefreshButton\n$tagNewMarks"
override fun toString() = "$useSvobodaMode\n$useAmoledMode\n$showRefreshButton"
}
enum class LectureNoteType {
@@ -158,6 +153,7 @@ class Mark {
lateinit var subject: String // subjectId -> parse that
lateinit var date: String // markDate
lateinit var theme: String // theme
var editDate: LocalDateTime = LocalDateTime.now()
override fun toString(): String {
return "mark: ${this.grade} * ${this.weight}, subject: ${this.subject}, description: ${this.theme}, date: ${this.date}"
@@ -187,6 +183,7 @@ class Global {
lateinit var timetableJSON: JSONObject
lateinit var marksJSON: JSONObject
lateinit var marks: MutableMap<String, MutableList<Mark>>
lateinit var newMarks: MutableMap<String, MutableList<Mark>>
lateinit var settings: SettingsData
lateinit var fileDir: File
@@ -1,6 +1,7 @@
package com.odweta.solon
import android.content.Context
import android.util.Log
import androidx.compose.ui.graphics.Color
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
@@ -73,6 +74,7 @@ fun launchContinue(
global.timetable = parsedTimetable
val parsedMarks = Parsing.parseMarks(marks)
global.marks = parsedMarks
global.newMarks = Parsing.parseNewMarks(marks)
// load the settings
val settingsData = Util.fileToString(global.filePaths.settings).toSettingsData()
@@ -20,16 +20,29 @@ import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.AutoAwesome
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.shadow
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Shadow
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.window.Dialog
import androidx.compose.ui.window.DialogProperties
import androidx.compose.ui.zIndex
import com.odweta.solon.ui.theme.PastelGreen
import com.odweta.solon.ui.theme.PastelGreenTransparent
import com.odweta.solon.ui.theme.PastelOrange
@@ -43,6 +56,8 @@ import com.odweta.solon.ui.theme.PastelYellowTransparent
import java.time.LocalDate
import java.time.format.DateTimeFormatter
var showNewMarksDialog by mutableStateOf(false)
enum class MarksDepthLevel {
All,
Subject,
@@ -56,6 +71,106 @@ fun MarksScreen() {
MarksDepthLevel.Subject -> MarksSubject()
MarksDepthLevel.Detail -> MarksDetail()
}
if (showNewMarksDialog) {
val scrollStateNewMarks = rememberScrollState()
Dialog(
onDismissRequest = { showNewMarksDialog = false },
properties = DialogProperties(
dismissOnBackPress = true,
dismissOnClickOutside = true
)
) {
Column(
Modifier.verticalScroll(scrollStateNewMarks).padding(vertical = 10.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
"Nové známky",
color = Color.White,
fontWeight = FontWeight.Bold,
fontSize = 30.sp,
textAlign = TextAlign.Center,
modifier = Modifier.background(
color = Color.Black,
shape = RoundedCornerShape(global.dimens.roundedCorner)
).border(
shape = RoundedCornerShape(global.dimens.roundedCorner),
color = PastelYellow,
width = global.dimens.borderWidth
).padding(10.dp)
)
Spacer(Modifier.height(10.dp))
for ((k, v) in global.newMarks) {
if (v.size > 0) {
Column(
modifier = Modifier
.padding(10.dp)
.border(
shape = RoundedCornerShape(global.dimens.roundedCorner),
color = PastelYellow,
width = global.dimens.borderWidth
)
.background(
Color.Black,
shape = RoundedCornerShape(global.dimens.roundedCorner)
)
.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
k,
color = Color.White,
modifier = Modifier.padding(10.dp),
fontWeight = FontWeight.Bold,
fontSize = 30.sp
)
for (i in v) {
Row(
Modifier.padding(10.dp),
verticalAlignment = Alignment.CenterVertically
) {
Text(
i.theme,
color = Color.White,
modifier = Modifier.padding(end = 5.dp, top = 5.dp)
.weight(1f)
)
Column(
horizontalAlignment = Alignment.End
) {
Text(
i.grade + " * " + i.weight,
color = Color.White,
modifier = Modifier
.background(
color = getAvgColor(i.grade, true),
shape = RoundedCornerShape(global.dimens.roundedCorner)
).padding(5.dp),
style = TextStyle(
shadow = Shadow(
color = Color.Black,
offset = Offset(4f, 4f),
blurRadius = 8f
)
)
)
Text(
i.editDate.format(
DateTimeFormatter.ofPattern("dd. MM. yyyy")
),
color = Color.White
)
}
}
HorizontalLine()
}
}
}
}
}
}
}
}
private fun getAvgColor(avg: String, isBorder: Boolean = false): Color {
@@ -112,7 +227,10 @@ fun MarksAll() {
.fillMaxHeight()
.border(
width = global.dimens.borderWidth,
color = getAvgColor(Util.avg(markList), true), // decide on the color (transparent)
color = getAvgColor(
Util.avg(markList),
true
), // decide on the color (transparent)
shape = RoundedCornerShape(global.dimens.roundedCorner)
)
} else {
@@ -131,7 +249,10 @@ fun MarksAll() {
.height(70.dp)
.border(
width = global.dimens.borderWidth,
color = getAvgColor(Util.avg(markList), true), // decide on the color (transparent)
color = getAvgColor(
Util.avg(markList),
true
), // decide on the color (transparent)
shape = RoundedCornerShape(global.dimens.roundedCorner)
)
.clickable {
@@ -176,16 +297,6 @@ fun MarksAll() {
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(
modifier = amoledModifierBackground
) {
@@ -224,18 +335,11 @@ fun MarksAll() {
}
Box(
modifier = Modifier.fillMaxSize().weight(1f),
modifier = Modifier
.fillMaxSize()
.weight(1f),
contentAlignment = Alignment.TopStart
) {
if (subjectContainsNewMark && settings.tagNewMarks.checked.value) {
Icon(
modifier = Modifier.padding(start = 4.dp, top = 4.dp),
imageVector = Icons.Default.AutoAwesome,
contentDescription = "New marks in subject",
tint = Color.White // You can customize the icon color
)
}
Box(
modifier = Modifier
.fillMaxSize()
@@ -251,6 +355,27 @@ fun MarksAll() {
}
}
}
Spacer(Modifier.height(80.dp))
}
Box(Modifier.fillMaxSize()) {
FloatingActionButton(
onClick = { showNewMarksDialog = true },
modifier = Modifier
.align(Alignment.BottomEnd)
.padding(10.dp)
.background(Color.Black, shape = RoundedCornerShape(global.dimens.roundedCorner)),
containerColor = Color.Black,
contentColor = PastelYellow
) {
Icon(
modifier = Modifier.padding(start = 4.dp, top = 4.dp),
imageVector = Icons.Default.AutoAwesome,
contentDescription = "New marks in subject",
tint = PastelYellow // You can customize the icon color
)
}
}
}
@@ -287,7 +412,8 @@ fun MarksSubject() {
),
shape = RoundedCornerShape(global.dimens.roundedCorner)
)
.background(color = if (settings.useAmoledMode.checked.value) {
.background(
color = if (settings.useAmoledMode.checked.value) {
Color.Black
} else {
getAvgColor(
@@ -327,7 +453,8 @@ fun MarksSubject() {
color = PastelYellow,
shape = RoundedCornerShape(global.dimens.roundedCorner)
)
.background(color = if (settings.useAmoledMode.checked.value) {
.background(
color = if (settings.useAmoledMode.checked.value) {
Color.Black
} else {
PastelYellowTransparent
@@ -353,11 +480,12 @@ fun MarksSubject() {
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 5.dp)
.background(color = if (settings.useAmoledMode.checked.value) {
Color.Black
} else {
getAvgColor(mark.grade)
},
.background(
color = if (settings.useAmoledMode.checked.value) {
Color.Black
} else {
getAvgColor(mark.grade)
},
shape = RoundedCornerShape(global.dimens.roundedCorner)
)
.padding(vertical = 10.dp)
@@ -392,20 +520,6 @@ fun MarksSubject() {
) // theme
}
}
// only add if mark date is not older than one week
if ((LocalDate
.parse(mark.date, DateTimeFormatter.ISO_LOCAL_DATE_TIME)
.isAfter(LocalDate.now().minusWeeks(1))
) && settings.tagNewMarks.checked.value
) {
Icon(
modifier = Modifier.padding(start = 7.dp, top = 4.dp),
imageVector = Icons.Default.AutoAwesome,
contentDescription = "A new mark",
tint = Color.White // You can customize the icon color
)
}
}
}
}
@@ -2,7 +2,9 @@ package com.odweta.solon
import android.util.Log
import org.json.JSONObject
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.LocalTime
import java.time.format.DateTimeFormatter
class Parsing {
@@ -324,9 +326,8 @@ class Parsing {
return timetable
}
fun parseMarks(jsonString: JSONObject): MutableMap<String, MutableList<Mark>> {
fun parseMarks(json: JSONObject): MutableMap<String, MutableList<Mark>> {
// no marks
val json = jsonString
if (json.has("marks") && json.getJSONArray("marks").length() == 0) {
val noMarks = mutableMapOf<String, MutableList<Mark>>()
val list = mutableListOf<Mark>()
@@ -340,9 +341,9 @@ class Parsing {
val marksList = mutableListOf<JSONObject>()
val marksJSONArray = jsonString.getJSONArray("marks")
val marksJSONArray = json.getJSONArray("marks")
val subjectsJSONArray = jsonString.getJSONArray("subjects")
val subjectsJSONArray = json.getJSONArray("subjects")
val subjectMap = mutableMapOf<String, String>()
for (i in 0..<subjectsJSONArray.length()) {
@@ -361,16 +362,6 @@ class Parsing {
marks[subj] = mutableListOf()
}
/*
* class Mark {
* lateinit var grade: String // markText
* lateinit var weight: String // weight
* lateinit var subject: String // subjectId -> parse that
* lateinit var date: String // markDate
* lateinit var theme: String // theme
* }
*/
for (markJSON in marksList) {
val mark = Mark()
mark.grade = markJSON.getString("markText")
@@ -384,6 +375,57 @@ class Parsing {
return marks
}
fun parseNewMarks(json: JSONObject): MutableMap<String, MutableList<Mark>> {
// no marks
if (json.has("marks") && json.getJSONArray("marks").length() == 0) {
val noMarks = mutableMapOf<String, MutableList<Mark>>()
val list = mutableListOf<Mark>()
list.add(Mark().none())
noMarks["-"] = list
return noMarks
}
// [subject] = (<editDate>, <mark>)
val marks = mutableMapOf<String, MutableList<Mark>>()
val marksList = mutableListOf<JSONObject>()
val marksJSONArray = json.getJSONArray("marks")
val subjectsJSONArray = json.getJSONArray("subjects")
val subjectMap = mutableMapOf<String, String>()
for (i in 0..<subjectsJSONArray.length()) {
val subj = subjectsJSONArray.getJSONObject(i)
subjectMap[subj.getString("id")] = subj.getString("abbrev")
// map names to abbrevs
global.subjectNameMap[subj.getString("abbrev")] = subj.getString("name")
}
for (i in 0..<marksJSONArray.length()) {
marksList.add(marksJSONArray.getJSONObject(i))
}
for (subj in subjectMap.values) {
marks[subj] = mutableListOf()
}
for (markJSON in marksList) {
val mark = Mark()
mark.grade = markJSON.getString("markText")
mark.weight = markJSON.getString("weight")
mark.subject = subjectMap[markJSON.getString("subjectId")].toString()
mark.date = markJSON.getString("markDate")
mark.theme = markJSON.getString("theme")
mark.editDate = LocalDateTime.parse(markJSON.getString("editDate"), DateTimeFormatter.ISO_LOCAL_DATE_TIME)
if (isTimeBetweenD(mark.editDate, LocalDateTime.now().minusWeeks(1), LocalDateTime.now())) marks[mark.subject]?.add(mark)
}
return marks
}
fun getStudentClass(): String {
return if (!userIsParent()) {
global.userData
@@ -2,8 +2,6 @@ package com.odweta.solon
import androidx.activity.compose.BackHandler
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
@@ -11,16 +9,9 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBackIosNew
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.Switch
import androidx.compose.material3.SwitchColors
import androidx.compose.material3.Text
@@ -58,10 +49,6 @@ fun SettingsScreen() {
Spacer(Modifier.height(10.dp))
SettingsTableRow(settings.showRefreshButton)
Spacer(Modifier.height(10.dp))
SettingsTableRow(settings.tagNewMarks)
}
}
@@ -91,7 +78,6 @@ fun SettingsTableRow(setting: Setting) {
SettingsId.Svoboda -> settings.useSvobodaMode = setting
SettingsId.Amoled -> settings.useAmoledMode = setting
SettingsId.RefreshButton -> settings.showRefreshButton = setting
SettingsId.TagNewMarks -> settings.tagNewMarks = setting
else -> {}
}
Util.saveStringToFile(global.filePaths.settings, settings.toString())
@@ -1,6 +1,7 @@
package com.odweta.solon
import android.annotation.SuppressLint
import android.util.Log
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
@@ -66,6 +67,7 @@ import com.odweta.solon.ui.theme.PastelYellowTransparent
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.LocalTime
import java.time.format.DateTimeFormatter
@@ -255,8 +257,12 @@ private fun getSubjectColor(s: Subject, transparent: Boolean): Color {
}
}
}
fun isTimeBetweenT(givenTime: LocalTime, startTime: LocalTime, endTime: LocalTime): Boolean {
// Check if the given time is between startTime and endTime
return givenTime.isAfter(startTime) && givenTime.isBefore(endTime)
}
fun isTimeBetween(givenTime: LocalTime, startTime: LocalTime, endTime: LocalTime): Boolean {
fun isTimeBetweenD(givenTime: LocalDateTime, startTime: LocalDateTime, endTime: LocalDateTime): Boolean {
// Check if the given time is between startTime and endTime
return givenTime.isAfter(startTime) && givenTime.isBefore(endTime)
}
@@ -283,7 +289,7 @@ fun subjectModifier(d: Day, s: Subject, lectureNumber: Int): Modifier {
val todayDate = LocalDate.now()
val now = LocalTime.now()
if (dateParsed == todayDate && isTimeBetween(now, startTimeParsed, endTimeParsed)) {
if (dateParsed == todayDate && isTimeBetweenT(now, startTimeParsed, endTimeParsed)) {
global.currentLectureNumber = lectureNumber
}