Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bda937095c | ||
|
|
67392ccb3d | ||
|
|
a163d6b285 | ||
|
|
e67f87864c | ||
|
|
8e9693bfe6 | ||
|
|
c6646e554f | ||
|
|
98b6b72e81 | ||
|
|
c6a5c50a7d | ||
|
|
09bddaac3c | ||
|
|
bb39f10a0b | ||
|
|
7e44cb585b | ||
|
|
91ba977a86 | ||
|
|
5d9b70f3a1 | ||
|
|
75a766ca7d | ||
|
|
23607f93b3 | ||
|
|
887c7d58b5 | ||
|
|
4d96707a51 | ||
|
|
5a98379d3f | ||
|
|
80e5581f45 | ||
|
|
5200e3ba07 | ||
|
|
f67e28b8f6 | ||
|
|
597971288e | ||
|
|
0a4ea395fd | ||
|
|
509f7f33a7 | ||
|
|
87470effcd | ||
|
|
079872dae2 | ||
|
|
26317052cc | ||
|
|
ed981f89de | ||
|
|
fd788195c5 | ||
|
|
ed1f67f3e6 | ||
|
|
980e51e8f1 | ||
|
|
ebfc3c1c23 | ||
|
|
07716e1ae6 | ||
|
|
1049401429 | ||
|
|
83a825f4b7 | ||
|
|
66dc2338fb | ||
|
|
7c585709ed | ||
|
|
f448420e03 | ||
|
|
ec989d6ae0 | ||
|
|
db91df4d22 | ||
|
|
e020ae5f17 | ||
|
|
d3197111c3 | ||
|
|
8a4956e6c6 |
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="deploymentTargetSelector">
|
||||||
|
<selectionStates>
|
||||||
|
<SelectionState runConfigName="app">
|
||||||
|
<option name="selectionMode" value="DROPDOWN" />
|
||||||
|
</SelectionState>
|
||||||
|
</selectionStates>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="MaterialThemeProjectNewConfig">
|
||||||
|
<option name="metadata">
|
||||||
|
<MTProjectMetadataState>
|
||||||
|
<option name="migrated" value="true" />
|
||||||
|
<option name="pristineConfig" value="false" />
|
||||||
|
<option name="userId" value="-239e49af:192a4be9597:-7ffe" />
|
||||||
|
</MTProjectMetadataState>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="RunConfigurationProducerService">
|
||||||
|
<option name="ignoredProducers">
|
||||||
|
<set>
|
||||||
|
<option value="com.intellij.execution.junit.AbstractAllInDirectoryConfigurationProducer" />
|
||||||
|
<option value="com.intellij.execution.junit.AllInPackageConfigurationProducer" />
|
||||||
|
<option value="com.intellij.execution.junit.PatternConfigurationProducer" />
|
||||||
|
<option value="com.intellij.execution.junit.TestInClassConfigurationProducer" />
|
||||||
|
<option value="com.intellij.execution.junit.UniqueIdConfigurationProducer" />
|
||||||
|
<option value="com.intellij.execution.junit.testDiscovery.JUnitTestDiscoveryConfigurationProducer" />
|
||||||
|
<option value="org.jetbrains.kotlin.idea.junit.KotlinJUnitRunConfigurationProducer" />
|
||||||
|
<option value="org.jetbrains.kotlin.idea.junit.KotlinPatternConfigurationProducer" />
|
||||||
|
</set>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
@@ -2,7 +2,5 @@
|
|||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="VcsDirectoryMappings">
|
<component name="VcsDirectoryMappings">
|
||||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||||
<mapping directory="$PROJECT_DIR$/help" vcs="Git" />
|
|
||||||
<mapping directory="$PROJECT_DIR$/mobile/help" vcs="Git" />
|
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
@@ -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/solon.apk?ref_type=heads&inline=false) (verze 2.0)
|
# 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)
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
Optimalizovana a zbavena nesmyslu verze skolniho online systemu SkolaOnLine
|
||||||
|
After Width: | Height: | Size: 88 KiB |
|
After Width: | Height: | Size: 70 KiB |
@@ -0,0 +1 @@
|
|||||||
|
Odlehcena verze aplikace SkolaOnLine
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Solon
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
A more optimized and debloated version of the SkolaOnLine online school system
|
||||||
|
After Width: | Height: | Size: 15 KiB |
@@ -0,0 +1 @@
|
|||||||
|
A light-weight Android frontend to SkolaOnLine
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Solon
|
||||||
@@ -62,6 +62,18 @@
|
|||||||
<PersistentState>
|
<PersistentState>
|
||||||
<option name="children">
|
<option name="children">
|
||||||
<map>
|
<map>
|
||||||
|
<entry key="backgroundImage">
|
||||||
|
<value>
|
||||||
|
<PersistentState>
|
||||||
|
<option name="values">
|
||||||
|
<map>
|
||||||
|
<entry key="imagePath" value="$PROJECT_DIR$/app/src/main/res/drawable/black.png" />
|
||||||
|
<entry key="scalingPercent" value="172" />
|
||||||
|
</map>
|
||||||
|
</option>
|
||||||
|
</PersistentState>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
<entry key="foregroundClipArt">
|
<entry key="foregroundClipArt">
|
||||||
<value>
|
<value>
|
||||||
<PersistentState>
|
<PersistentState>
|
||||||
|
|||||||
@@ -4,16 +4,19 @@
|
|||||||
<selectionStates>
|
<selectionStates>
|
||||||
<SelectionState runConfigName="app">
|
<SelectionState runConfigName="app">
|
||||||
<option name="selectionMode" value="DROPDOWN" />
|
<option name="selectionMode" value="DROPDOWN" />
|
||||||
<DropdownSelection timestamp="2024-10-20T07:27:51.115175643Z">
|
<DropdownSelection timestamp="2024-11-29T17:18:42.354545820Z">
|
||||||
<Target type="DEFAULT_BOOT">
|
<Target type="DEFAULT_BOOT">
|
||||||
<handle>
|
<handle>
|
||||||
<DeviceId pluginId="LocalEmulator" identifier="path=/home/thinker/.android/avd/Motorola_Moto_e22_API_31.avd" />
|
<DeviceId pluginId="LocalEmulator" identifier="path=/home/thinker/.config/.android/avd/Medium_Phone_API_35.avd" />
|
||||||
</handle>
|
</handle>
|
||||||
</Target>
|
</Target>
|
||||||
</DropdownSelection>
|
</DropdownSelection>
|
||||||
<DialogSelection />
|
<DialogSelection />
|
||||||
</SelectionState>
|
</SelectionState>
|
||||||
<SelectionState runConfigName="DefaultPreview">
|
<SelectionState runConfigName="TimetablePreview">
|
||||||
|
<option name="selectionMode" value="DROPDOWN" />
|
||||||
|
</SelectionState>
|
||||||
|
<SelectionState runConfigName="RBPreview">
|
||||||
<option name="selectionMode" value="DROPDOWN" />
|
<option name="selectionMode" value="DROPDOWN" />
|
||||||
</SelectionState>
|
</SelectionState>
|
||||||
</selectionStates>
|
</selectionStates>
|
||||||
|
|||||||
@@ -3,15 +3,19 @@
|
|||||||
<option name="myName" value="Project Default" />
|
<option name="myName" value="Project Default" />
|
||||||
<inspection_tool class="ComposePreviewDimensionRespectsLimit" enabled="true" level="WARNING" enabled_by_default="true">
|
<inspection_tool class="ComposePreviewDimensionRespectsLimit" enabled="true" level="WARNING" enabled_by_default="true">
|
||||||
<option name="composableFile" value="true" />
|
<option name="composableFile" value="true" />
|
||||||
|
<option name="previewFile" value="true" />
|
||||||
</inspection_tool>
|
</inspection_tool>
|
||||||
<inspection_tool class="ComposePreviewMustBeTopLevelFunction" enabled="true" level="ERROR" enabled_by_default="true">
|
<inspection_tool class="ComposePreviewMustBeTopLevelFunction" enabled="true" level="ERROR" enabled_by_default="true">
|
||||||
<option name="composableFile" value="true" />
|
<option name="composableFile" value="true" />
|
||||||
|
<option name="previewFile" value="true" />
|
||||||
</inspection_tool>
|
</inspection_tool>
|
||||||
<inspection_tool class="ComposePreviewNeedsComposableAnnotation" enabled="true" level="ERROR" enabled_by_default="true">
|
<inspection_tool class="ComposePreviewNeedsComposableAnnotation" enabled="true" level="ERROR" enabled_by_default="true">
|
||||||
<option name="composableFile" value="true" />
|
<option name="composableFile" value="true" />
|
||||||
|
<option name="previewFile" value="true" />
|
||||||
</inspection_tool>
|
</inspection_tool>
|
||||||
<inspection_tool class="ComposePreviewNotSupportedInUnitTestFiles" enabled="true" level="ERROR" enabled_by_default="true">
|
<inspection_tool class="ComposePreviewNotSupportedInUnitTestFiles" enabled="true" level="ERROR" enabled_by_default="true">
|
||||||
<option name="composableFile" value="true" />
|
<option name="composableFile" value="true" />
|
||||||
|
<option name="previewFile" value="true" />
|
||||||
</inspection_tool>
|
</inspection_tool>
|
||||||
<inspection_tool class="GlancePreviewDimensionRespectsLimit" enabled="true" level="WARNING" enabled_by_default="true">
|
<inspection_tool class="GlancePreviewDimensionRespectsLimit" enabled="true" level="WARNING" enabled_by_default="true">
|
||||||
<option name="composableFile" value="true" />
|
<option name="composableFile" value="true" />
|
||||||
@@ -27,21 +31,27 @@
|
|||||||
</inspection_tool>
|
</inspection_tool>
|
||||||
<inspection_tool class="PreviewAnnotationInFunctionWithParameters" enabled="true" level="ERROR" enabled_by_default="true">
|
<inspection_tool class="PreviewAnnotationInFunctionWithParameters" enabled="true" level="ERROR" enabled_by_default="true">
|
||||||
<option name="composableFile" value="true" />
|
<option name="composableFile" value="true" />
|
||||||
|
<option name="previewFile" value="true" />
|
||||||
</inspection_tool>
|
</inspection_tool>
|
||||||
<inspection_tool class="PreviewApiLevelMustBeValid" enabled="true" level="ERROR" enabled_by_default="true">
|
<inspection_tool class="PreviewApiLevelMustBeValid" enabled="true" level="ERROR" enabled_by_default="true">
|
||||||
<option name="composableFile" value="true" />
|
<option name="composableFile" value="true" />
|
||||||
|
<option name="previewFile" value="true" />
|
||||||
</inspection_tool>
|
</inspection_tool>
|
||||||
<inspection_tool class="PreviewDeviceShouldUseNewSpec" enabled="true" level="WEAK WARNING" enabled_by_default="true">
|
<inspection_tool class="PreviewDeviceShouldUseNewSpec" enabled="true" level="WEAK WARNING" enabled_by_default="true">
|
||||||
<option name="composableFile" value="true" />
|
<option name="composableFile" value="true" />
|
||||||
|
<option name="previewFile" value="true" />
|
||||||
</inspection_tool>
|
</inspection_tool>
|
||||||
<inspection_tool class="PreviewFontScaleMustBeGreaterThanZero" enabled="true" level="ERROR" enabled_by_default="true">
|
<inspection_tool class="PreviewFontScaleMustBeGreaterThanZero" enabled="true" level="ERROR" enabled_by_default="true">
|
||||||
<option name="composableFile" value="true" />
|
<option name="composableFile" value="true" />
|
||||||
|
<option name="previewFile" value="true" />
|
||||||
</inspection_tool>
|
</inspection_tool>
|
||||||
<inspection_tool class="PreviewMultipleParameterProviders" enabled="true" level="ERROR" enabled_by_default="true">
|
<inspection_tool class="PreviewMultipleParameterProviders" enabled="true" level="ERROR" enabled_by_default="true">
|
||||||
<option name="composableFile" value="true" />
|
<option name="composableFile" value="true" />
|
||||||
|
<option name="previewFile" value="true" />
|
||||||
</inspection_tool>
|
</inspection_tool>
|
||||||
<inspection_tool class="PreviewPickerAnnotation" enabled="true" level="ERROR" enabled_by_default="true">
|
<inspection_tool class="PreviewPickerAnnotation" enabled="true" level="ERROR" enabled_by_default="true">
|
||||||
<option name="composableFile" value="true" />
|
<option name="composableFile" value="true" />
|
||||||
|
<option name="previewFile" value="true" />
|
||||||
</inspection_tool>
|
</inspection_tool>
|
||||||
</profile>
|
</profile>
|
||||||
</component>
|
</component>
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="VcsDirectoryMappings">
|
<component name="VcsDirectoryMappings">
|
||||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
|
||||||
<mapping directory="$PROJECT_DIR$/help" vcs="Git" />
|
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
@@ -12,12 +12,25 @@ android {
|
|||||||
applicationId = "com.odweta.solon"
|
applicationId = "com.odweta.solon"
|
||||||
minSdk = 28
|
minSdk = 28
|
||||||
targetSdk = 34
|
targetSdk = 34
|
||||||
versionCode = 1
|
versionCode = 205
|
||||||
versionName = "2.0"
|
versionName = "2.2"
|
||||||
|
|
||||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
applicationVariants.all {
|
||||||
|
this.outputs
|
||||||
|
.map { it as com.android.build.gradle.internal.api.ApkVariantOutputImpl }
|
||||||
|
.forEach { output ->
|
||||||
|
val apkName = "com.odweta.solon_" + this.versionName + ".apk"
|
||||||
|
output.outputFileName = apkName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buildFeatures {
|
||||||
|
compose = true
|
||||||
|
}
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
release {
|
release {
|
||||||
isMinifyEnabled = false
|
isMinifyEnabled = false
|
||||||
@@ -27,15 +40,21 @@ android {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
sourceCompatibility = JavaVersion.VERSION_11
|
sourceCompatibility = JavaVersion.VERSION_11
|
||||||
targetCompatibility = JavaVersion.VERSION_11
|
targetCompatibility = JavaVersion.VERSION_11
|
||||||
}
|
}
|
||||||
|
|
||||||
kotlinOptions {
|
kotlinOptions {
|
||||||
jvmTarget = "11"
|
jvmTarget = "11"
|
||||||
}
|
}
|
||||||
buildFeatures {
|
|
||||||
compose = true
|
dependenciesInfo {
|
||||||
|
// Disables dependency metadata when building APKs.
|
||||||
|
includeInApk = false
|
||||||
|
// Disables dependency metadata when building Android App Bundles.
|
||||||
|
includeInBundle = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,4 +70,4 @@ dependencies {
|
|||||||
implementation(libs.okhttp)
|
implementation(libs.okhttp)
|
||||||
implementation(libs.glide)
|
implementation(libs.glide)
|
||||||
implementation(libs.androidx.material.icons.extended)
|
implementation(libs.androidx.material.icons.extended)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,9 +18,12 @@
|
|||||||
tools:targetApi="31">
|
tools:targetApi="31">
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
|
android:screenOrientation="portrait"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:theme="@style/Theme.Solon">
|
android:theme="@style/Theme.Solon"
|
||||||
|
android:windowSoftInputMode="adjustResize"
|
||||||
|
tools:ignore="DiscouragedApi">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package com.odweta.solon
|
package com.odweta.solon
|
||||||
|
|
||||||
|
import androidx.activity.compose.BackHandler
|
||||||
import androidx.compose.foundation.Image
|
import androidx.compose.foundation.Image
|
||||||
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.border
|
import androidx.compose.foundation.border
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
@@ -8,6 +10,7 @@ import androidx.compose.foundation.layout.Box
|
|||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
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
|
||||||
@@ -24,6 +27,7 @@ import androidx.compose.runtime.Composable
|
|||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.platform.LocalUriHandler
|
import androidx.compose.ui.platform.LocalUriHandler
|
||||||
import com.odweta.solon.ui.theme.PastelYellow
|
import com.odweta.solon.ui.theme.PastelYellow
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
@@ -32,10 +36,14 @@ import androidx.compose.ui.text.style.TextAlign
|
|||||||
import androidx.compose.ui.text.style.TextDecoration
|
import androidx.compose.ui.text.style.TextDecoration
|
||||||
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 java.time.format.TextStyle
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun AboutScreen(modifier: Modifier = Modifier) {
|
fun AboutScreen(modifier: Modifier = Modifier) {
|
||||||
|
// handle the back gesture (back swipe form side or back button on bottom android navbar)
|
||||||
|
BackHandler {
|
||||||
|
isShowing.value = IsShowing.Menu
|
||||||
|
}
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize(),
|
.fillMaxSize(),
|
||||||
@@ -45,6 +53,7 @@ fun AboutScreen(modifier: Modifier = Modifier) {
|
|||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
|
.padding(start = 5.dp)
|
||||||
) {
|
) {
|
||||||
Button(
|
Button(
|
||||||
onClick = {
|
onClick = {
|
||||||
@@ -60,13 +69,13 @@ fun AboutScreen(modifier: Modifier = Modifier) {
|
|||||||
shape = RoundedCornerShape(roundedCornerDimen),
|
shape = RoundedCornerShape(roundedCornerDimen),
|
||||||
color = PastelYellow
|
color = PastelYellow
|
||||||
)
|
)
|
||||||
.width(100.dp)
|
.width(70.dp)
|
||||||
.height(100.dp)
|
.height(70.dp)
|
||||||
) {
|
) {
|
||||||
Icon(
|
Icon(
|
||||||
imageVector = Icons.Default.ArrowBackIosNew, // Replace with your desired icon
|
imageVector = Icons.Default.ArrowBackIosNew,
|
||||||
contentDescription = "Back icon",
|
contentDescription = "Back icon",
|
||||||
modifier = Modifier.size(35.dp) // Adjust size if needed
|
modifier = Modifier.size(40.dp)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -100,30 +109,71 @@ fun AboutScreen(modifier: Modifier = Modifier) {
|
|||||||
.padding(10.dp)
|
.padding(10.dp)
|
||||||
)
|
)
|
||||||
|
|
||||||
Row(
|
HorizontalLine()
|
||||||
modifier = Modifier
|
|
||||||
.padding(10.dp)
|
|
||||||
) {
|
|
||||||
val uriHandler = LocalUriHandler.current
|
|
||||||
|
|
||||||
Text(
|
AboutTableRow(
|
||||||
text = "Vývoj: ",
|
"Vývoj",
|
||||||
textAlign = TextAlign.Start,
|
"@Odweta",
|
||||||
color = Color.White,
|
"https://www.gitlab.com/Odweta/solon"
|
||||||
fontSize = 30.sp
|
)
|
||||||
)
|
|
||||||
|
|
||||||
Text(
|
AboutTableRow(
|
||||||
text = "@Odweta",
|
"Verze aplikace",
|
||||||
color = PastelYellow,
|
Util.getAppVersion(LocalContext.current)?.versionName ?: "N/A"
|
||||||
fontSize = 30.sp,
|
)
|
||||||
textAlign = TextAlign.End,
|
}
|
||||||
textDecoration = TextDecoration.Underline,
|
}
|
||||||
modifier = Modifier.clickable {
|
}
|
||||||
uriHandler.openUri("https://www.gitlab.com/Odweta/solon")
|
|
||||||
}
|
@Composable
|
||||||
)
|
fun HorizontalLine(modifier: Modifier = Modifier) {
|
||||||
}
|
Spacer(modifier = Modifier.height(20.dp))
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier
|
||||||
|
.height(2.dp)
|
||||||
|
.background(color = PastelYellow)
|
||||||
|
.fillMaxWidth(fraction = 0.8f)
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(20.dp))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun AboutTableRow(key: String, value: String, href: String = "") {
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(10.dp)
|
||||||
|
.background(color = Color.Black, shape = RoundedCornerShape(roundedCornerDimen))
|
||||||
|
.fillMaxWidth()
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = key,
|
||||||
|
textAlign = TextAlign.Start,
|
||||||
|
color = Color.White,
|
||||||
|
fontSize = 20.sp
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.weight(1f))
|
||||||
|
|
||||||
|
if (href != "") {
|
||||||
|
val uriHandler = LocalUriHandler.current
|
||||||
|
Text(
|
||||||
|
text = value,
|
||||||
|
color = PastelYellow,
|
||||||
|
fontSize = 20.sp,
|
||||||
|
textAlign = TextAlign.End,
|
||||||
|
textDecoration = TextDecoration.Underline,
|
||||||
|
modifier = Modifier.clickable {
|
||||||
|
uriHandler.openUri(href)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
Text(
|
||||||
|
text = value,
|
||||||
|
color = Color.White,
|
||||||
|
fontSize = 20.sp,
|
||||||
|
textAlign = TextAlign.End
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,22 +1,18 @@
|
|||||||
package com.odweta.solon
|
package com.odweta.solon
|
||||||
|
|
||||||
import android.view.Window
|
import android.view.Window
|
||||||
import androidx.compose.foundation.background
|
|
||||||
import androidx.compose.foundation.border
|
import androidx.compose.foundation.border
|
||||||
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.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.runtime.MutableState
|
import androidx.compose.runtime.MutableState
|
||||||
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
|
||||||
import androidx.compose.ui.graphics.toArgb
|
import androidx.compose.ui.graphics.toArgb
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.core.view.WindowCompat
|
|
||||||
import com.odweta.solon.ui.theme.PastelYellow
|
import com.odweta.solon.ui.theme.PastelYellow
|
||||||
import com.odweta.solon.ui.theme.PastelYellowTransparent
|
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
@@ -44,6 +40,8 @@ const val accountDataFilePath: String = "account_data.txt"
|
|||||||
const val timeTableFilePath: String = "timetable.json"
|
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 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
|
||||||
@@ -59,7 +57,8 @@ enum class IsShowing {
|
|||||||
Timetable,
|
Timetable,
|
||||||
Marks,
|
Marks,
|
||||||
Menu,
|
Menu,
|
||||||
About
|
About,
|
||||||
|
Settings
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class Screen {
|
enum class Screen {
|
||||||
@@ -76,8 +75,48 @@ var isShowing: MutableState<IsShowing> = mutableStateOf(IsShowing.Timetable)
|
|||||||
|
|
||||||
var toolbarText: MutableState<String> = mutableStateOf("")
|
var toolbarText: MutableState<String> = mutableStateOf("")
|
||||||
|
|
||||||
|
// default settings (will get overwritten by the saved settings)
|
||||||
|
class Setting(auxId: SettingsId, auxName: String, auxChecked: Boolean) {
|
||||||
|
var id: SettingsId = auxId
|
||||||
|
var name: String = auxName
|
||||||
|
var checked: MutableState<Boolean> = mutableStateOf(auxChecked)
|
||||||
|
override fun toString() = "$id#$name#${checked.value}"
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class SettingsId {
|
||||||
|
Svoboda,
|
||||||
|
Amoled,
|
||||||
|
RefreshButton
|
||||||
|
}
|
||||||
|
|
||||||
|
class SettingsData {
|
||||||
|
var useSvobodaMode: Setting = Setting(
|
||||||
|
SettingsId.Svoboda,
|
||||||
|
"Používat Svoboda mód",
|
||||||
|
false
|
||||||
|
)
|
||||||
|
|
||||||
|
var useAmoledMode: Setting = Setting(
|
||||||
|
SettingsId.Amoled,
|
||||||
|
"Používat AMOLED mód",
|
||||||
|
false
|
||||||
|
)
|
||||||
|
|
||||||
|
var showRefreshButton: Setting = Setting(
|
||||||
|
SettingsId.RefreshButton,
|
||||||
|
"Zobrazovat tlačítko obnovení dat",
|
||||||
|
true
|
||||||
|
)
|
||||||
|
|
||||||
|
override fun toString() = "$useSvobodaMode\n$useAmoledMode\n$showRefreshButton"
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
@@ -99,6 +138,9 @@ var resetNav: Boolean = false
|
|||||||
|
|
||||||
var isAPISetUp: Boolean = false
|
var isAPISetUp: Boolean = false
|
||||||
|
|
||||||
|
var lectureNotes: HashMap<Int, MutableState<String>> = hashMapOf()
|
||||||
|
var selectedLecture: Int = 0
|
||||||
|
|
||||||
var selectedDay: Int = 0
|
var selectedDay: Int = 0
|
||||||
var dayEndString: String = ""
|
var dayEndString: String = ""
|
||||||
|
|
||||||
@@ -1,15 +1,12 @@
|
|||||||
package com.odweta.solon
|
package com.odweta.solon
|
||||||
|
|
||||||
import android.app.Activity
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.GlobalScope
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
import kotlin.math.cos
|
|
||||||
|
|
||||||
private var week: List<Day> = mutableListOf()
|
private var week: List<Day> = mutableListOf()
|
||||||
private var toastShowing: Boolean = false
|
private var toastShowing: Boolean = false
|
||||||
@@ -19,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) {
|
||||||
@@ -37,7 +35,7 @@ private fun setOnInternetAvailListener(ctx: Context, coscope: CoroutineScope) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun fetchNewData(ctx: Context, coscope: CoroutineScope) {
|
fun fetchNewData(ctx: Context, coscope: CoroutineScope) {
|
||||||
coscope.launch {
|
coscope.launch {
|
||||||
done = false
|
done = false
|
||||||
|
|
||||||
@@ -46,23 +44,19 @@ private fun fetchNewData(ctx: Context, coscope: CoroutineScope) {
|
|||||||
"Načítání nových dat",
|
"Načítání nových dat",
|
||||||
"Načítání nových dat.",
|
"Načítání nových dat.",
|
||||||
"Načítání nových dat..",
|
"Načítání nových dat..",
|
||||||
"Načítání nových dat..."
|
"Načítání nových dat...",
|
||||||
|
"Načítání nových dat..",
|
||||||
|
"Načítání nových dat."
|
||||||
)
|
)
|
||||||
val delayTime: Long = 300 // delay in ms
|
val delayTime: Long = 300 // delay in ms
|
||||||
|
|
||||||
// show a loading animation
|
// show a loading animation
|
||||||
while (!done && Util.internetAvail(ctx)) {
|
while (!done && Util.internetAvail(ctx)) {
|
||||||
for (text in loadingArray) {
|
for (text in loadingArray) {
|
||||||
|
if (done) break
|
||||||
toolbarText.value = text
|
toolbarText.value = text
|
||||||
delay(delayTime)
|
delay(delayTime)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (text in loadingArray.reversedArray().slice(1..<loadingArray.size)) {
|
|
||||||
toolbarText.value = text
|
|
||||||
delay(delayTime)
|
|
||||||
}
|
|
||||||
|
|
||||||
delay(delayTime)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// determine the role of the student
|
// determine the role of the student
|
||||||
@@ -119,6 +113,7 @@ fun launchPhase0(ctx: Context, coscope: CoroutineScope) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun launchPhase1(ctx: Context) {
|
private suspend fun launchPhase1(ctx: Context) {
|
||||||
|
// TODO: CONVERT TO SNACKBARS
|
||||||
val toast: Toast = Toast.makeText(
|
val toast: Toast = Toast.makeText(
|
||||||
ctx,
|
ctx,
|
||||||
"Nelze načíst data, zkuste se připojit k internetu.",
|
"Nelze načíst data, zkuste se připojit k internetu.",
|
||||||
@@ -144,9 +139,11 @@ private suspend fun launchPhase1(ctx: Context) {
|
|||||||
toast2.show()
|
toast2.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!timeTableAvailOffline || 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
|
||||||
@@ -155,23 +152,31 @@ private suspend fun launchPhase1(ctx: Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// get the JSON data
|
// get the JSON data
|
||||||
val timeTableJSON = Network.getTimeTableJSON()
|
var timeTableJSON = Network.getTimeTableJSON()
|
||||||
|
if (timeTableJSON == """{"error": "network"}""") {
|
||||||
// try to save them into a file for later use
|
timeTableJSON = Util.fileToString(timeTableFilePath)
|
||||||
timeTableAvailOffline =
|
}
|
||||||
Util.saveStringToFile(timeTableFilePath, timeTableJSON)
|
|
||||||
|
|
||||||
// parse the data
|
|
||||||
week = Parsing.parseTimeTableJSON(timeTableJSON)
|
|
||||||
|
|
||||||
// fetch and parse marks
|
// fetch and parse marks
|
||||||
marksJSON = Network.getMarksJSON()
|
marksJSON = Network.getMarksJSON()
|
||||||
|
if (marksJSON == """{"error": "network"}""") {
|
||||||
|
marksJSON = Util.fileToString(marksFilePath)
|
||||||
|
}
|
||||||
|
|
||||||
|
timeTableAvailOffline =
|
||||||
|
Util.saveStringToFile(timeTableFilePath, timeTableJSON)
|
||||||
marksAvailOffline =
|
marksAvailOffline =
|
||||||
Util.saveStringToFile(marksFilePath, marksJSON)
|
Util.saveStringToFile(marksFilePath, marksJSON)
|
||||||
|
|
||||||
|
// parse the data
|
||||||
|
week = Parsing.parseTimeTableJSON(timeTableJSON)
|
||||||
marks = Parsing.parseMarksJSON(marksJSON)
|
marks = Parsing.parseMarksJSON(marksJSON)
|
||||||
|
|
||||||
|
// set the settings
|
||||||
|
if (Util.fileExists(settingsDataFilePath) && !Util.fileIsEmpty(settingsDataFilePath)) {
|
||||||
|
settings = Util.stringToSettingsData(Util.fileToString(settingsDataFilePath))
|
||||||
|
} // else load the default settings
|
||||||
|
|
||||||
// continue to launch phase 2
|
// continue to launch phase 2
|
||||||
done = true
|
done = true
|
||||||
launchPhase2(ctx)
|
launchPhase2(ctx)
|
||||||
@@ -270,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()) {
|
||||||
@@ -287,8 +296,13 @@ private fun launchPhase2(ctx: Context) {
|
|||||||
Util.fileToString(
|
Util.fileToString(
|
||||||
userDataFilePath
|
userDataFilePath
|
||||||
)
|
)
|
||||||
).getString("fullName")}$role"
|
).getString("fullName")
|
||||||
|
}$role"
|
||||||
|
|
||||||
// set the main content view
|
// set the main content view
|
||||||
screenToShow.value = Screen.Main
|
screenToShow.value = Screen.Main
|
||||||
|
|
||||||
|
if (settings.showRefreshButton.checked.value) {
|
||||||
|
refreshButtonContentColor.value = Color.White
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -15,6 +15,7 @@ import androidx.compose.ui.Alignment
|
|||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
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.core.view.WindowCompat
|
||||||
import com.odweta.solon.ui.theme.SolonTheme
|
import com.odweta.solon.ui.theme.SolonTheme
|
||||||
import kotlin.math.sign
|
import kotlin.math.sign
|
||||||
|
|
||||||
@@ -68,6 +69,7 @@ class MainActivity : ComponentActivity() {
|
|||||||
IsShowing.Marks -> MarksScreen()
|
IsShowing.Marks -> MarksScreen()
|
||||||
IsShowing.Menu -> MenuScreen()
|
IsShowing.Menu -> MenuScreen()
|
||||||
IsShowing.About -> AboutScreen()
|
IsShowing.About -> AboutScreen()
|
||||||
|
IsShowing.Settings -> SettingsScreen()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.odweta.solon
|
package com.odweta.solon
|
||||||
|
|
||||||
|
import androidx.activity.compose.BackHandler
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.border
|
import androidx.compose.foundation.border
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
@@ -20,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
|
||||||
@@ -37,11 +39,15 @@ import androidx.compose.ui.unit.sp
|
|||||||
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.PastelOrange
|
import com.odweta.solon.ui.theme.PastelOrange
|
||||||
|
import com.odweta.solon.ui.theme.PastelOrangeDark
|
||||||
|
import com.odweta.solon.ui.theme.PastelOrangeDarkTransparent
|
||||||
import com.odweta.solon.ui.theme.PastelOrangeTransparent
|
import com.odweta.solon.ui.theme.PastelOrangeTransparent
|
||||||
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 java.time.LocalDate
|
||||||
|
import java.time.format.DateTimeFormatter
|
||||||
|
|
||||||
enum class MarksShow {
|
enum class MarksShow {
|
||||||
All,
|
All,
|
||||||
@@ -63,25 +69,31 @@ fun MarksScreen() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun getAvgColor(avg: String, isBorder: Boolean = false): Color {
|
private fun getAvgColor(avg: String, isBorder: Boolean = false): Color {
|
||||||
val aux = avg.replace(",", ".").toFloat().toInt()
|
val aux = avg.replace(",", ".").toFloat()
|
||||||
return if (aux in 1..<2) {
|
return if (aux in 1f..<1.5f) {
|
||||||
if (isBorder) {
|
if (isBorder) {
|
||||||
PastelGreen
|
PastelGreen
|
||||||
} else {
|
} else {
|
||||||
PastelGreenTransparent
|
PastelGreenTransparent
|
||||||
}
|
}
|
||||||
} else if (aux in 2..<3) {
|
} else if (aux in 1.5f..<2.5f) {
|
||||||
if (isBorder) {
|
if (isBorder) {
|
||||||
PastelYellow
|
PastelYellow
|
||||||
} else {
|
} else {
|
||||||
PastelYellowTransparent
|
PastelYellowTransparent
|
||||||
}
|
}
|
||||||
} else if (aux in 3..<4) {
|
} else if (aux in 2.5f..<3.5f) {
|
||||||
if (isBorder) {
|
if (isBorder) {
|
||||||
PastelOrange
|
PastelOrange
|
||||||
} else {
|
} else {
|
||||||
PastelOrangeTransparent
|
PastelOrangeTransparent
|
||||||
}
|
}
|
||||||
|
} else if (aux in 3.5f..<4.5f) {
|
||||||
|
if (isBorder) {
|
||||||
|
PastelOrangeDark
|
||||||
|
} else {
|
||||||
|
PastelOrangeDarkTransparent
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (isBorder) {
|
if (isBorder) {
|
||||||
PastelRed
|
PastelRed
|
||||||
@@ -104,6 +116,64 @@ fun MarksAll() {
|
|||||||
.verticalScroll(scrollState)
|
.verticalScroll(scrollState)
|
||||||
) {
|
) {
|
||||||
for ((subject, markList) in marks) {
|
for ((subject, markList) in marks) {
|
||||||
|
val amoledModifier = if (settings.useAmoledMode.checked.value) {
|
||||||
|
Modifier
|
||||||
|
.width(150.dp)
|
||||||
|
.fillMaxHeight()
|
||||||
|
.border(
|
||||||
|
width = borderWidthDimen,
|
||||||
|
color = getAvgColor(Util.avg(markList), true), // decide on the color (transparent)
|
||||||
|
shape = RoundedCornerShape(roundedCornerDimen)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
Modifier
|
||||||
|
.width(150.dp)
|
||||||
|
.fillMaxHeight()
|
||||||
|
.background(
|
||||||
|
color = getAvgColor(Util.avg(markList)), // decide on the color (not transparent)
|
||||||
|
shape = RoundedCornerShape(roundedCornerDimen)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
val amoledModifierBackground = if (settings.useAmoledMode.checked.value) {
|
||||||
|
Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.height(70.dp)
|
||||||
|
.border(
|
||||||
|
width = borderWidthDimen,
|
||||||
|
color = getAvgColor(Util.avg(markList), true), // decide on the color (transparent)
|
||||||
|
shape = RoundedCornerShape(roundedCornerDimen)
|
||||||
|
)
|
||||||
|
.clickable {
|
||||||
|
marksShow.value = MarksShow.Subject
|
||||||
|
subjectToShow = subject
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.height(70.dp)
|
||||||
|
.background(
|
||||||
|
color = getAvgColor(Util.avg(markList)), // decide on the color (transparent)
|
||||||
|
shape = RoundedCornerShape(roundedCornerDimen)
|
||||||
|
)
|
||||||
|
.clickable {
|
||||||
|
marksShow.value = MarksShow.Subject
|
||||||
|
subjectToShow = subject
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val amoledSpacerModifier = if (settings.useAmoledMode.checked.value) {
|
||||||
|
Modifier
|
||||||
|
.width(10.dp)
|
||||||
|
.fillMaxHeight()
|
||||||
|
.background(getAvgColor(Util.avg(markList)))
|
||||||
|
} else {
|
||||||
|
Modifier
|
||||||
|
.width(10.dp)
|
||||||
|
.fillMaxHeight()
|
||||||
|
.background(Color.Black)
|
||||||
|
}
|
||||||
|
|
||||||
var marksString = ""
|
var marksString = ""
|
||||||
for (m in 0 until markList.size-1) {
|
for (m in 0 until markList.size-1) {
|
||||||
if (markList[m].grade in "0123456789") {
|
if (markList[m].grade in "0123456789") {
|
||||||
@@ -116,68 +186,78 @@ 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 = Modifier
|
modifier = amoledModifierBackground
|
||||||
.fillMaxWidth()
|
|
||||||
.height(100.dp)
|
|
||||||
.background(
|
|
||||||
color = getAvgColor(Util.avg(markList)), // decide on the color (transparent)
|
|
||||||
shape = RoundedCornerShape(roundedCornerDimen)
|
|
||||||
)
|
|
||||||
.clickable {
|
|
||||||
marksShow.value = MarksShow.Subject
|
|
||||||
subjectToShow = subject
|
|
||||||
}
|
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier = amoledModifier,
|
||||||
.width(210.dp)
|
|
||||||
.fillMaxHeight()
|
|
||||||
.background(
|
|
||||||
color = getAvgColor(Util.avg(markList)), // decide on the color (not transparent)
|
|
||||||
shape = RoundedCornerShape(roundedCornerDimen)
|
|
||||||
),
|
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
horizontalArrangement = Arrangement.Center
|
horizontalArrangement = Arrangement.Center
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = subject.uppercase(),
|
text = subject.uppercase(),
|
||||||
fontSize = 35.sp,
|
fontSize = 30.sp,
|
||||||
color = Color.White,
|
color = Color.White,
|
||||||
fontWeight = FontWeight.Bold,
|
fontWeight = FontWeight.Bold,
|
||||||
textAlign = TextAlign.Center,
|
textAlign = TextAlign.Center,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.width(100.dp)
|
.width(70.dp)
|
||||||
)
|
)
|
||||||
|
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = amoledSpacerModifier
|
||||||
.width(10.dp)
|
|
||||||
.fillMaxHeight()
|
|
||||||
.background(Color.Black)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val currAvg = Util.avg(markList).replace(".", ",")
|
||||||
|
var textToShow = currAvg
|
||||||
|
if (currAvg.length == 3 && currAvg[2] == '0') {
|
||||||
|
textToShow = currAvg[0].toString()
|
||||||
|
}
|
||||||
Text(
|
Text(
|
||||||
text = Util.avg(markList).replace(".", ","),
|
text = textToShow,
|
||||||
fontSize = 30.sp,
|
fontSize = 28.sp,
|
||||||
color = Color.White,
|
color = Color.White,
|
||||||
textAlign = TextAlign.Center,
|
textAlign = TextAlign.Center,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.width(100.dp)
|
.width(70.dp)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier.fillMaxSize().weight(1f),
|
||||||
.weight(1f)
|
contentAlignment = Alignment.TopStart
|
||||||
.fillMaxHeight(),
|
|
||||||
contentAlignment = Alignment.Center
|
|
||||||
) {
|
) {
|
||||||
Text(
|
if (subjectContainsNewMark) {
|
||||||
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
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -186,6 +266,11 @@ fun MarksAll() {
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun MarksSubject() {
|
fun MarksSubject() {
|
||||||
|
// handle the back gesture (back swipe form side or back button on bottom android navbar)
|
||||||
|
BackHandler {
|
||||||
|
marksShow.value = MarksShow.All
|
||||||
|
}
|
||||||
|
|
||||||
val scrollState = rememberScrollState()
|
val scrollState = rememberScrollState()
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
@@ -195,62 +280,39 @@ fun MarksSubject() {
|
|||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(horizontal = 5.dp)
|
.padding(horizontal = 5.dp)
|
||||||
) {
|
) {
|
||||||
Button(
|
Row(
|
||||||
onClick = {
|
modifier = Modifier.fillMaxWidth()
|
||||||
marksShow.value = MarksShow.All
|
|
||||||
},
|
|
||||||
colors = ButtonDefaults.buttonColors(
|
|
||||||
contentColor = Color.White,
|
|
||||||
containerColor = Color.Black
|
|
||||||
),
|
|
||||||
modifier = Modifier
|
|
||||||
.border(
|
|
||||||
width = 5.dp,
|
|
||||||
shape = RoundedCornerShape(roundedCornerDimen),
|
|
||||||
color = PastelYellow
|
|
||||||
)
|
|
||||||
.width(100.dp)
|
|
||||||
.height(100.dp)
|
|
||||||
) {
|
) {
|
||||||
Icon(
|
Button(
|
||||||
imageVector = Icons.Default.ArrowBackIosNew, // Replace with your desired icon
|
onClick = {
|
||||||
contentDescription = "Back icon",
|
marksShow.value = MarksShow.All
|
||||||
modifier = Modifier.size(35.dp) // Adjust size if needed
|
},
|
||||||
)
|
colors = ButtonDefaults.buttonColors(
|
||||||
}
|
contentColor = Color.White,
|
||||||
|
containerColor = Color.Black
|
||||||
Spacer(modifier = Modifier.height(20.dp))
|
),
|
||||||
|
|
||||||
Box(modifier = Modifier.height(100.dp)) {
|
|
||||||
Text(
|
|
||||||
text = subjectNameMap[subjectToShow]!!,
|
|
||||||
color = Color.White,
|
|
||||||
textAlign = TextAlign.Center,
|
|
||||||
fontSize = 30.sp,
|
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
|
||||||
.border(
|
.border(
|
||||||
width = 5.dp,
|
width = 5.dp,
|
||||||
color = PastelYellow,
|
shape = RoundedCornerShape(roundedCornerDimen),
|
||||||
shape = RoundedCornerShape(roundedCornerDimen)
|
color = PastelYellow
|
||||||
)
|
)
|
||||||
.background(PastelYellowTransparent)
|
.width(70.dp)
|
||||||
.padding(vertical = 20.dp)
|
.height(70.dp)
|
||||||
) // subject
|
) {
|
||||||
}
|
Icon(
|
||||||
|
imageVector = Icons.Default.ArrowBackIosNew,
|
||||||
|
contentDescription = "Back icon",
|
||||||
|
modifier = Modifier.size(40.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
Box(
|
Box(modifier = Modifier.weight(1f))
|
||||||
modifier = Modifier.fillMaxWidth(),
|
|
||||||
contentAlignment = Alignment.Center
|
Box(
|
||||||
) {
|
|
||||||
Text(
|
|
||||||
text = Util.avg(marks[subjectToShow]!!).replace(".", ","),
|
|
||||||
color = Color.White,
|
|
||||||
textAlign = TextAlign.Center,
|
|
||||||
fontSize = 30.sp,
|
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.width(100.dp)
|
.width(70.dp)
|
||||||
.height(100.dp)
|
.height(70.dp)
|
||||||
.border(
|
.border(
|
||||||
width = 5.dp,
|
width = 5.dp,
|
||||||
color = getAvgColor(
|
color = getAvgColor(
|
||||||
@@ -259,61 +321,120 @@ fun MarksSubject() {
|
|||||||
),
|
),
|
||||||
shape = RoundedCornerShape(roundedCornerDimen)
|
shape = RoundedCornerShape(roundedCornerDimen)
|
||||||
)
|
)
|
||||||
.background(
|
.background(color = if (settings.useAmoledMode.checked.value) {
|
||||||
getAvgColor(
|
Color.Black
|
||||||
Util.avg(marks[subjectToShow]!!)
|
} else {
|
||||||
)
|
getAvgColor(
|
||||||
|
Util.avg(marks[subjectToShow]!!)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
shape = RoundedCornerShape(roundedCornerDimen)
|
||||||
)
|
)
|
||||||
.padding(vertical = 32.5.dp)
|
.padding(vertical = 15.dp),
|
||||||
) // average
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
val currAvg = Util.avg(marks[subjectToShow]!!).replace(".", ",")
|
||||||
|
var textToShow = currAvg
|
||||||
|
if (currAvg.length == 3 && currAvg[2] == '0') {
|
||||||
|
textToShow = currAvg[0].toString()
|
||||||
|
}
|
||||||
|
Text(
|
||||||
|
text = textToShow,
|
||||||
|
color = Color.White,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
fontSize = 25.sp
|
||||||
|
) // average
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(20.dp))
|
Spacer(modifier = Modifier.height(20.dp))
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = subjectNameMap[subjectToShow]!!,
|
||||||
|
color = Color.White,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
fontSize = 30.sp,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.border(
|
||||||
|
width = 5.dp,
|
||||||
|
color = PastelYellow,
|
||||||
|
shape = RoundedCornerShape(roundedCornerDimen)
|
||||||
|
)
|
||||||
|
.background(color = if (settings.useAmoledMode.checked.value) {
|
||||||
|
Color.Black
|
||||||
|
} else {
|
||||||
|
PastelYellowTransparent
|
||||||
|
},
|
||||||
|
shape = RoundedCornerShape(roundedCornerDimen)
|
||||||
|
)
|
||||||
|
.padding(vertical = 20.dp)
|
||||||
|
) // subject
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(20.dp))
|
||||||
|
|
||||||
Column(modifier = Modifier.verticalScroll(scrollState)) {
|
Column(modifier = Modifier.verticalScroll(scrollState)) {
|
||||||
for ((i, mark) in marks[subjectToShow]!!.withIndex()) {
|
for ((i, mark) in marks[subjectToShow]!!.withIndex()) {
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
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 = getAvgColor(mark.grade),
|
|
||||||
shape = RoundedCornerShape(roundedCornerDimen)
|
|
||||||
)
|
|
||||||
.padding(vertical = 20.dp)
|
|
||||||
.clickable {
|
|
||||||
markToShow = mark
|
|
||||||
marksShow.value = MarksShow.Detail
|
|
||||||
}
|
|
||||||
) {
|
) {
|
||||||
Box(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.width(100.dp)
|
.fillMaxWidth()
|
||||||
.align(Alignment.CenterVertically),
|
.padding(horizontal = 5.dp)
|
||||||
contentAlignment = Alignment.Center
|
.background(color = if (settings.useAmoledMode.checked.value) {
|
||||||
|
Color.Black
|
||||||
|
} else {
|
||||||
|
getAvgColor(mark.grade)
|
||||||
|
},
|
||||||
|
shape = RoundedCornerShape(roundedCornerDimen)
|
||||||
|
)
|
||||||
|
.padding(vertical = 10.dp)
|
||||||
|
.clickable {
|
||||||
|
markToShow = mark
|
||||||
|
marksShow.value = MarksShow.Detail
|
||||||
|
}
|
||||||
) {
|
) {
|
||||||
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.parse(mark.date, DateTimeFormatter.ISO_LOCAL_DATE_TIME).isAfter(LocalDate.now().minusWeeks(1))) {
|
||||||
.align(Alignment.CenterVertically)
|
Icon(
|
||||||
.weight(1f),
|
modifier = Modifier.padding(start = 7.dp, top = 4.dp),
|
||||||
contentAlignment = Alignment.CenterStart
|
imageVector = Icons.Default.AutoAwesome,
|
||||||
) {
|
contentDescription = "A new mark",
|
||||||
Text(
|
tint = Color.White // You can customize the icon color
|
||||||
text = mark.theme,
|
)
|
||||||
color = Color.White,
|
|
||||||
fontSize = 23.sp
|
|
||||||
) // theme
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -323,6 +444,11 @@ fun MarksSubject() {
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun MarksDetail() {
|
fun MarksDetail() {
|
||||||
|
// handle the back gesture (back swipe form side or back button on bottom android navbar)
|
||||||
|
BackHandler {
|
||||||
|
marksShow.value = MarksShow.Subject
|
||||||
|
}
|
||||||
|
|
||||||
val scrollState = rememberScrollState()
|
val scrollState = rememberScrollState()
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
@@ -333,82 +459,92 @@ fun MarksDetail() {
|
|||||||
.padding(horizontal = 5.dp)
|
.padding(horizontal = 5.dp)
|
||||||
.verticalScroll(scrollState)
|
.verticalScroll(scrollState)
|
||||||
) {
|
) {
|
||||||
Button(
|
Row(
|
||||||
onClick = {
|
modifier = Modifier.fillMaxWidth()
|
||||||
marksShow.value = MarksShow.Subject
|
|
||||||
},
|
|
||||||
colors = ButtonDefaults.buttonColors(
|
|
||||||
contentColor = Color.White,
|
|
||||||
containerColor = Color.Black
|
|
||||||
),
|
|
||||||
modifier = Modifier
|
|
||||||
.border(
|
|
||||||
width = 5.dp,
|
|
||||||
shape = RoundedCornerShape(roundedCornerDimen),
|
|
||||||
color = PastelYellow
|
|
||||||
)
|
|
||||||
.width(100.dp)
|
|
||||||
.height(100.dp)
|
|
||||||
) {
|
) {
|
||||||
Icon(
|
Button(
|
||||||
imageVector = Icons.Default.ArrowBackIosNew, // Replace with your desired icon
|
onClick = {
|
||||||
contentDescription = "Back icon",
|
marksShow.value = MarksShow.Subject
|
||||||
modifier = Modifier.size(35.dp) // Adjust size if needed
|
},
|
||||||
)
|
colors = ButtonDefaults.buttonColors(
|
||||||
}
|
contentColor = Color.White,
|
||||||
|
containerColor = Color.Black
|
||||||
Spacer(modifier = Modifier.height(20.dp))
|
),
|
||||||
|
modifier = Modifier
|
||||||
Row {
|
.border(
|
||||||
Box(modifier = Modifier.height(100.dp)) {
|
width = 5.dp,
|
||||||
Text(
|
shape = RoundedCornerShape(roundedCornerDimen),
|
||||||
text = markToShow.theme,
|
color = PastelYellow
|
||||||
color = Color.White,
|
)
|
||||||
textAlign = TextAlign.Center,
|
.width(70.dp)
|
||||||
fontSize = 30.sp,
|
.height(70.dp)
|
||||||
modifier = Modifier
|
) {
|
||||||
.fillMaxWidth()
|
Icon(
|
||||||
.border(
|
imageVector = Icons.Default.ArrowBackIosNew,
|
||||||
width = 5.dp,
|
contentDescription = "Back icon",
|
||||||
color = PastelYellow,
|
modifier = Modifier.size(40.dp)
|
||||||
shape = RoundedCornerShape(roundedCornerDimen)
|
)
|
||||||
)
|
|
||||||
.background(PastelYellowTransparent)
|
|
||||||
.padding(vertical = 20.dp)
|
|
||||||
) // description
|
|
||||||
}
|
}
|
||||||
} // description
|
|
||||||
|
|
||||||
Row {
|
Box(modifier = Modifier.weight(1f))
|
||||||
|
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier
|
||||||
|
.width(70.dp)
|
||||||
|
.height(70.dp)
|
||||||
|
.border(
|
||||||
|
width = 5.dp,
|
||||||
|
color = getAvgColor(
|
||||||
|
Util.avg(marks[subjectToShow]!!),
|
||||||
|
true
|
||||||
|
),
|
||||||
|
shape = RoundedCornerShape(roundedCornerDimen)
|
||||||
|
)
|
||||||
|
.background(
|
||||||
|
if (settings.useAmoledMode.checked.value) {
|
||||||
|
Color.Black
|
||||||
|
} else {
|
||||||
|
getAvgColor(
|
||||||
|
Util.avg(marks[subjectToShow]!!)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.padding(vertical = 15.dp),
|
||||||
contentAlignment = Alignment.Center
|
contentAlignment = Alignment.Center
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = markToShow.grade,
|
text = markToShow.grade,
|
||||||
color = Color.White,
|
color = Color.White,
|
||||||
textAlign = TextAlign.Center,
|
textAlign = TextAlign.Center,
|
||||||
fontSize = 35.sp,
|
fontSize = 25.sp
|
||||||
modifier = Modifier
|
|
||||||
.width(100.dp)
|
|
||||||
.height(100.dp)
|
|
||||||
.border(
|
|
||||||
width = 5.dp,
|
|
||||||
color = getAvgColor(
|
|
||||||
Util.avg(mutableListOf(markToShow)),
|
|
||||||
true
|
|
||||||
),
|
|
||||||
shape = RoundedCornerShape(roundedCornerDimen)
|
|
||||||
)
|
|
||||||
.background(
|
|
||||||
getAvgColor(
|
|
||||||
Util.avg(mutableListOf(markToShow))
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.padding(vertical = 32.5.dp)
|
|
||||||
) // average
|
) // average
|
||||||
}
|
}
|
||||||
} // grade
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(20.dp))
|
||||||
|
|
||||||
|
Row {
|
||||||
|
Text(
|
||||||
|
text = markToShow.theme,
|
||||||
|
color = Color.White,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
fontSize = 30.sp,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.border(
|
||||||
|
width = 5.dp,
|
||||||
|
color = PastelYellow,
|
||||||
|
shape = RoundedCornerShape(roundedCornerDimen)
|
||||||
|
)
|
||||||
|
.background(if (settings.useAmoledMode.checked.value) {
|
||||||
|
Color.Black
|
||||||
|
} else {
|
||||||
|
PastelYellowTransparent
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.padding(vertical = 20.dp)
|
||||||
|
) // description
|
||||||
|
} // description
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(20.dp))
|
Spacer(modifier = Modifier.height(20.dp))
|
||||||
|
|
||||||
@@ -417,7 +553,11 @@ fun MarksDetail() {
|
|||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(horizontal = 5.dp)
|
.padding(horizontal = 5.dp)
|
||||||
.background(
|
.background(
|
||||||
color = PastelYellowTransparent,
|
color = if (settings.useAmoledMode.checked.value) {
|
||||||
|
Color.Black
|
||||||
|
} else {
|
||||||
|
PastelYellowTransparent
|
||||||
|
},
|
||||||
shape = RoundedCornerShape(roundedCornerDimen)
|
shape = RoundedCornerShape(roundedCornerDimen)
|
||||||
)
|
)
|
||||||
.padding(vertical = 20.dp, horizontal = 10.dp)
|
.padding(vertical = 20.dp, horizontal = 10.dp)
|
||||||
@@ -431,7 +571,7 @@ fun MarksDetail() {
|
|||||||
Text(
|
Text(
|
||||||
text = "Váha:",
|
text = "Váha:",
|
||||||
color = Color.White,
|
color = Color.White,
|
||||||
fontSize = 30.sp
|
fontSize = 20.sp
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -444,7 +584,7 @@ fun MarksDetail() {
|
|||||||
Text(
|
Text(
|
||||||
text = markToShow.weight.replace(".", ","),
|
text = markToShow.weight.replace(".", ","),
|
||||||
color = Color.White,
|
color = Color.White,
|
||||||
fontSize = 23.sp
|
fontSize = 20.sp
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} // weight
|
} // weight
|
||||||
@@ -456,7 +596,11 @@ fun MarksDetail() {
|
|||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(horizontal = 5.dp)
|
.padding(horizontal = 5.dp)
|
||||||
.background(
|
.background(
|
||||||
color = PastelYellowTransparent,
|
color = if (settings.useAmoledMode.checked.value) {
|
||||||
|
Color.Black
|
||||||
|
} else {
|
||||||
|
PastelYellowTransparent
|
||||||
|
},
|
||||||
shape = RoundedCornerShape(roundedCornerDimen)
|
shape = RoundedCornerShape(roundedCornerDimen)
|
||||||
)
|
)
|
||||||
.padding(vertical = 20.dp, horizontal = 10.dp)
|
.padding(vertical = 20.dp, horizontal = 10.dp)
|
||||||
@@ -470,7 +614,7 @@ fun MarksDetail() {
|
|||||||
Text(
|
Text(
|
||||||
text = "Datum:",
|
text = "Datum:",
|
||||||
color = Color.White,
|
color = Color.White,
|
||||||
fontSize = 30.sp
|
fontSize = 20.sp
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -489,7 +633,7 @@ fun MarksDetail() {
|
|||||||
Text(
|
Text(
|
||||||
text = date,
|
text = date,
|
||||||
color = Color.White,
|
color = Color.White,
|
||||||
fontSize = 23.sp
|
fontSize = 20.sp
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} // date
|
} // date
|
||||||
|
|||||||
@@ -36,129 +36,97 @@ fun MenuScreen(modifier: Modifier = Modifier) {
|
|||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
verticalArrangement = Arrangement.Center
|
verticalArrangement = Arrangement.Center
|
||||||
) {
|
) {
|
||||||
// Button to trigger the dialog
|
MenuButton({ showDialog = true }, "Odhlásit se")
|
||||||
Button(
|
|
||||||
onClick = { showDialog = true },
|
Spacer(modifier = Modifier.height(80.dp))
|
||||||
colors = ButtonDefaults.buttonColors(
|
|
||||||
contentColor = Color.White,
|
MenuButton({ screenToShow.value = Screen.SignIn }, "Změnit přihlášení")
|
||||||
containerColor = Color.Black
|
|
||||||
),
|
Spacer(modifier = Modifier.height(80.dp))
|
||||||
|
|
||||||
|
MenuButton({ isShowing.value = IsShowing.About }, "O aplikaci")
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(80.dp))
|
||||||
|
|
||||||
|
MenuButton({ isShowing.value = IsShowing.Settings }, "Nastavení")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dialog implementation
|
||||||
|
if (showDialog) {
|
||||||
|
AlertDialog(
|
||||||
|
onDismissRequest = { showDialog = false }, // Close the dialog on dismiss
|
||||||
|
title = {
|
||||||
|
Text(text = "Odhlásit se", color = Color.White)
|
||||||
|
},
|
||||||
|
text = {
|
||||||
|
Text("Opravdu se chcete odhlásit? Tato akce zavře aplikaci.", color = Color.White)
|
||||||
|
},
|
||||||
|
containerColor = Color.Black,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.border(
|
.border(width = 5.dp, color = PastelYellow, shape = RoundedCornerShape(
|
||||||
width = 5.dp,
|
roundedCornerDimen)), // Yellow border
|
||||||
shape = RoundedCornerShape(roundedCornerDimen),
|
confirmButton = {
|
||||||
color = PastelYellow
|
Button(
|
||||||
)
|
onClick = {
|
||||||
.width(230.dp)
|
showDialog = false
|
||||||
.height(80.dp)
|
Util.deleteFile(userDataFilePath)
|
||||||
) {
|
Util.deleteFile(timeTableFilePath)
|
||||||
Text(
|
Util.deleteFile(marksFilePath)
|
||||||
text = "Odhlásit se",
|
Util.deleteFile(accountDataFilePath)
|
||||||
fontSize = 23.sp
|
exitProcess(0)
|
||||||
)
|
},
|
||||||
}
|
colors = ButtonDefaults.buttonColors(
|
||||||
|
containerColor = Color.Black, // Black background for the button
|
||||||
Spacer(modifier = Modifier.height(100.dp))
|
contentColor = Color.White // Yellow text for the button
|
||||||
|
),
|
||||||
// Dialog implementation
|
modifier = Modifier
|
||||||
if (showDialog) {
|
.border(width = 5.dp, color = PastelYellow, shape = RoundedCornerShape(
|
||||||
AlertDialog(
|
roundedCornerDimen)) // Yellow border
|
||||||
onDismissRequest = { showDialog = false }, // Close the dialog on dismiss
|
) {
|
||||||
title = {
|
Text("Ano")
|
||||||
Text(text = "Odhlásit se", color = Color.White)
|
|
||||||
},
|
|
||||||
text = {
|
|
||||||
Text("Opravdu se chcete odhlásit? Tato akce zavře aplikaci.", color = Color.White)
|
|
||||||
},
|
|
||||||
containerColor = Color.Black,
|
|
||||||
modifier = Modifier
|
|
||||||
.border(width = 5.dp, color = PastelYellow, shape = RoundedCornerShape(
|
|
||||||
roundedCornerDimen)), // Yellow border
|
|
||||||
confirmButton = {
|
|
||||||
Button(
|
|
||||||
onClick = {
|
|
||||||
showDialog = false
|
|
||||||
Util.deleteFile(userDataFilePath)
|
|
||||||
Util.deleteFile(timeTableFilePath)
|
|
||||||
Util.deleteFile(marksFilePath)
|
|
||||||
Util.deleteFile(accountDataFilePath)
|
|
||||||
exitProcess(0)
|
|
||||||
},
|
|
||||||
colors = ButtonDefaults.buttonColors(
|
|
||||||
containerColor = Color.Black, // Black background for the button
|
|
||||||
contentColor = Color.White // Yellow text for the button
|
|
||||||
),
|
|
||||||
modifier = Modifier
|
|
||||||
.border(width = 5.dp, color = PastelYellow, shape = RoundedCornerShape(
|
|
||||||
roundedCornerDimen)) // Yellow border
|
|
||||||
) {
|
|
||||||
Text("Ano")
|
|
||||||
}
|
|
||||||
},
|
|
||||||
dismissButton = {
|
|
||||||
Button(
|
|
||||||
onClick = {
|
|
||||||
showDialog = false
|
|
||||||
},
|
|
||||||
colors = ButtonDefaults.buttonColors(
|
|
||||||
containerColor = Color.Black, // Black background for the button
|
|
||||||
contentColor = Color.White,
|
|
||||||
// Yellow text for the button
|
|
||||||
),
|
|
||||||
modifier = Modifier
|
|
||||||
.border(width = 5.dp, color = PastelYellow, shape = RoundedCornerShape(
|
|
||||||
roundedCornerDimen)) // Yellow border
|
|
||||||
) {
|
|
||||||
Text("Ne")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
) // TODO: THEME DIALOG
|
|
||||||
}
|
|
||||||
|
|
||||||
Button(onClick = {
|
|
||||||
screenToShow.value = Screen.SignIn
|
|
||||||
},
|
},
|
||||||
colors = ButtonDefaults.buttonColors(
|
dismissButton = {
|
||||||
contentColor = Color.White,
|
Button(
|
||||||
containerColor = Color.Black
|
onClick = {
|
||||||
),
|
showDialog = false
|
||||||
modifier = Modifier
|
},
|
||||||
.border(
|
colors = ButtonDefaults.buttonColors(
|
||||||
width = 5.dp,
|
containerColor = Color.Black, // Black background for the button
|
||||||
shape = RoundedCornerShape(roundedCornerDimen),
|
contentColor = Color.White,
|
||||||
color = PastelYellow
|
// Yellow text for the button
|
||||||
)
|
),
|
||||||
.width(230.dp)
|
modifier = Modifier
|
||||||
.height(80.dp)
|
.border(width = 5.dp, color = PastelYellow, shape = RoundedCornerShape(
|
||||||
) {
|
roundedCornerDimen)) // Yellow border
|
||||||
Text(
|
) {
|
||||||
text = "Změnit přihlášení",
|
Text("Ne")
|
||||||
fontSize = 23.sp
|
}
|
||||||
)
|
}
|
||||||
}
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(100.dp))
|
@Composable
|
||||||
|
fun MenuButton(onClick: () -> Unit, text: String) {
|
||||||
Button(onClick = {
|
Button(
|
||||||
isShowing.value = IsShowing.About
|
onClick = onClick,
|
||||||
},
|
colors = ButtonDefaults.buttonColors(
|
||||||
colors = ButtonDefaults.buttonColors(
|
contentColor = Color.White,
|
||||||
contentColor = Color.White,
|
containerColor = Color.Black
|
||||||
containerColor = Color.Black
|
),
|
||||||
),
|
modifier = Modifier
|
||||||
modifier = Modifier
|
.border(
|
||||||
.border(
|
width = 5.dp,
|
||||||
width = 5.dp,
|
shape = RoundedCornerShape(roundedCornerDimen),
|
||||||
shape = RoundedCornerShape(roundedCornerDimen),
|
color = PastelYellow
|
||||||
color = PastelYellow
|
|
||||||
)
|
|
||||||
.width(230.dp)
|
|
||||||
.height(80.dp)
|
|
||||||
) {
|
|
||||||
Text(
|
|
||||||
text = "O aplikaci",
|
|
||||||
fontSize = 23.sp
|
|
||||||
)
|
)
|
||||||
}
|
.width(230.dp)
|
||||||
|
.height(80.dp)
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = text,
|
||||||
|
fontSize = 23.sp
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4,10 +4,12 @@ import androidx.compose.foundation.layout.Arrangement
|
|||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.layout.width
|
import androidx.compose.foundation.layout.width
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.Menu
|
import androidx.compose.material.icons.filled.Menu
|
||||||
|
import androidx.compose.material.icons.filled.Refresh
|
||||||
import androidx.compose.material.icons.filled.Schedule
|
import androidx.compose.material.icons.filled.Schedule
|
||||||
import androidx.compose.material3.Button
|
import androidx.compose.material3.Button
|
||||||
import androidx.compose.material3.ButtonDefaults
|
import androidx.compose.material3.ButtonDefaults
|
||||||
@@ -15,24 +17,54 @@ import androidx.compose.material3.Icon
|
|||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.MutableState
|
import androidx.compose.runtime.MutableState
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
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.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import com.odweta.solon.ui.theme.PastelYellow
|
import com.odweta.solon.ui.theme.PastelYellow
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
|
||||||
private var timetableColor: MutableState<Color> = mutableStateOf(PastelYellow)
|
private var timetableColor: MutableState<Color> = mutableStateOf(PastelYellow)
|
||||||
private var marksColor: MutableState<Color> = mutableStateOf(Color.White)
|
private var marksColor: MutableState<Color> = mutableStateOf(Color.White)
|
||||||
private var menuColor: MutableState<Color> = mutableStateOf(Color.White)
|
private var menuColor: MutableState<Color> = mutableStateOf(Color.White)
|
||||||
|
var refreshButtonContentColor: MutableState<Color> = mutableStateOf(Color.White)
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun NavbarScreen(modifier: Modifier = Modifier) {
|
fun NavbarScreen(modifier: Modifier = Modifier) {
|
||||||
|
val ctx = LocalContext.current
|
||||||
|
val coscope = rememberCoroutineScope()
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
horizontalArrangement = Arrangement.Center,
|
horizontalArrangement = Arrangement.Center,
|
||||||
verticalAlignment = Alignment.CenterVertically
|
verticalAlignment = Alignment.CenterVertically
|
||||||
) {
|
) {
|
||||||
|
var spacerModifier = 30.dp
|
||||||
|
if (settings.showRefreshButton.checked.value) {
|
||||||
|
spacerModifier = 15.dp
|
||||||
|
Button(
|
||||||
|
onClick = {
|
||||||
|
fetchNewData(ctx, coscope)
|
||||||
|
refreshButtonContentColor.value = PastelYellow
|
||||||
|
},
|
||||||
|
colors = ButtonDefaults.buttonColors(
|
||||||
|
contentColor = refreshButtonContentColor.value,
|
||||||
|
containerColor = Color.Black
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Default.Refresh,
|
||||||
|
contentDescription = "Refresh Button",
|
||||||
|
modifier = Modifier.size(25.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.width(spacerModifier))
|
||||||
|
}
|
||||||
|
|
||||||
Button(
|
Button(
|
||||||
onClick = {
|
onClick = {
|
||||||
isShowing.value = IsShowing.Timetable
|
isShowing.value = IsShowing.Timetable
|
||||||
@@ -52,7 +84,7 @@ fun NavbarScreen(modifier: Modifier = Modifier) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer(modifier = Modifier.width(30.dp))
|
Spacer(modifier = Modifier.width(spacerModifier))
|
||||||
|
|
||||||
Button(
|
Button(
|
||||||
onClick = {
|
onClick = {
|
||||||
@@ -74,7 +106,7 @@ fun NavbarScreen(modifier: Modifier = Modifier) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer(modifier = Modifier.width(30.dp))
|
Spacer(modifier = Modifier.width(spacerModifier))
|
||||||
|
|
||||||
Button(
|
Button(
|
||||||
onClick = {
|
onClick = {
|
||||||
|
|||||||
@@ -58,10 +58,15 @@ class Network {
|
|||||||
internetAvail = true
|
internetAvail = true
|
||||||
userData = getUserDataJSON()
|
userData = getUserDataJSON()
|
||||||
Util.saveStringToFile(userDataFilePath, userData)
|
Util.saveStringToFile(userDataFilePath, userData)
|
||||||
if (!Parsing.userIsParent()) {
|
studentClass = if (!Parsing.userIsParent()) {
|
||||||
studentClass = JSONObject(
|
JSONObject(
|
||||||
Util.fileToString(userDataFilePath)
|
Util.fileToString(userDataFilePath)
|
||||||
).getJSONObject("class").get("name").toString()
|
).getJSONObject("class").get("name").toString()
|
||||||
|
} else {
|
||||||
|
// if the user is a parent, the class will be of their first child
|
||||||
|
JSONObject(
|
||||||
|
Util.fileToString(userDataFilePath)
|
||||||
|
).getJSONArray("children").getJSONObject(0).getString("className")
|
||||||
}
|
}
|
||||||
studentId = getStudentId()
|
studentId = getStudentId()
|
||||||
//syid = getSYID()
|
//syid = getSYID()
|
||||||
|
|||||||
@@ -269,6 +269,23 @@ class Parsing {
|
|||||||
auxSubjects.add(Subject.empty())
|
auxSubjects.add(Subject.empty())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// prepend free subjects when day does not start with subject number 1
|
||||||
|
val newSubjects: MutableList<Subject> = mutableListOf()
|
||||||
|
var n = auxSubjects[0].number.toInt()
|
||||||
|
while (n > 1) {
|
||||||
|
newSubjects.add(
|
||||||
|
Subject.freeSubject(
|
||||||
|
number = (n - 1).toString(),
|
||||||
|
start = "00:00",
|
||||||
|
end = "00:00"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
n -= 1
|
||||||
|
}
|
||||||
|
val finalSubjects: MutableList<Subject> = mutableListOf()
|
||||||
|
finalSubjects.addAll(newSubjects.reversed())
|
||||||
|
finalSubjects.addAll(auxSubjects)
|
||||||
|
|
||||||
for ((i, s) in auxSubjects.withIndex()) {
|
for ((i, s) in auxSubjects.withIndex()) {
|
||||||
if (s.free) {
|
if (s.free) {
|
||||||
s.start = auxSubjects[i-1].end
|
s.start = auxSubjects[i-1].end
|
||||||
@@ -279,7 +296,7 @@ class Parsing {
|
|||||||
val day = Day()
|
val day = Day()
|
||||||
day.name = name
|
day.name = name
|
||||||
day.date = date
|
day.date = date
|
||||||
day.subjects = auxSubjects
|
day.subjects = finalSubjects
|
||||||
|
|
||||||
// get rid of duplicates
|
// get rid of duplicates
|
||||||
val nextSubjects: MutableList<Subject> = mutableListOf()
|
val nextSubjects: MutableList<Subject> = mutableListOf()
|
||||||
|
|||||||
@@ -0,0 +1,143 @@
|
|||||||
|
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
|
||||||
|
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
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import com.odweta.solon.ui.theme.PastelYellow
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun SettingsScreen(modifier: Modifier = Modifier) {
|
||||||
|
// handle the back gesture (back swipe form side or back button on bottom android navbar)
|
||||||
|
BackHandler {
|
||||||
|
isShowing.value = IsShowing.Menu
|
||||||
|
}
|
||||||
|
|
||||||
|
val scrollState = rememberScrollState()
|
||||||
|
|
||||||
|
Column(modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.background(color = Color.Black)
|
||||||
|
.verticalScroll(scrollState)
|
||||||
|
) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(start = 5.dp)
|
||||||
|
) {
|
||||||
|
Button(
|
||||||
|
onClick = {
|
||||||
|
isShowing.value = IsShowing.Menu
|
||||||
|
},
|
||||||
|
colors = ButtonDefaults.buttonColors(
|
||||||
|
contentColor = Color.White,
|
||||||
|
containerColor = Color.Black
|
||||||
|
),
|
||||||
|
modifier = Modifier
|
||||||
|
.border(
|
||||||
|
width = 5.dp,
|
||||||
|
shape = RoundedCornerShape(roundedCornerDimen),
|
||||||
|
color = PastelYellow
|
||||||
|
)
|
||||||
|
.width(70.dp)
|
||||||
|
.height(70.dp)
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Default.ArrowBackIosNew,
|
||||||
|
contentDescription = "Back icon",
|
||||||
|
modifier = Modifier.size(40.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} // back button
|
||||||
|
|
||||||
|
Spacer(Modifier.height(10.dp))
|
||||||
|
|
||||||
|
SettingsTableRow(settings.useSvobodaMode)
|
||||||
|
|
||||||
|
Spacer(Modifier.height(10.dp))
|
||||||
|
|
||||||
|
SettingsTableRow(settings.useAmoledMode)
|
||||||
|
|
||||||
|
Spacer(Modifier.height(10.dp))
|
||||||
|
|
||||||
|
SettingsTableRow(settings.showRefreshButton)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun SettingsTableRow(setting: Setting) {
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(10.dp)
|
||||||
|
.background(color = Color.Black, shape = RoundedCornerShape(roundedCornerDimen))
|
||||||
|
.fillMaxWidth(),
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = setting.name,
|
||||||
|
textAlign = TextAlign.Start,
|
||||||
|
color = Color.White,
|
||||||
|
fontSize = 20.sp
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.weight(1f))
|
||||||
|
|
||||||
|
Switch(
|
||||||
|
checked = setting.checked.value,
|
||||||
|
onCheckedChange = {
|
||||||
|
setting.checked.value = it
|
||||||
|
when (setting.id) {
|
||||||
|
SettingsId.Svoboda -> settings.useSvobodaMode = setting
|
||||||
|
SettingsId.Amoled -> settings.useAmoledMode = setting
|
||||||
|
SettingsId.RefreshButton -> settings.showRefreshButton = setting
|
||||||
|
}
|
||||||
|
Util.saveStringToFile(settingsDataFilePath, settings.toString())
|
||||||
|
},
|
||||||
|
colors = SwitchColors(
|
||||||
|
uncheckedThumbColor = Color.Black,
|
||||||
|
uncheckedTrackColor = Color.DarkGray,
|
||||||
|
uncheckedBorderColor = Color.DarkGray,
|
||||||
|
checkedThumbColor = Color.Black,
|
||||||
|
checkedTrackColor = PastelYellow,
|
||||||
|
checkedBorderColor = PastelYellow,
|
||||||
|
checkedIconColor = Color.White,
|
||||||
|
uncheckedIconColor = Color.White,
|
||||||
|
disabledCheckedThumbColor = Color.Black,
|
||||||
|
disabledCheckedTrackColor = Color.Black,
|
||||||
|
disabledCheckedBorderColor = Color.Black,
|
||||||
|
disabledCheckedIconColor = Color.Black,
|
||||||
|
disabledUncheckedThumbColor = Color.Black,
|
||||||
|
disabledUncheckedTrackColor = Color.Black,
|
||||||
|
disabledUncheckedBorderColor = Color.Black,
|
||||||
|
disabledUncheckedIconColor = Color.Black
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,20 +2,18 @@ package com.odweta.solon
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
|
import androidx.activity.compose.BackHandler
|
||||||
import androidx.compose.foundation.Image
|
import androidx.compose.foundation.Image
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.border
|
import androidx.compose.foundation.border
|
||||||
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.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.layout.width
|
import androidx.compose.foundation.layout.width
|
||||||
import androidx.compose.foundation.rememberScrollState
|
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.foundation.verticalScroll
|
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.Visibility
|
import androidx.compose.material.icons.filled.Visibility
|
||||||
import androidx.compose.material.icons.filled.VisibilityOff
|
import androidx.compose.material.icons.filled.VisibilityOff
|
||||||
@@ -27,8 +25,6 @@ import androidx.compose.runtime.mutableStateOf
|
|||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.Alignment
|
|
||||||
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
|
||||||
@@ -40,6 +36,9 @@ import com.odweta.solon.ui.theme.PastelYellow
|
|||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import androidx.compose.foundation.layout.*
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
|
||||||
private var buttonText: MutableState<String> = mutableStateOf("Přihlásit se")
|
private var buttonText: MutableState<String> = mutableStateOf("Přihlásit se")
|
||||||
|
|
||||||
@@ -96,6 +95,7 @@ fun signInButtonCallback(ctx: Context, coscope: CoroutineScope, buttonText: Stri
|
|||||||
Account.save(acc)
|
Account.save(acc)
|
||||||
signedInAndReadyToLaunch.value = true
|
signedInAndReadyToLaunch.value = true
|
||||||
screenToShow.value = Screen.Splash
|
screenToShow.value = Screen.Splash
|
||||||
|
fetchNewData(ctx, coscope)
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(
|
Toast.makeText(
|
||||||
ctx,
|
ctx,
|
||||||
@@ -106,41 +106,48 @@ fun signInButtonCallback(ctx: Context, coscope: CoroutineScope, buttonText: Stri
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
|
||||||
@Composable
|
@Composable
|
||||||
fun SignInScreen() {
|
fun SignInScreen() {
|
||||||
|
// handle the back gesture (back swipe form side or back button on bottom android navbar)
|
||||||
|
BackHandler {
|
||||||
|
screenToShow.value = Screen.Main
|
||||||
|
}
|
||||||
|
|
||||||
var usernameText by remember { mutableStateOf("") }
|
var usernameText by remember { mutableStateOf("") }
|
||||||
var passwordText by remember { mutableStateOf("") }
|
var passwordText by remember { mutableStateOf("") }
|
||||||
val ctx = LocalContext.current
|
val ctx = LocalContext.current
|
||||||
val coscope = rememberCoroutineScope()
|
val coscope = rememberCoroutineScope()
|
||||||
var isPasswordVisible by remember { mutableStateOf(false) } // State for visibility toggle
|
var isPasswordVisible by remember { mutableStateOf(false) } // State for visibility toggle
|
||||||
val visualTransformation = if (isPasswordVisible) VisualTransformation.None else PasswordVisualTransformation()
|
val visualTransformation = if (isPasswordVisible) VisualTransformation.None else PasswordVisualTransformation()
|
||||||
val scrollState = rememberScrollState()
|
|
||||||
|
|
||||||
Box(
|
Column(
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier
|
||||||
contentAlignment = Alignment.Center
|
.fillMaxSize()
|
||||||
|
.background(Color.Black)
|
||||||
|
.imePadding(),
|
||||||
|
verticalArrangement = Arrangement.Center,
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
) {
|
) {
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize()
|
.wrapContentSize(),
|
||||||
.background(Color.Black)
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
.verticalScroll(scrollState),
|
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
|
||||||
verticalArrangement = Arrangement.Center
|
|
||||||
) {
|
) {
|
||||||
Image(
|
Image(
|
||||||
painter = painterResource(R.drawable.solon_just_yellow),
|
painter = painterResource(R.drawable.solon_just_yellow),
|
||||||
contentDescription = "Solon logo",
|
contentDescription = "Solon logo",
|
||||||
modifier = Modifier.size(230.dp)
|
modifier = Modifier.size(200.dp)
|
||||||
)
|
)
|
||||||
|
|
||||||
TextField(
|
TextField(
|
||||||
value = usernameText,
|
value = usernameText,
|
||||||
onValueChange = { input -> usernameText = input },
|
onValueChange = { input -> usernameText = input },
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.border(width = 5.dp, color = PastelYellow, shape = RoundedCornerShape(
|
.border(
|
||||||
roundedCornerDimen))
|
width = 5.dp, color = PastelYellow, shape = RoundedCornerShape(
|
||||||
|
roundedCornerDimen
|
||||||
|
)
|
||||||
|
)
|
||||||
.width(230.dp),
|
.width(230.dp),
|
||||||
colors = TextFieldDefaults.colors(
|
colors = TextFieldDefaults.colors(
|
||||||
focusedTextColor = Color.White, // White text
|
focusedTextColor = Color.White, // White text
|
||||||
@@ -214,4 +221,4 @@ fun SignInScreen() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package com.odweta.solon
|
package com.odweta.solon
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.text.format.Time
|
import android.util.Log
|
||||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
@@ -13,16 +13,29 @@ 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.Image
|
||||||
import androidx.compose.foundation.border
|
import androidx.compose.foundation.border
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxHeight
|
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
|
||||||
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.material3.AlertDialog
|
||||||
|
import androidx.compose.material3.BasicAlertDialog
|
||||||
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.TextField
|
||||||
|
import androidx.compose.material3.TextFieldColors
|
||||||
|
import androidx.compose.material3.TextFieldDefaults
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
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.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
@@ -31,22 +44,89 @@ 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.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.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 java.security.MessageDigest
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
import java.time.LocalDateTime
|
|
||||||
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)
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun TimetableScreen() {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize(),
|
||||||
|
contentAlignment = Alignment.BottomCenter
|
||||||
|
) {
|
||||||
|
DayPager()
|
||||||
|
if (showDetailDialog.value) {
|
||||||
|
DetailDialog()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("UnrememberedMutableState")
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
@Composable
|
||||||
|
fun DetailDialog(modifier: Modifier = Modifier) {
|
||||||
|
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)
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
if (lectureNotes[selectedLecture] == null) {
|
||||||
|
lectureNotes[selectedLecture] = mutableStateOf("")
|
||||||
|
}
|
||||||
|
|
||||||
|
TextField(
|
||||||
|
value = lectureNotes[selectedLecture]!!.value,
|
||||||
|
onValueChange = { newText: String ->
|
||||||
|
lectureNotes[selectedLecture]!!.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 TimetableScreen() {
|
fun DayPager(modifier: Modifier = Modifier) {
|
||||||
val pagerState = rememberPagerState( pageCount = { days.size } )
|
val pagerState = rememberPagerState(pageCount = { days.size })
|
||||||
HorizontalPager(
|
HorizontalPager(
|
||||||
state = pagerState,
|
state = pagerState,
|
||||||
modifier = Modifier.fillMaxSize()
|
modifier = Modifier.fillMaxSize()
|
||||||
@@ -85,9 +165,19 @@ fun isTimeBetween(givenTime: LocalTime, startTime: LocalTime, endTime: LocalTime
|
|||||||
@SuppressLint("ModifierFactoryExtensionFunction")
|
@SuppressLint("ModifierFactoryExtensionFunction")
|
||||||
@Composable
|
@Composable
|
||||||
fun subjectModifier(d: Day, s: Subject, lectureNumber: Int): Modifier {
|
fun subjectModifier(d: Day, s: Subject, lectureNumber: Int): Modifier {
|
||||||
|
var day = d.date.split(".")[0].replace(" ", "")
|
||||||
|
var month = d.date.split(".")[1].replace(" ", "")
|
||||||
|
if (day.length < 2) {
|
||||||
|
day = "0$day"
|
||||||
|
}
|
||||||
|
|
||||||
|
if (month.length < 2) {
|
||||||
|
month = "0$month"
|
||||||
|
}
|
||||||
|
|
||||||
val dayFormatter = DateTimeFormatter.ofPattern("dd. MM. yyyy")
|
val dayFormatter = DateTimeFormatter.ofPattern("dd. MM. yyyy")
|
||||||
val hourFormatter = DateTimeFormatter.ofPattern("HH:mm:ss")
|
val hourFormatter = DateTimeFormatter.ofPattern("HH:mm:ss")
|
||||||
val dateParsed = LocalDate.parse(d.date + " " + LocalDate.now().year, dayFormatter)
|
val dateParsed = LocalDate.parse("$day. $month." + " " + LocalDate.now().year, dayFormatter)
|
||||||
val startTimeParsed = LocalTime.parse(s.start + ":00", hourFormatter)
|
val startTimeParsed = LocalTime.parse(s.start + ":00", hourFormatter)
|
||||||
val endTimeParsed = LocalTime.parse(s.end + ":00", hourFormatter)
|
val endTimeParsed = LocalTime.parse(s.end + ":00", hourFormatter)
|
||||||
|
|
||||||
@@ -98,28 +188,34 @@ fun subjectModifier(d: Day, s: Subject, lectureNumber: Int): Modifier {
|
|||||||
currentLectureNumber = lectureNumber
|
currentLectureNumber = lectureNumber
|
||||||
}
|
}
|
||||||
|
|
||||||
return if (lectureNumber == currentLectureNumber && dateParsed == todayDate) {
|
val m = if (settings.useAmoledMode.checked.value) {
|
||||||
Modifier
|
Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.height(100.dp)
|
.height(70.dp)
|
||||||
.background(
|
|
||||||
color = getSubjectColor(s, true), // decide on the color (transparent)
|
|
||||||
shape = RoundedCornerShape(roundedCornerDimen)
|
|
||||||
)
|
|
||||||
.border(
|
.border(
|
||||||
width = 5.dp,
|
width = borderWidthDimen,
|
||||||
color = getSubjectColor(s, false),
|
color = getSubjectColor(s, false), // decide on the color (transparent)
|
||||||
shape = RoundedCornerShape(roundedCornerDimen)
|
shape = RoundedCornerShape(roundedCornerDimen)
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
Modifier
|
Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.height(100.dp)
|
.height(70.dp)
|
||||||
.background(
|
.background(
|
||||||
color = getSubjectColor(s, true), // decide on the color (transparent)
|
color = getSubjectColor(s, true), // decide on the color (transparent)
|
||||||
shape = RoundedCornerShape(roundedCornerDimen)
|
shape = RoundedCornerShape(roundedCornerDimen)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return if (lectureNumber == currentLectureNumber && dateParsed == todayDate) {
|
||||||
|
m.border(
|
||||||
|
width = borderWidthDimen,
|
||||||
|
color = getSubjectColor(s, false),
|
||||||
|
shape = RoundedCornerShape(roundedCornerDimen)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
m
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@@ -138,7 +234,7 @@ private fun DayScreen(day: Day) {
|
|||||||
Text(
|
Text(
|
||||||
text = "${day.name} ${day.date}",
|
text = "${day.name} ${day.date}",
|
||||||
color = Color.White,
|
color = Color.White,
|
||||||
fontSize = 30.sp,
|
fontSize = 26.sp,
|
||||||
fontWeight = FontWeight.Bold,
|
fontWeight = FontWeight.Bold,
|
||||||
fontStyle = FontStyle.Italic
|
fontStyle = FontStyle.Italic
|
||||||
)
|
)
|
||||||
@@ -152,12 +248,42 @@ 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)
|
||||||
|
val amoledModifier = if (settings.useAmoledMode.checked.value) {
|
||||||
|
Modifier
|
||||||
|
.width(50.dp)
|
||||||
|
.fillMaxHeight()
|
||||||
|
.border(
|
||||||
|
width = borderWidthDimen,
|
||||||
|
color = getSubjectColor(
|
||||||
|
subject,
|
||||||
|
false
|
||||||
|
),
|
||||||
|
shape = RoundedCornerShape(roundedCornerDimen)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
Modifier
|
||||||
|
.width(50.dp)
|
||||||
|
.fillMaxHeight()
|
||||||
|
.background(
|
||||||
|
color = getSubjectColor(
|
||||||
|
subject,
|
||||||
|
true
|
||||||
|
),
|
||||||
|
shape = RoundedCornerShape(roundedCornerDimen)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
if (day.subjects.indexOf(subject) > 0) {
|
if (day.subjects.indexOf(subject) > 0) {
|
||||||
Box(modifier = Modifier.height(10.dp)) {
|
Box(modifier = Modifier.height(10.dp)) {
|
||||||
if (subject.name == day.subjects[day.subjects.indexOf(subject) - 1].name) {
|
if (subject.name == day.subjects[day.subjects.indexOf(subject) - 1].name) {
|
||||||
|
val drawable =
|
||||||
|
if (subject.free) { R.drawable.squiggly_line_green }
|
||||||
|
else { R.drawable.squiggly_line_yellow }
|
||||||
|
|
||||||
Image(
|
Image(
|
||||||
painter = painterResource(R.drawable.squiggly_line_yellow),
|
painter = painterResource(drawable),
|
||||||
contentDescription = "Spojovač stejných předmětů",
|
contentDescription = "Spojovač stejných předmětů",
|
||||||
modifier = Modifier.fillMaxSize()
|
modifier = Modifier.fillMaxSize()
|
||||||
)
|
)
|
||||||
@@ -165,115 +291,140 @@ private fun DayScreen(day: Day) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Row(
|
Box (modifier = subjectModifier(day, subject, subject.number.toInt())) {
|
||||||
modifier = subjectModifier(day, subject, subject.number.toInt())
|
Row {
|
||||||
) {
|
if (subject.substitute != "2") {
|
||||||
if (subject.substitute != "2") {
|
Box(
|
||||||
Box(
|
modifier = amoledModifier,
|
||||||
modifier = Modifier
|
contentAlignment = Alignment.Center
|
||||||
.width(50.dp)
|
) {
|
||||||
.fillMaxHeight()
|
|
||||||
.background(
|
|
||||||
color = getSubjectColor(
|
|
||||||
subject,
|
|
||||||
true
|
|
||||||
), // decide on the color (not transparent)
|
|
||||||
shape = RoundedCornerShape(roundedCornerDimen)
|
|
||||||
),
|
|
||||||
contentAlignment = Alignment.Center
|
|
||||||
) {
|
|
||||||
Text(
|
|
||||||
text = subject.number,
|
|
||||||
fontSize = 30.sp,
|
|
||||||
color = Color.White
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (subject.substitute != "2") {
|
|
||||||
Column(
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxHeight()
|
|
||||||
.padding(start = 20.dp),
|
|
||||||
verticalArrangement = Arrangement.Center,
|
|
||||||
horizontalAlignment = Alignment.Start
|
|
||||||
) {
|
|
||||||
if (!subject.free) {
|
|
||||||
Text(
|
Text(
|
||||||
text = subject.name.uppercase(),
|
text = subject.number,
|
||||||
|
fontSize = 30.sp,
|
||||||
|
color = Color.White
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (subject.substitute != "2") {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxHeight()
|
||||||
|
.padding(start = 20.dp),
|
||||||
|
verticalArrangement = Arrangement.Center,
|
||||||
|
horizontalAlignment = Alignment.Start
|
||||||
|
) {
|
||||||
|
if (!subject.free) {
|
||||||
|
if (subject.substitute == "1") {
|
||||||
|
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 = subject.name.uppercase(),
|
||||||
|
color = Color.White,
|
||||||
|
fontSize = 25.sp,
|
||||||
|
fontWeight = FontWeight.Bold
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = subject.place,
|
||||||
color = Color.White,
|
color = Color.White,
|
||||||
fontSize = 25.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
|
fontWeight = FontWeight.Bold
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
Text(
|
|
||||||
text = subject.place,
|
|
||||||
color = Color.White,
|
|
||||||
fontSize = 21.sp
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
Column(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
|
.weight(1f)
|
||||||
.fillMaxHeight()
|
.fillMaxHeight()
|
||||||
.padding(start = 20.dp),
|
.padding(vertical = 5.dp),
|
||||||
verticalArrangement = Arrangement.Center,
|
contentAlignment = Alignment.Center
|
||||||
horizontalAlignment = Alignment.CenterHorizontally
|
|
||||||
) {
|
) {
|
||||||
Text(
|
if (settings.useSvobodaMode.checked.value) {
|
||||||
text = subject.name,
|
if (
|
||||||
color = Color.White,
|
subject.teacher == "Jindřich Svoboda" &&
|
||||||
fontSize = 20.sp,
|
studentClass == "5. G"
|
||||||
fontWeight = FontWeight.Bold
|
) {
|
||||||
)
|
Image(
|
||||||
|
painter = painterResource(R.drawable.spock),
|
||||||
|
contentDescription = "Spock",
|
||||||
|
modifier = Modifier.fillMaxSize()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Box(
|
if (subject.substitute != "2") {
|
||||||
modifier = Modifier
|
Column(
|
||||||
.weight(1f)
|
modifier = Modifier
|
||||||
.fillMaxHeight()
|
.fillMaxHeight()
|
||||||
.padding(vertical = 5.dp),
|
.padding(end = 10.dp),
|
||||||
contentAlignment = Alignment.Center
|
verticalArrangement = Arrangement.Center,
|
||||||
) {
|
horizontalAlignment = Alignment.End
|
||||||
if (!Parsing.userIsParent()) {
|
|
||||||
if (
|
|
||||||
subject.teacher == "Jindřich Svoboda" &&
|
|
||||||
studentClass == "5. G"
|
|
||||||
) {
|
) {
|
||||||
Image(
|
// show only for non prepended free lectures
|
||||||
painter = painterResource(R.drawable.spock),
|
if ((subject.free && subject.start != "00:00" && subject.end != "00:00") || !subject.free) {
|
||||||
contentDescription = "Spock",
|
Text(
|
||||||
modifier = Modifier.fillMaxSize()
|
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
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (subject.substitute != "2") {
|
Box(modifier = Modifier
|
||||||
Column(
|
.fillMaxSize()
|
||||||
modifier = Modifier
|
.zIndex(99f)
|
||||||
.fillMaxHeight()
|
.clickable {
|
||||||
.padding(end = 20.dp),
|
selectedLecture = lectureId
|
||||||
verticalArrangement = Arrangement.Center,
|
showDetailDialog.value = true
|
||||||
horizontalAlignment = Alignment.End
|
})
|
||||||
) {
|
|
||||||
Text(
|
|
||||||
text = "${subject.start}–${subject.end}",
|
|
||||||
color = Color.White,
|
|
||||||
fontSize = 21.sp
|
|
||||||
)
|
|
||||||
|
|
||||||
if (!subject.free) {
|
|
||||||
Text(
|
|
||||||
text = subject.teacher,
|
|
||||||
color = Color.White,
|
|
||||||
fontSize = 12.sp
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,46 @@
|
|||||||
package com.odweta.solon
|
package com.odweta.solon
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ToolbarScreen() {
|
fun ToolbarScreen() {
|
||||||
Text(
|
// make the font size adaptive relative to the length of the user's name
|
||||||
text = toolbarText.value,
|
var toolbarTextSizeAdaptive by remember { mutableStateOf(25.sp) }
|
||||||
fontSize = 25.sp,
|
|
||||||
color = Color.White
|
if (toolbarText.value.length > 28) {
|
||||||
)
|
toolbarTextSizeAdaptive = 20.sp
|
||||||
|
}
|
||||||
|
|
||||||
|
if (toolbarText.value.length > 32) {
|
||||||
|
toolbarTextSizeAdaptive = 16.sp
|
||||||
|
}
|
||||||
|
|
||||||
|
if (toolbarText.value.length > 40) {
|
||||||
|
toolbarTextSizeAdaptive = 12.sp
|
||||||
|
}
|
||||||
|
|
||||||
|
if (toolbarText.value.length > 45) {
|
||||||
|
toolbarTextSizeAdaptive = 10.sp
|
||||||
|
}
|
||||||
|
|
||||||
|
Box(modifier = Modifier.padding(10.dp)) {
|
||||||
|
Text(
|
||||||
|
text = toolbarText.value,
|
||||||
|
fontSize = toolbarTextSizeAdaptive,
|
||||||
|
color = Color.White
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,33 +1,22 @@
|
|||||||
package com.odweta.solon
|
package com.odweta.solon
|
||||||
|
|
||||||
import android.animation.Animator
|
|
||||||
import android.animation.AnimatorInflater
|
|
||||||
import android.animation.AnimatorListenerAdapter
|
|
||||||
import android.animation.ArgbEvaluator
|
|
||||||
import android.animation.ValueAnimator
|
|
||||||
import android.app.ActivityManager
|
import android.app.ActivityManager
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.res.ColorStateList
|
import android.content.pm.PackageManager
|
||||||
import android.content.res.Resources
|
|
||||||
import android.graphics.drawable.Drawable
|
|
||||||
import android.graphics.drawable.GradientDrawable
|
|
||||||
import android.net.ConnectivityManager
|
import android.net.ConnectivityManager
|
||||||
import android.net.NetworkCapabilities
|
import android.net.NetworkCapabilities
|
||||||
import android.os.Handler
|
import android.os.Build
|
||||||
import android.util.DisplayMetrics
|
import android.util.DisplayMetrics
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
import android.view.animation.AnimationUtils
|
import androidx.compose.runtime.MutableState
|
||||||
import android.widget.Button
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.core.content.pm.PackageInfoCompat
|
||||||
import androidx.core.content.ContextCompat
|
|
||||||
import androidx.core.content.res.ResourcesCompat
|
|
||||||
import com.odweta.solon.ui.theme.PastelGreenTransparent
|
|
||||||
import com.odweta.solon.ui.theme.PastelOrangeTransparent
|
|
||||||
import com.odweta.solon.ui.theme.PastelRedTransparent
|
|
||||||
import com.odweta.solon.ui.theme.PastelYellowTransparent
|
|
||||||
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
|
||||||
|
|
||||||
class Util {
|
class Util {
|
||||||
companion object {
|
companion object {
|
||||||
@@ -130,22 +119,20 @@ 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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
fun pixelsToDp(pixels: Int, resources: Resources): Int {
|
|
||||||
return (pixels * resources.displayMetrics.density).toInt()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun avg(marks: MutableList<Mark>): String {
|
fun avg(marks: MutableList<Mark>): String {
|
||||||
var sum = 0f
|
var sum = 0f
|
||||||
var len = 0
|
var len = 0
|
||||||
@@ -166,7 +153,8 @@ class Util {
|
|||||||
weights.add(mark.weight.toFloat())
|
weights.add(mark.weight.toFloat())
|
||||||
}
|
}
|
||||||
|
|
||||||
return String.format("%.2f", (sum / sum(weights))).replace(',', '.')
|
return "${Math.round(sum / sum(weights) * 100f) / 100f}".replace(",", ".")
|
||||||
|
//return String.format("%.2f", (sum / sum(weights))).replace(',', '.')
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun sum(nums: List<Float>): Float {
|
private fun sum(nums: List<Float>): Float {
|
||||||
@@ -220,5 +208,100 @@ class Util {
|
|||||||
|
|
||||||
return d
|
return d
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
data class AppVersion(
|
||||||
|
val versionName: String,
|
||||||
|
val versionNumber: Long,
|
||||||
|
)
|
||||||
|
|
||||||
|
fun getAppVersion(
|
||||||
|
context: Context,
|
||||||
|
): AppVersion? {
|
||||||
|
return try {
|
||||||
|
val packageManager = context.packageManager
|
||||||
|
val packageName = context.packageName
|
||||||
|
val packageInfo = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||||
|
packageManager.getPackageInfo(
|
||||||
|
packageName,
|
||||||
|
PackageManager.PackageInfoFlags.of(0)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
packageManager.getPackageInfo(packageName, 0)
|
||||||
|
}
|
||||||
|
AppVersion(
|
||||||
|
versionName = packageInfo.versionName,
|
||||||
|
versionNumber = PackageInfoCompat.getLongVersionCode(packageInfo),
|
||||||
|
)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun stringToSettingsData(s: String): SettingsData {
|
||||||
|
val settings = s.split("\n")
|
||||||
|
val auxSettingsData = SettingsData()
|
||||||
|
val useSvobodaMode = settings[0].split("#")
|
||||||
|
val useAmoledMode = settings[1].split("#")
|
||||||
|
val showRefreshButton = settings[2].split("#")
|
||||||
|
|
||||||
|
auxSettingsData.useSvobodaMode.id = SettingsId.Svoboda
|
||||||
|
auxSettingsData.useSvobodaMode.name = useSvobodaMode[1]
|
||||||
|
auxSettingsData.useSvobodaMode.checked.value = useSvobodaMode[2].toBoolean()
|
||||||
|
|
||||||
|
auxSettingsData.useAmoledMode.id = SettingsId.Amoled
|
||||||
|
auxSettingsData.useAmoledMode.name = useAmoledMode[1]
|
||||||
|
auxSettingsData.useAmoledMode.checked.value = useAmoledMode[2].toBoolean()
|
||||||
|
|
||||||
|
auxSettingsData.showRefreshButton.id = SettingsId.RefreshButton
|
||||||
|
auxSettingsData.showRefreshButton.name = showRefreshButton[1]
|
||||||
|
auxSettingsData.showRefreshButton.checked.value = showRefreshButton[2].toBoolean()
|
||||||
|
|
||||||
|
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<String>> {
|
||||||
|
val hashMap = HashMap<Int, MutableState<String>>()
|
||||||
|
val lines = fileToString(filePath).lines()
|
||||||
|
for (line in lines) {
|
||||||
|
if (line.isBlank()) continue
|
||||||
|
|
||||||
|
val parts = line.split(",")
|
||||||
|
|
||||||
|
if (parts.size == 2) {
|
||||||
|
val key = parts[0].trim().toInt()
|
||||||
|
val value = parts[1].trim()
|
||||||
|
hashMap[key] = mutableStateOf("")
|
||||||
|
hashMap[key]!!.value = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return hashMap
|
||||||
|
}
|
||||||
|
|
||||||
|
fun hashMapToCsv(hashMap: HashMap<Int, MutableState<String>>): String {
|
||||||
|
var result = ""
|
||||||
|
for ((key, value) in hashMap) {
|
||||||
|
result += "$key,${value.value}\n"
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
fun loadLectureIds() {
|
||||||
|
lectureNotes = csvToHashMap(lectureNotesFilePath)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun saveLectureIds() {
|
||||||
|
val toSave = hashMapToCsv(lectureNotes)
|
||||||
|
saveStringToFile(lectureNotesFilePath, toSave)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -19,11 +19,13 @@ val White = Color(0xFFFFFFFF)
|
|||||||
val Transparent = Color(0x00000000)
|
val Transparent = Color(0x00000000)
|
||||||
|
|
||||||
val PastelRed = Color(0xFFFF6666)
|
val PastelRed = Color(0xFFFF6666)
|
||||||
|
val PastelOrangeDark = Color(0xFFDC6421)
|
||||||
val PastelGreen = Color(0xFF00CC99)
|
val PastelGreen = Color(0xFF00CC99)
|
||||||
val PastelOrange = Color(0xFFFF9933)
|
val PastelOrange = Color(0xFFFF9933)
|
||||||
val PastelYellow = Color(0xFFFFCC33)
|
val PastelYellow = Color(0xFFFFCC33)
|
||||||
|
|
||||||
val PastelRedTransparent = Color(0x50FF6666)
|
val PastelRedTransparent = Color(0x50FF6666)
|
||||||
|
val PastelOrangeDarkTransparent = Color(0x50DC6421)
|
||||||
val PastelGreenTransparent = Color(0x5000CC99)
|
val PastelGreenTransparent = Color(0x5000CC99)
|
||||||
val PastelOrangeTransparent = Color(0x50FF9933)
|
val PastelOrangeTransparent = Color(0x50FF9933)
|
||||||
val PastelYellowTransparent = Color(0x50FFCC33)
|
val PastelYellowTransparent = Color(0x50FFCC33)
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 9.8 KiB |
|
After Width: | Height: | Size: 7.4 KiB |
@@ -1,53 +1,74 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<vector
|
<vector
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:height="108dp"
|
android:height="108dp"
|
||||||
android:width="108dp"
|
android:width="108dp"
|
||||||
android:viewportHeight="108"
|
android:viewportHeight="108"
|
||||||
android:viewportWidth="108">
|
android:viewportWidth="108"
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<!-- Background Color -->
|
<path android:fillColor="#3DDC84"
|
||||||
<path android:fillColor="#000000"
|
android:pathData="M0,0h108v108h-108z"/>
|
||||||
android:pathData="M0,0h108v108h-108z"/>
|
<path android:fillColor="#00000000" android:pathData="M9,0L9,108"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
<!-- Vertical Grid Lines -->
|
<path android:fillColor="#00000000" android:pathData="M19,0L19,108"
|
||||||
<path android:fillColor="#00000000"
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
android:pathData="M9,0L9,108"
|
<path android:fillColor="#00000000" android:pathData="M29,0L29,108"
|
||||||
android:strokeColor="#000000"
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
android:strokeWidth="0.8"/>
|
<path android:fillColor="#00000000" android:pathData="M39,0L39,108"
|
||||||
<path android:fillColor="#00000000"
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
android:pathData="M19,0L19,108"
|
<path android:fillColor="#00000000" android:pathData="M49,0L49,108"
|
||||||
android:strokeColor="#000000"
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
android:strokeWidth="0.8"/>
|
<path android:fillColor="#00000000" android:pathData="M59,0L59,108"
|
||||||
<path android:fillColor="#00000000"
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
android:pathData="M29,0L29,108"
|
<path android:fillColor="#00000000" android:pathData="M69,0L69,108"
|
||||||
android:strokeColor="#000000"
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
android:strokeWidth="0.8"/>
|
<path android:fillColor="#00000000" android:pathData="M79,0L79,108"
|
||||||
<!-- Repeat the lines for remaining grid -->
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M89,0L89,108"
|
||||||
<!-- Horizontal Grid Lines -->
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
<path android:fillColor="#00000000"
|
<path android:fillColor="#00000000" android:pathData="M99,0L99,108"
|
||||||
android:pathData="M0,9L108,9"
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
android:strokeColor="#000000"
|
<path android:fillColor="#00000000" android:pathData="M0,9L108,9"
|
||||||
android:strokeWidth="0.8"/>
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
<path android:fillColor="#00000000"
|
<path android:fillColor="#00000000" android:pathData="M0,19L108,19"
|
||||||
android:pathData="M0,19L108,19"
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
android:strokeColor="#000000"
|
<path android:fillColor="#00000000" android:pathData="M0,29L108,29"
|
||||||
android:strokeWidth="0.8"/>
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
<path android:fillColor="#00000000"
|
<path android:fillColor="#00000000" android:pathData="M0,39L108,39"
|
||||||
android:pathData="M0,29L108,29"
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
android:strokeColor="#000000"
|
<path android:fillColor="#00000000" android:pathData="M0,49L108,49"
|
||||||
android:strokeWidth="0.8"/>
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
<!-- Repeat the lines for remaining grid -->
|
<path android:fillColor="#00000000" android:pathData="M0,59L108,59"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
<!-- Additional Grid Lines within the Central Area -->
|
<path android:fillColor="#00000000" android:pathData="M0,69L108,69"
|
||||||
<path android:fillColor="#00000000"
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
android:pathData="M19,29L89,29"
|
<path android:fillColor="#00000000" android:pathData="M0,79L108,79"
|
||||||
android:strokeColor="#000000"
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
android:strokeWidth="0.8"/>
|
<path android:fillColor="#00000000" android:pathData="M0,89L108,89"
|
||||||
<path android:fillColor="#00000000"
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
android:pathData="M19,39L89,39"
|
<path android:fillColor="#00000000" android:pathData="M0,99L108,99"
|
||||||
android:strokeColor="#000000"
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
android:strokeWidth="0.8"/>
|
<path android:fillColor="#00000000" android:pathData="M19,29L89,29"
|
||||||
<!-- Repeat similar paths for the remaining inner lines -->
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M19,39L89,39"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M19,49L89,49"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M19,59L89,59"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M19,69L89,69"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M19,79L89,79"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M29,19L29,89"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M39,19L39,89"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M49,19L49,89"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M59,19L59,89"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M69,19L69,89"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M79,19L79,89"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
</vector>
|
</vector>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 6.0 KiB |
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<background android:drawable="@drawable/launcher_background"/>
|
<background android:drawable="@mipmap/launcher_background"/>
|
||||||
<foreground android:drawable="@mipmap/launcher_foreground"/>
|
<foreground android:drawable="@mipmap/launcher_foreground"/>
|
||||||
</adaptive-icon>
|
</adaptive-icon>
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<background android:drawable="@drawable/launcher_background"/>
|
<background android:drawable="@mipmap/launcher_background"/>
|
||||||
<foreground android:drawable="@mipmap/launcher_foreground"/>
|
<foreground android:drawable="@mipmap/launcher_foreground"/>
|
||||||
</adaptive-icon>
|
</adaptive-icon>
|
||||||
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 746 B |
|
After Width: | Height: | Size: 40 B |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 650 B |
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 912 B After Width: | Height: | Size: 590 B |
|
After Width: | Height: | Size: 42 B |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 464 B |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 42 B |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 804 B |
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 48 B |
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 4.0 KiB |
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 48 B |
|
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 7.1 KiB After Width: | Height: | Size: 5.5 KiB |
@@ -5,7 +5,7 @@
|
|||||||
-->
|
-->
|
||||||
<data-extraction-rules>
|
<data-extraction-rules>
|
||||||
<cloud-backup>
|
<cloud-backup>
|
||||||
<!-- TODO: Use <include> and <exclude> to control what is backed up.
|
<!-- xTODO: Use <include> and <exclude> to control what is backed up.
|
||||||
<include .../>
|
<include .../>
|
||||||
<exclude .../>
|
<exclude .../>
|
||||||
-->
|
-->
|
||||||
|
|||||||
@@ -20,4 +20,5 @@ kotlin.code.style=official
|
|||||||
# Enables namespacing of each library's R class so that its R class includes only the
|
# Enables namespacing of each library's R class so that its R class includes only the
|
||||||
# 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=~/Android/Sdk
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
[versions]
|
[versions]
|
||||||
accompanistCoil = "0.30.1"
|
accompanistCoil = "0.30.1"
|
||||||
agp = "8.7.1"
|
agp = "8.7.2"
|
||||||
coilCompose = "2.4.0"
|
coilCompose = "2.4.0"
|
||||||
glide = "4.16.0"
|
glide = "4.16.0"
|
||||||
kotlin = "2.0.0"
|
kotlin = "2.0.0"
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
cp app/build/outputs/apk/release/com.odweta.solon_$1.apk ../release/
|
||||||