From da890ea1801095de52dc6c9f1467bcb7d795ce14 Mon Sep 17 00:00:00 2001 From: Odweta Date: Sun, 22 Dec 2024 16:16:07 +0100 Subject: [PATCH] remade new marks into a FAB --- .../src/main/java/com/odweta/solon/Global.kt | 15 +- .../src/main/java/com/odweta/solon/Launch.kt | 2 + .../src/main/java/com/odweta/solon/Marks.kt | 200 ++++++++++++++---- .../src/main/java/com/odweta/solon/Parsing.kt | 70 ++++-- .../main/java/com/odweta/solon/Settings.kt | 14 -- .../main/java/com/odweta/solon/Timetable.kt | 10 +- 6 files changed, 229 insertions(+), 82 deletions(-) diff --git a/mobile/app/src/main/java/com/odweta/solon/Global.kt b/mobile/app/src/main/java/com/odweta/solon/Global.kt index ef69b0a..e4e8dc3 100644 --- a/mobile/app/src/main/java/com/odweta/solon/Global.kt +++ b/mobile/app/src/main/java/com/odweta/solon/Global.kt @@ -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> + lateinit var newMarks: MutableMap> lateinit var settings: SettingsData lateinit var fileDir: File diff --git a/mobile/app/src/main/java/com/odweta/solon/Launch.kt b/mobile/app/src/main/java/com/odweta/solon/Launch.kt index 2929f22..f0671d5 100644 --- a/mobile/app/src/main/java/com/odweta/solon/Launch.kt +++ b/mobile/app/src/main/java/com/odweta/solon/Launch.kt @@ -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() diff --git a/mobile/app/src/main/java/com/odweta/solon/Marks.kt b/mobile/app/src/main/java/com/odweta/solon/Marks.kt index d5e57e4..27fb11c 100644 --- a/mobile/app/src/main/java/com/odweta/solon/Marks.kt +++ b/mobile/app/src/main/java/com/odweta/solon/Marks.kt @@ -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 - ) - } } } } diff --git a/mobile/app/src/main/java/com/odweta/solon/Parsing.kt b/mobile/app/src/main/java/com/odweta/solon/Parsing.kt index 400d1dd..9af49e8 100644 --- a/mobile/app/src/main/java/com/odweta/solon/Parsing.kt +++ b/mobile/app/src/main/java/com/odweta/solon/Parsing.kt @@ -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> { + fun parseMarks(json: JSONObject): MutableMap> { // no marks - val json = jsonString if (json.has("marks") && json.getJSONArray("marks").length() == 0) { val noMarks = mutableMapOf>() val list = mutableListOf() @@ -340,9 +341,9 @@ class Parsing { val marksList = mutableListOf() - val marksJSONArray = jsonString.getJSONArray("marks") + val marksJSONArray = json.getJSONArray("marks") - val subjectsJSONArray = jsonString.getJSONArray("subjects") + val subjectsJSONArray = json.getJSONArray("subjects") val subjectMap = mutableMapOf() for (i in 0.. 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> { + // no marks + if (json.has("marks") && json.getJSONArray("marks").length() == 0) { + val noMarks = mutableMapOf>() + val list = mutableListOf() + list.add(Mark().none()) + noMarks["-"] = list + + return noMarks + } + + // [subject] = (, ) + val marks = mutableMapOf>() + + val marksList = mutableListOf() + + val marksJSONArray = json.getJSONArray("marks") + + val subjectsJSONArray = json.getJSONArray("subjects") + val subjectMap = mutableMapOf() + + for (i in 0.. 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()) diff --git a/mobile/app/src/main/java/com/odweta/solon/Timetable.kt b/mobile/app/src/main/java/com/odweta/solon/Timetable.kt index c4c7571..47c4b8c 100644 --- a/mobile/app/src/main/java/com/odweta/solon/Timetable.kt +++ b/mobile/app/src/main/java/com/odweta/solon/Timetable.kt @@ -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 }