6 Commits
10 changed files with 609 additions and 61 deletions
+1 -1
View File
@@ -1,3 +1,3 @@
![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/-/raw/master/release/com.odweta.solon_2.2.apk?ref_type=heads&inline=false) (verze 2.2) # 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)
+329
View File
@@ -0,0 +1,329 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DeviceStreaming">
<option name="deviceSelectionList">
<list>
<PersistentDeviceSelectionData>
<option name="api" value="27" />
<option name="brand" value="DOCOMO" />
<option name="codename" value="F01L" />
<option name="id" value="F01L" />
<option name="manufacturer" value="FUJITSU" />
<option name="name" value="F-01L" />
<option name="screenDensity" value="360" />
<option name="screenX" value="720" />
<option name="screenY" value="1280" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="28" />
<option name="brand" value="DOCOMO" />
<option name="codename" value="SH-01L" />
<option name="id" value="SH-01L" />
<option name="manufacturer" value="SHARP" />
<option name="name" value="AQUOS sense2 SH-01L" />
<option name="screenDensity" value="480" />
<option name="screenX" value="1080" />
<option name="screenY" value="2160" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="Lenovo" />
<option name="codename" value="TB370FU" />
<option name="id" value="TB370FU" />
<option name="manufacturer" value="Lenovo" />
<option name="name" value="Tab P12" />
<option name="screenDensity" value="340" />
<option name="screenX" value="1840" />
<option name="screenY" value="2944" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="31" />
<option name="brand" value="samsung" />
<option name="codename" value="a51" />
<option name="id" value="a51" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy A51" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1080" />
<option name="screenY" value="2400" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="google" />
<option name="codename" value="akita" />
<option name="id" value="akita" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 8a" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1080" />
<option name="screenY" value="2400" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="33" />
<option name="brand" value="samsung" />
<option name="codename" value="b0q" />
<option name="id" value="b0q" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy S22 Ultra" />
<option name="screenDensity" value="600" />
<option name="screenX" value="1440" />
<option name="screenY" value="3088" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="32" />
<option name="brand" value="google" />
<option name="codename" value="bluejay" />
<option name="id" value="bluejay" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 6a" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1080" />
<option name="screenY" value="2400" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="google" />
<option name="codename" value="caiman" />
<option name="id" value="caiman" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 9 Pro" />
<option name="screenDensity" value="360" />
<option name="screenX" value="960" />
<option name="screenY" value="2142" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="google" />
<option name="codename" value="comet" />
<option name="id" value="comet" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 9 Pro Fold" />
<option name="screenDensity" value="390" />
<option name="screenX" value="2076" />
<option name="screenY" value="2152" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="29" />
<option name="brand" value="samsung" />
<option name="codename" value="crownqlteue" />
<option name="id" value="crownqlteue" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy Note9" />
<option name="screenDensity" value="420" />
<option name="screenX" value="2220" />
<option name="screenY" value="1080" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="samsung" />
<option name="codename" value="dm3q" />
<option name="id" value="dm3q" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy S23 Ultra" />
<option name="screenDensity" value="600" />
<option name="screenX" value="1440" />
<option name="screenY" value="3088" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="samsung" />
<option name="codename" value="e1q" />
<option name="id" value="e1q" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy S24" />
<option name="screenDensity" value="480" />
<option name="screenX" value="1080" />
<option name="screenY" value="2340" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="33" />
<option name="brand" value="google" />
<option name="codename" value="felix" />
<option name="id" value="felix" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel Fold" />
<option name="screenDensity" value="420" />
<option name="screenX" value="2208" />
<option name="screenY" value="1840" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="google" />
<option name="codename" value="felix" />
<option name="id" value="felix" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel Fold" />
<option name="screenDensity" value="420" />
<option name="screenX" value="2208" />
<option name="screenY" value="1840" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="33" />
<option name="brand" value="google" />
<option name="codename" value="felix_camera" />
<option name="id" value="felix_camera" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel Fold (Camera-enabled)" />
<option name="screenDensity" value="420" />
<option name="screenX" value="2208" />
<option name="screenY" value="1840" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="33" />
<option name="brand" value="samsung" />
<option name="codename" value="gts8uwifi" />
<option name="id" value="gts8uwifi" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy Tab S8 Ultra" />
<option name="screenDensity" value="320" />
<option name="screenX" value="1848" />
<option name="screenY" value="2960" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="google" />
<option name="codename" value="husky" />
<option name="id" value="husky" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 8 Pro" />
<option name="screenDensity" value="390" />
<option name="screenX" value="1008" />
<option name="screenY" value="2244" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="30" />
<option name="brand" value="motorola" />
<option name="codename" value="java" />
<option name="id" value="java" />
<option name="manufacturer" value="Motorola" />
<option name="name" value="G20" />
<option name="screenDensity" value="280" />
<option name="screenX" value="720" />
<option name="screenY" value="1600" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="google" />
<option name="codename" value="komodo" />
<option name="id" value="komodo" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 9 Pro XL" />
<option name="screenDensity" value="360" />
<option name="screenX" value="1008" />
<option name="screenY" value="2244" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="33" />
<option name="brand" value="google" />
<option name="codename" value="lynx" />
<option name="id" value="lynx" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 7a" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1080" />
<option name="screenY" value="2400" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="31" />
<option name="brand" value="google" />
<option name="codename" value="oriole" />
<option name="id" value="oriole" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 6" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1080" />
<option name="screenY" value="2400" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="33" />
<option name="brand" value="google" />
<option name="codename" value="panther" />
<option name="id" value="panther" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 7" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1080" />
<option name="screenY" value="2400" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="samsung" />
<option name="codename" value="q5q" />
<option name="id" value="q5q" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy Z Fold5" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1812" />
<option name="screenY" value="2176" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="samsung" />
<option name="codename" value="q6q" />
<option name="id" value="q6q" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy Z Fold6" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1856" />
<option name="screenY" value="2160" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="30" />
<option name="brand" value="google" />
<option name="codename" value="r11" />
<option name="id" value="r11" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel Watch" />
<option name="screenDensity" value="320" />
<option name="screenX" value="384" />
<option name="screenY" value="384" />
<option name="type" value="WEAR_OS" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="30" />
<option name="brand" value="google" />
<option name="codename" value="redfin" />
<option name="id" value="redfin" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 5" />
<option name="screenDensity" value="440" />
<option name="screenX" value="1080" />
<option name="screenY" value="2340" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="google" />
<option name="codename" value="shiba" />
<option name="id" value="shiba" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 8" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1080" />
<option name="screenY" value="2400" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="33" />
<option name="brand" value="google" />
<option name="codename" value="tangorpro" />
<option name="id" value="tangorpro" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel Tablet" />
<option name="screenDensity" value="320" />
<option name="screenX" value="1600" />
<option name="screenY" value="2560" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="google" />
<option name="codename" value="tokay" />
<option name="id" value="tokay" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 9" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1080" />
<option name="screenY" value="2424" />
</PersistentDeviceSelectionData>
</list>
</option>
</component>
</project>
+2 -2
View File
@@ -12,8 +12,8 @@ android {
applicationId = "com.odweta.solon" applicationId = "com.odweta.solon"
minSdk = 28 minSdk = 28
targetSdk = 34 targetSdk = 34
versionCode = 205 versionCode = 206
versionName = "2.2" 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
@@ -86,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 {
@@ -108,7 +111,13 @@ 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()
@@ -138,7 +147,48 @@ var resetNav: Boolean = false
var isAPISetUp: Boolean = false var isAPISetUp: Boolean = false
var lectureNotes: HashMap<Int, MutableState<String>> = hashMapOf() 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 selectedLecture: Int = 0
var selectedDay: Int = 0 var selectedDay: Int = 0
@@ -237,7 +237,7 @@ fun MarksAll() {
modifier = Modifier.fillMaxSize().weight(1f), modifier = Modifier.fillMaxSize().weight(1f),
contentAlignment = Alignment.TopStart contentAlignment = Alignment.TopStart
) { ) {
if (subjectContainsNewMark) { if (subjectContainsNewMark && settings.tagNewMarks.checked.value) {
Icon( Icon(
modifier = Modifier.padding(start = 4.dp, top = 4.dp), modifier = Modifier.padding(start = 4.dp, top = 4.dp),
imageVector = Icons.Default.AutoAwesome, imageVector = Icons.Default.AutoAwesome,
@@ -368,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))
@@ -428,7 +428,11 @@ fun MarksSubject() {
} }
// only add if mark date is not older than one week // 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))) { if ((LocalDate
.parse(mark.date, DateTimeFormatter.ISO_LOCAL_DATE_TIME)
.isAfter(LocalDate.now().minusWeeks(1))
) && settings.tagNewMarks.checked.value
) {
Icon( Icon(
modifier = Modifier.padding(start = 7.dp, top = 4.dp), modifier = Modifier.padding(start = 7.dp, top = 4.dp),
imageVector = Icons.Default.AutoAwesome, imageVector = Icons.Default.AutoAwesome,
@@ -472,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
) )
@@ -493,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)
@@ -505,7 +509,7 @@ fun MarksDetail() {
Color.Black Color.Black
} else { } else {
getAvgColor( getAvgColor(
Util.avg(marks[subjectToShow]!!) Util.avg(mutableListOf(markToShow))
) )
} }
) )
@@ -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())
}, },
@@ -1,22 +1,21 @@
package com.odweta.solon package com.odweta.solon
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.util.Log
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.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight
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
@@ -24,28 +23,39 @@ 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.text.selection.TextSelectionColors
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.AlertDialog import androidx.compose.material.icons.Icons
import androidx.compose.material3.BasicAlertDialog import androidx.compose.material.icons.filled.AutoAwesome
import androidx.compose.material.icons.filled.EditNote
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonColors
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TextField import androidx.compose.material3.TextField
import androidx.compose.material3.TextFieldColors
import androidx.compose.material3.TextFieldDefaults import androidx.compose.material3.TextFieldDefaults
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue 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.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.Dialog
import androidx.compose.ui.window.DialogProperties import androidx.compose.ui.window.DialogProperties
import androidx.compose.ui.window.PopupProperties
import androidx.compose.ui.zIndex 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
@@ -53,11 +63,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 java.security.MessageDigest import kotlinx.coroutines.delay
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
import kotlin.math.abs
var showDetailDialog = mutableStateOf(false) var showDetailDialog = mutableStateOf(false)
@@ -78,7 +88,7 @@ fun TimetableScreen() {
@SuppressLint("UnrememberedMutableState") @SuppressLint("UnrememberedMutableState")
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun DetailDialog(modifier: Modifier = Modifier) { fun DetailDialog() {
Dialog( Dialog(
onDismissRequest = { showDetailDialog.value = false }, // Close the dialog on dismiss onDismissRequest = { showDetailDialog.value = false }, // Close the dialog on dismiss
properties = DialogProperties( properties = DialogProperties(
@@ -95,29 +105,131 @@ fun DetailDialog(modifier: Modifier = Modifier) {
shape = RoundedCornerShape(roundedCornerDimen) shape = RoundedCornerShape(roundedCornerDimen)
) )
) { ) {
if (lectureNotes[selectedLecture] == null) { Column(
lectureNotes[selectedLecture] = mutableStateOf("") horizontalAlignment = Alignment.CenterHorizontally
} ) {
Text(
TextField( text = "" +
value = lectureNotes[selectedLecture]!!.value, lectureNotes[selectedLecture]?.value?.number?.value.toString() +
onValueChange = { newText: String -> " " +
lectureNotes[selectedLecture]!!.value = newText lectureNotes[selectedLecture]?.value?.lectureName?.value.toString(),
Util.saveLectureIds() color = Color.White,
}, textAlign = TextAlign.Left
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
) )
)
///////////////////////////////////////////////////////////
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ě.") }, // &nbsp;
colors = TextFieldDefaults.textFieldColors(
focusedTextColor = Color.White,
containerColor = Color.Black,
selectionColors = TextSelectionColors(
handleColor = PastelYellow,
backgroundColor = PastelYellowTransparent
),
cursorColor = PastelYellow,
focusedIndicatorColor = PastelYellow,
unfocusedIndicatorColor = PastelYellowTransparent
)
)
}
} }
} }
) )
@@ -125,7 +237,7 @@ fun DetailDialog(modifier: Modifier = Modifier) {
@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,
@@ -218,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()
@@ -250,6 +363,17 @@ private fun DayScreen(day: Day) {
) { ) {
for ((subjectIndex, subject) in day.subjects.withIndex()) { for ((subjectIndex, subject) in day.subjects.withIndex()) {
val lectureId = Util.getLectureId(day.date, subjectIndex) 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)
@@ -291,7 +415,10 @@ private fun DayScreen(day: Day) {
} }
} }
Box (modifier = subjectModifier(day, subject, subject.number.toInt())) { Box (
modifier = subjectModifier(day, subject, subject.number.toInt()),
contentAlignment = Alignment.TopStart
) {
Row { Row {
if (subject.substitute != "2") { if (subject.substitute != "2") {
Box( Box(
@@ -424,7 +551,21 @@ private fun DayScreen(day: Day) {
.clickable { .clickable {
selectedLecture = lectureId selectedLecture = lectureId
showDetailDialog.value = true 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
)
}
} }
} }
} }
@@ -9,6 +9,7 @@ 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.MutableState
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf 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
@@ -268,29 +269,46 @@ class Util {
}) })
} }
fun csvToHashMap(filePath: String): HashMap<Int, MutableState<String>> { fun csvToHashMap(filePath: String): HashMap<Int, MutableState<LectureNote>> {
val hashMap = HashMap<Int, MutableState<String>>() val hashMap = HashMap<Int, MutableState<LectureNote>>()
val lines = fileToString(filePath).lines() val lines = fileToString(filePath).lines()
for (line in lines) { for (line in lines) {
if (line.isBlank()) continue if (line.isBlank()) continue
val parts = line.split(",") val parts = line.split(",")
if (parts.size == 2) { if (parts.size == 5) {
val key = parts[0].trim().toInt() val id = parts[0].trim().toInt()
val value = parts[1].trim() val note = parts[1].trim()
hashMap[key] = mutableStateOf("") val type = parts[2].trim().toLectureNoteType()
hashMap[key]!!.value = value 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 return hashMap
} }
fun hashMapToCsv(hashMap: HashMap<Int, MutableState<String>>): String { fun hashMapToCsv(hashMap: HashMap<Int, MutableState<LectureNote>>): String {
var result = "" var result = ""
for ((key, value) in hashMap) { for ((key, lectureNote) in hashMap) {
result += "$key,${value.value}\n" result +=
"$key," +
"${lectureNote.value.note.value}," +
"${lectureNote.value.type.value}," +
"${lectureNote.value.number.value}," +
lectureNote.value.lectureName.value +
"\n"
} }
return result return result
} }
Binary file not shown.
Binary file not shown.