Update colors

Add average to NotenActivity
Fix Bugs in NotenActivity and FachActivity
This commit is contained in:
BuildTools
2024-04-18 13:22:45 +02:00
parent dbfed92a42
commit 888d737965
12 changed files with 261 additions and 80 deletions

View File

@@ -50,14 +50,16 @@ fun AboutContent(activity: ComponentActivity){
colors = TopAppBarDefaults.centerAlignedTopAppBarColors(MaterialTheme.colorScheme.primaryContainer),
title = {
Text(text = "About",
style = MaterialTheme.typography.headlineSmall
style = MaterialTheme.typography.headlineSmall,
color = MaterialTheme.colorScheme.onPrimaryContainer
)},
navigationIcon = {
IconButton(onClick = { activity.finish() }) {
Icon(
imageVector = Icons.Filled.ArrowBack,
contentDescription = null,
modifier = Modifier.size(28.dp)
modifier = Modifier.size(28.dp),
tint = MaterialTheme.colorScheme.onPrimaryContainer
)
}
},

View File

@@ -47,14 +47,16 @@ fun DSBContent(activity: ComponentActivity){
colors = TopAppBarDefaults.centerAlignedTopAppBarColors(MaterialTheme.colorScheme.primaryContainer),
title = {
Text(text = "DSBmobile",
style = MaterialTheme.typography.headlineSmall
style = MaterialTheme.typography.headlineSmall,
color = MaterialTheme.colorScheme.onPrimaryContainer
)},
navigationIcon = {
IconButton(onClick = { activity.finish() }) {
Icon(
imageVector = Icons.Filled.ArrowBack,
contentDescription = null,
modifier = Modifier.size(28.dp)
modifier = Modifier.size(28.dp),
tint = MaterialTheme.colorScheme.onPrimaryContainer
)
}
},

View File

@@ -1,5 +1,7 @@
package com.schoolapp.cleverclass
import android.content.Context
import android.content.SharedPreferences.Editor
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
@@ -25,6 +27,7 @@ import androidx.compose.material.icons.filled.KeyboardArrowDown
import androidx.compose.material.icons.filled.KeyboardArrowUp
import androidx.compose.material.icons.outlined.Delete
import androidx.compose.material.icons.outlined.Edit
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.BottomAppBar
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
@@ -102,17 +105,14 @@ class FachActivity : ComponentActivity() {
}
}
}
/* TODO: save data when activity is destroyed
override fun onDestroy() {
super.onDestroy()
} */
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun GradeContent(activity: ComponentActivity, loadedGrades: List<GradeData>){
val sharedPreferences = activity.getSharedPreferences("gradeAverages", Context.MODE_PRIVATE)
val editor = sharedPreferences.edit()
var grades by remember {
mutableStateOf(loadedGrades)
}
@@ -120,6 +120,10 @@ fun GradeContent(activity: ComponentActivity, loadedGrades: List<GradeData>){
mutableStateOf(0.00f)
}
var showDeleteConfirmation by remember {
mutableStateOf(false)
}
val colors = listOf(
Color(0xFF536DFE),
Color(0xFF448AFF),
@@ -130,7 +134,7 @@ fun GradeContent(activity: ComponentActivity, loadedGrades: List<GradeData>){
)
LaunchedEffect(grades) {
average = calculateAverage(grades)
average = calculateAverage(grades, editor)
}
DisposableEffect(activity) {
@@ -147,7 +151,8 @@ fun GradeContent(activity: ComponentActivity, loadedGrades: List<GradeData>){
colors = TopAppBarDefaults.centerAlignedTopAppBarColors(MaterialTheme.colorScheme.primaryContainer),
title = {
Text(text = name,
style = MaterialTheme.typography.headlineSmall
style = MaterialTheme.typography.headlineSmall,
color = MaterialTheme.colorScheme.onPrimaryContainer
)},
navigationIcon = {
IconButton(onClick = {
@@ -159,17 +164,18 @@ fun GradeContent(activity: ComponentActivity, loadedGrades: List<GradeData>){
Icon(
imageVector = Icons.Filled.ArrowBack,
contentDescription = null,
modifier = Modifier.size(28.dp)
modifier = Modifier.size(28.dp),
tint = MaterialTheme.colorScheme.onPrimaryContainer
)
}
},
// TODO: add confirmation to delete all
actions = {
IconButton(onClick = { grades = emptyList() }) {
IconButton(onClick = { showDeleteConfirmation = true }) {
Icon(
imageVector = Icons.Outlined.Delete,
contentDescription = null,
modifier = Modifier.size(28.dp)
modifier = Modifier.size(28.dp),
tint = MaterialTheme.colorScheme.onPrimaryContainer
)
}
},
@@ -219,6 +225,7 @@ fun GradeContent(activity: ComponentActivity, loadedGrades: List<GradeData>){
{
grades.forEach{ gradeData ->
GradePrefab(
id = gradeData.id,
onClose = { grades = grades.filter { it.id != gradeData.id } },
type = gradeData.type,
grade = gradeData.grade,
@@ -226,21 +233,54 @@ fun GradeContent(activity: ComponentActivity, loadedGrades: List<GradeData>){
color = gradeData.color,
onGradeChange = { grade ->
grades.find { it.id == gradeData.id }?.grade = grade
average = calculateAverage(grades) },
average = calculateAverage(grades, editor) },
onWeightChange = { weight ->
grades.find { it.id == gradeData.id }?.weight = weight
average = calculateAverage(grades) },
average = calculateAverage(grades, editor) },
onTypeChange = { type ->
grades.find { it.id == gradeData.id }?.type = type
average = calculateAverage(grades) })
average = calculateAverage(grades, editor) }
)
}
Spacer(modifier = Modifier.height(216.dp))
}
}
if (showDeleteConfirmation){
AlertDialog(
onDismissRequest = { showDeleteConfirmation = false },
text = { Text(text = "Möchten Sie wirklich alle Noten löschen?", color = MaterialTheme.colorScheme.onPrimaryContainer, style = MaterialTheme.typography.labelMedium) },
confirmButton = {
Row(modifier = Modifier.fillMaxWidth()){
Text(
text = "Bestätigen",
color = MaterialTheme.colorScheme.secondary,
style = MaterialTheme.typography.labelMedium,
modifier = Modifier.clickable {
grades = emptyList()
editor.putFloat(name, 0.0f).apply()
showDeleteConfirmation = false
}
)
Spacer(modifier = Modifier.weight(1f))
Text(
text = "Abbrechen",
color = MaterialTheme.colorScheme.secondary,
style = MaterialTheme.typography.labelMedium,
modifier = Modifier.clickable { showDeleteConfirmation = false }
)
}
},
containerColor = MaterialTheme.colorScheme.primaryContainer
)
}
}
@Composable
fun GradePrefab(
id: Int,
onClose: () -> Unit,
type: String,
grade: Int,
@@ -248,30 +288,30 @@ fun GradePrefab(
color: Color,
onGradeChange: (grade: Int) -> Unit,
onWeightChange: (weight: Float) -> Unit,
onTypeChange: (type: String) -> Unit
onTypeChange: (type: String) -> Unit,
){
var editing by remember {
var editing by remember(id) {
mutableStateOf(false)
}
var typeExpanded by remember {
var typeExpanded by remember(id) {
mutableStateOf(false)
}
var gradeExpanded by remember {
var gradeExpanded by remember(id) {
mutableStateOf(false)
}
var weightExpanded by remember {
var weightExpanded by remember(id) {
mutableStateOf(false)
}
var selectedType by remember {
var selectedType by remember(id) {
mutableStateOf(type)
}
var selectedGrade by remember {
var selectedGrade by remember(id) {
mutableStateOf(grade)
}
var selectedWeight by remember {
var selectedWeight by remember(id) {
mutableStateOf(weight)
}
@@ -483,7 +523,7 @@ data class GradeData(
var type: String
)
fun calculateAverage(grades: List<GradeData>): Float {
fun calculateAverage(grades: List<GradeData>, editor: Editor): Float {
if (grades.isEmpty()) return 0.0f
var totalGrade = 0.0f
@@ -507,15 +547,11 @@ fun calculateAverage(grades: List<GradeData>): Float {
val saAverage = saTotalGrade / saTotalWeights
return if (smallAverage.isNaN()) saAverage
val finalGrade = if (smallAverage.isNaN()) saAverage
else if (saAverage.isNaN()) smallAverage
else (smallAverage + saAverage * SAWeight) / (1 + SAWeight)
}
fun formatFloat(number: Float): String {
var formattedString = number.toString()
formattedString = formattedString.substring(0, if(formattedString.length == 3) 3 else 4)
return formattedString
editor.putFloat(name, finalGrade).apply()
return finalGrade
}

View File

@@ -67,7 +67,7 @@ fun MainContent(activity: ComponentActivity){
title = {
Text(text = "CleverClass",
style = MaterialTheme.typography.headlineMedium,
color = MaterialTheme.colorScheme.onPrimary)
color = MaterialTheme.colorScheme.onPrimaryContainer)
},
actions = {
IconButton(
@@ -75,7 +75,8 @@ fun MainContent(activity: ComponentActivity){
Icon(
imageVector = Icons.Filled.Settings,
contentDescription = null,
modifier = Modifier.size(28.dp))
modifier = Modifier.size(28.dp),
tint = MaterialTheme.colorScheme.onPrimaryContainer)
}
},
modifier = Modifier.fillMaxWidth()

View File

@@ -47,14 +47,16 @@ fun MebisContent(activity: ComponentActivity){
colors = TopAppBarDefaults.centerAlignedTopAppBarColors(MaterialTheme.colorScheme.primaryContainer),
title = {
Text(text = "Mebis",
style = MaterialTheme.typography.headlineSmall
style = MaterialTheme.typography.headlineSmall,
color = MaterialTheme.colorScheme.onPrimaryContainer
)},
navigationIcon = {
IconButton(onClick = { activity.finish() }) {
Icon(
imageVector = Icons.Filled.ArrowBack,
contentDescription = null,
modifier = Modifier.size(28.dp)
modifier = Modifier.size(28.dp),
tint = MaterialTheme.colorScheme.onPrimaryContainer
)
}
},

View File

@@ -1,6 +1,8 @@
package com.schoolapp.cleverclass
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
@@ -12,28 +14,48 @@ 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.ArrowBack
import androidx.compose.material3.BottomAppBar
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
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.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import com.schoolapp.cleverclass.ui.theme.CleverClassTheme
import com.schoolapp.cleverclass.ui.theme.TextOnColouredButton
val subjects = listOf("Biologie","Chemie","Deutsch","Englisch","Ethik","Evangelisch","Französisch",
"Geographie","Geschichte","Informatik","Katolisch","Kunst","Latein","Mathe","Musik","Physik",
"Pulitik und Gesellschaft","Sport","Wirtschaft")
val colors = listOf(
Color(0xFF69F0AE),
Color(0xFFEEFF41),
Color(0xFFFFAB40),
Color(0xFF18FFFF),
Color(0xFFB2FF59))
class NotenActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -54,41 +76,91 @@ class NotenActivity : ComponentActivity() {
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun NotenContent(activity: ComponentActivity){
Column() {
TopAppBar(
colors = TopAppBarDefaults.centerAlignedTopAppBarColors(MaterialTheme.colorScheme.primaryContainer),
title = {
Text(text = "Noten",
style = MaterialTheme.typography.headlineSmall
)},
navigationIcon = {
IconButton(onClick = { activity.finish() }) {
Icon(
imageVector = Icons.Filled.ArrowBack,
contentDescription = null,
modifier = Modifier.size(28.dp)
)
}
},
modifier = Modifier.fillMaxWidth()
)
val sharedPreferences = activity.getSharedPreferences("gradeAverages", Context.MODE_PRIVATE)
Column(modifier = Modifier.verticalScroll(rememberScrollState())) {
FachButton(color = Color(0xFF69F0AE), text = "Deutsch", 0, 3.66f, activity)
FachButton(color = Color(0xFFEEFF41), text = "Mathe",2, 1.56f, activity)
FachButton(color = Color(0xFFFFAB40), text = "Englisch",2, 2.27f, activity)
FachButton(color = Color(0xFF18FFFF), text = "Latein",2, 4.75f, activity)
FachButton(color = Color(0xFFB2FF59), text = "Französisch",2, 2.33f, activity)
var allAverage by remember {
mutableStateOf(calculateAllAverage(loadAllAverages(sharedPreferences)))
}
Scaffold(
topBar = {
TopAppBar(
colors = TopAppBarDefaults.centerAlignedTopAppBarColors(MaterialTheme.colorScheme.primaryContainer),
title = {
Text(text = "Noten",
style = MaterialTheme.typography.headlineSmall,
color = MaterialTheme.colorScheme.onPrimaryContainer
)},
navigationIcon = {
IconButton(onClick = { activity.finish() }) {
Icon(
imageVector = Icons.Filled.ArrowBack,
contentDescription = null,
modifier = Modifier.size(28.dp),
tint = MaterialTheme.colorScheme.onPrimaryContainer
)
}
},
modifier = Modifier.fillMaxWidth()
)
},
bottomBar = {
BottomAppBar(
containerColor = MaterialTheme.colorScheme.primaryContainer,
modifier = Modifier
.fillMaxWidth()
.height(64.dp)
) {
Row (modifier = Modifier
.fillMaxWidth()
.align(Alignment.CenterVertically)){
Spacer(modifier = Modifier.width(16.dp))
Text(text = "Gesamtschnitt:",
style = MaterialTheme.typography.headlineSmall)
Spacer(modifier = Modifier.weight(1f))
Text(
text = "Ø" + formatFloat(allAverage),
style = MaterialTheme.typography.headlineSmall)
Spacer(modifier = Modifier.width(16.dp))
}
}
}
) {innerPadding ->
Column(modifier = Modifier
.verticalScroll(rememberScrollState())
.padding(innerPadding))
{
subjects.forEach { name ->
FachButton(
color = colors.random(),
subject = name,
saWeight = 2,
activity = activity,
sharedPreferences = sharedPreferences,
onAvgChange = { allAverage = calculateAllAverage(loadAllAverages(sharedPreferences)) }
)
}
Spacer(modifier = Modifier.height(16.dp))
}
}
}
@Composable
fun FachButton(color : Color, text : String, saWeight: Int, average : Float, activity : ComponentActivity){
fun FachButton(
color : Color,
subject : String,
saWeight: Int, activity :
ComponentActivity,
sharedPreferences: SharedPreferences,
onAvgChange: () -> Unit){
var avg by remember {
mutableStateOf(sharedPreferences.getFloat(subject, 0.0f))
}
Button(
onClick = {
val intent = Intent(activity, FachActivity::class.java).apply {
putExtra(FachActivity.NAME_KEY, text)
putExtra(FachActivity.NAME_KEY, subject)
putExtra(FachActivity.WEIGHT_KEY, saWeight)
}
activity.startActivity(intent) },
@@ -100,13 +172,54 @@ fun FachButton(color : Color, text : String, saWeight: Int, average : Float, act
.padding(start = 16.dp, end = 16.dp, top = 16.dp)
) {
Row(modifier = Modifier.fillMaxWidth()) {
Text(text = text,
Text(text = subject,
color = TextOnColouredButton,
style = MaterialTheme.typography.labelMedium)
Spacer(modifier = Modifier.weight(1f))
Text(text = "Ø$average",
Text(text = "Ø${formatFloat(avg)}",
color = TextOnColouredButton,
style = MaterialTheme.typography.labelMedium)
}
}
// changes state when Shared Preference is updated
val observer = remember {
SharedPreferences.OnSharedPreferenceChangeListener { _, key ->
if (key == subject) {
avg = sharedPreferences.getFloat(subject, 0.0f)
onAvgChange()
}
}
}
// handles observer creation and disposal
DisposableEffect(Unit) {
sharedPreferences.registerOnSharedPreferenceChangeListener(observer)
onDispose {
sharedPreferences.unregisterOnSharedPreferenceChangeListener(observer)
}
}
}
fun calculateAllAverage(avgs: List<Float>): Float{
var total = 0.0f
var number = 0
avgs.forEach{ avg ->
if (avg != 0.0f && !avg.isNaN()){
total += avg
number += 1
}
}
return (total / number)
}
fun loadAllAverages(sharedPreferences: SharedPreferences): List<Float>{
val avgs = emptyList<Float>().toMutableList()
subjects.forEach { name ->
avgs += sharedPreferences.getFloat(name, 0.0f)
}
return avgs
}

View File

@@ -48,7 +48,8 @@ fun PSEContent(activity: ComponentActivity){
title = {
Text(
text = "Periodensystem",
style = MaterialTheme.typography.headlineSmall
style = MaterialTheme.typography.headlineSmall,
color = MaterialTheme.colorScheme.onPrimaryContainer
)
},
navigationIcon = {
@@ -56,7 +57,8 @@ fun PSEContent(activity: ComponentActivity){
Icon(
imageVector = Icons.Filled.ArrowBack,
contentDescription = null,
modifier = Modifier.size(28.dp)
modifier = Modifier.size(28.dp),
tint = MaterialTheme.colorScheme.onPrimaryContainer
)
}
},

View File

@@ -68,7 +68,8 @@ fun SettingsContent(activity: ComponentActivity) {
title = {
Text(
text = "Einstellungen",
style = MaterialTheme.typography.headlineSmall
style = MaterialTheme.typography.headlineSmall,
color = MaterialTheme.colorScheme.onPrimaryContainer
)
},
navigationIcon = {
@@ -76,7 +77,8 @@ fun SettingsContent(activity: ComponentActivity) {
Icon(
imageVector = Icons.Filled.ArrowBack,
contentDescription = null,
modifier = Modifier.size(28.dp)
modifier = Modifier.size(28.dp),
tint = MaterialTheme.colorScheme.onPrimaryContainer
)
}
},
@@ -110,6 +112,7 @@ fun SettingsContent(activity: ComponentActivity) {
Text(
text = "About",
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onBackground,
modifier = Modifier.clickable {
val intent = Intent(activity, AboutActivity::class.java)
activity.startActivity(intent)
@@ -137,7 +140,7 @@ fun Setting(text : String, sharedPreferences: SharedPreferences, editor: Editor)
)
Spacer(modifier = Modifier.width(16.dp))
Text(text = text,
color = MaterialTheme.colorScheme.onPrimaryContainer,
color = MaterialTheme.colorScheme.onBackground,
style = MaterialTheme.typography.labelMedium)
}
}

View File

@@ -47,14 +47,16 @@ fun StundenplanContent(activity: ComponentActivity){
colors = TopAppBarDefaults.centerAlignedTopAppBarColors(MaterialTheme.colorScheme.primaryContainer),
title = {
Text(text = "Stundenplan",
style = MaterialTheme.typography.headlineSmall
style = MaterialTheme.typography.headlineSmall,
color = MaterialTheme.colorScheme.onPrimaryContainer
)},
navigationIcon = {
IconButton(onClick = { activity.finish() }) {
Icon(
imageVector = Icons.Filled.ArrowBack,
contentDescription = null,
modifier = Modifier.size(28.dp)
modifier = Modifier.size(28.dp),
tint = MaterialTheme.colorScheme.onPrimaryContainer
)
}
},

View File

@@ -0,0 +1,9 @@
package com.schoolapp.cleverclass
fun formatFloat(number: Float): String {
var formattedString = number.toString()
formattedString = formattedString.substring(0, if(formattedString.length == 3) 3 else 4)
return formattedString
}

View File

@@ -11,3 +11,8 @@ val White90 = Color(0xFFEBEBEB)
val White70 = Color(0xFFD3D3D3)
val TextOnColouredButton = Color(0xFF121212)
val dismissLight = Color(0xFF536DFE)
val dismissDark = Color(0xFF448AFF)
val testColor = Color(0xFF00FF00)

View File

@@ -19,14 +19,18 @@ import androidx.core.view.WindowCompat
private val DarkColorScheme = darkColorScheme(
background = Black90,
primaryContainer = Black70,
onPrimary = White100,
onPrimaryContainer = White100,
secondary = dismissDark,
onBackground = White100,
primary = Color(0xFF536DFE)
)
private val LightColorScheme = lightColorScheme(
background = White90,
primaryContainer = White70,
onPrimary = Black100,
onPrimaryContainer = Black100,
secondary = dismissLight,
onBackground = Black100,
primary = Color(0xFF8396FF)
)