Compare commits

..

17 Commits

Author SHA1 Message Date
Paul
442ef70b8d update AboutActivity 2024-10-24 13:59:01 +02:00
BuildTools
ec3a95fc2d Merge remote-tracking branch 'origin/master' 2024-10-14 15:26:13 +02:00
BuildTools
b07cd27fce Why tf is "Index": 0 @ index = 1 and "Index": 2 @ index = 0 2024-10-14 15:25:58 +02:00
matthias
39c037a9ab delete empty line 2024-07-05 17:44:51 +02:00
matthias
f6956349e0 Small adjustment
3 month --> 3 months
2024-06-26 06:59:01 +02:00
BuildTools
a41bd9cbb3 Small adjustment 2024-06-21 16:52:28 +02:00
BuildTools
0db1e78cd4 Small adjustments 2024-06-16 13:16:56 +02:00
matthias
7bdcb7e3fb Added restart of app when first setup isn't done
when going back via phone feature, user sees the empty timetable
2024-06-09 23:46:58 +02:00
matthias
d36cadeb18 Fixed typo 2024-06-09 23:45:32 +02:00
BuildTools
1056dc39bf Add deleteAllData 2024-06-09 21:58:28 +02:00
matthias
15cadb76c6 Minor appearance adjustments
added scaling with 1.1f(lesson indexes & "Pause") / 0.8f(times)
2024-06-09 13:22:00 +02:00
matthias
41b54f15ea Major Bugfix
fixed removal of lessons
2024-06-09 13:20:31 +02:00
matthias
50eb19a464 minor code cleanup 2024-06-08 14:16:01 +02:00
matthias
4c3de94dd3 Stundenplan bugfixes
fixed indexing with wrong variable for breaks in core
added compatibility for lessons without subject, room or teacher
added horizontal scroll for too long user input
added info icon with alert dialog for scroll explanation
2024-06-08 14:15:43 +02:00
matthias
30ad4bed64 Stundenplan most definitely finished
Added Commenting to StundenplanActivity and TimeTableSetupActivity
2024-06-07 02:13:02 +02:00
BuildTools
f091451fe8 Add Ko-fi
Remove Langlebigstesisotop
Update stuff
2024-06-06 19:21:33 +02:00
1c665fea26 README.md updated
added android version minimum 8.0 as minimum api level defined in CleverClass/app/build.gradle.kts is 26
enlarged link to the license as version and release date belong to its name
2024-06-05 08:07:46 +00:00
13 changed files with 813 additions and 443 deletions

View File

@@ -19,14 +19,14 @@ APK-Datei:
- Öffne die heruntergeladene APK-Datei auf deinem Android-Gerät
- Folge den Anweisungen auf dem Bildschirm, um die Installation abzuschließen
## Anforderungen
Betriebssystem: Android
Betriebssystem: Android 8.0 oder neuer
## Autoren
- Paul Posch
- Matthias Meyer
- Jakub Szarko
- Emilian Bührer
## Lizenz
Dieses Projekt steht unter der [GNU General Public License](LICENSE) Version 3, 29 June 2007.
Dieses Projekt steht unter der [GNU General Public License Version 3, 29 June 2007](LICENSE).
## Sonstiges
Dieses Projekt ist als Schulprojekt inerhalb von 3 Monaten entstanden.

View File

@@ -23,6 +23,7 @@ android {
buildTypes {
release {
isMinifyEnabled = false
isDebuggable = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"

File diff suppressed because it is too large Load Diff

View File

@@ -1,9 +1,15 @@
package com.schoolapp.cleverclass
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.Image
import androidx.compose.foundation.clickable
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
@@ -14,6 +20,7 @@ import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material3.Divider
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
@@ -23,7 +30,10 @@ import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import com.schoolapp.cleverclass.ui.theme.CleverClassTheme
@@ -73,7 +83,35 @@ fun AboutContent(activity: ComponentActivity){
{
AboutTextElement("This Product is published under the\nGNU General Public License\nVersion 3, 29 June 2007", 16.dp)
AboutTextElement("Developed by:\n- Paul Posch\n- Matthias Meyer\n- Jakub Szarko\n- Emilian Bührer", 32.dp)
AboutTextElement("Fun Facts:\nThis app consists of 2.873 lines of code\nThe repository is 413KB big\nThe development took about 3 month", 64.dp) //TODO: Update before launch
AboutTextElement("Fun Facts:\nThis app consists of 4.189 lines of code\nThe repository is 768KB big\nThe development took about 3 months", 64.dp)
Spacer(modifier = Modifier.height(32.dp))
Divider()
Box(contentAlignment = Alignment.CenterStart,
modifier = Modifier
.fillMaxWidth()
.clickable {
val intent =
Intent(Intent.ACTION_VIEW, Uri.parse("https://ko-fi.com/cleverclass"))
activity.startActivity(intent)
}
) {
Row {
Text(
text = "Support the Devs",
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onBackground,
modifier = Modifier.padding(16.dp)
)
Spacer(modifier = Modifier.weight(1f))
Image(
painter = painterResource(R.drawable.baseline_open_in_browser_24),
contentDescription = null,
colorFilter = ColorFilter.tint(MaterialTheme.colorScheme.onBackground),
modifier = Modifier.padding(16.dp)
)
}
}
}
}
}

View File

@@ -127,7 +127,19 @@ private fun decompressGZIPAndDecodeBase64(compressedData: String): String {
private fun downloadImagesTask(jsonResponse: JSONObject, mainDir : File) : Int {
clearFolder(mainDir)
val jsonDaysObject = jsonResponse.getJSONArray("ResultMenuItems").getJSONObject(0).getJSONArray("Childs").getJSONObject(0).getJSONObject("Root").getJSONArray("Childs")
var jsonDaysObject = jsonResponse.getJSONArray("ResultMenuItems")
for (i in 0 until jsonDaysObject.length()) {
if (jsonDaysObject.getJSONObject(i).get("Index") == 0) {
jsonDaysObject = jsonDaysObject.getJSONObject(i).getJSONArray("Childs")
break
}
}
for (i in 0 until jsonDaysObject.length()) {
if (jsonDaysObject.getJSONObject(i).get("Index") == 0) {
jsonDaysObject = jsonDaysObject.getJSONObject(i).getJSONObject("Root").getJSONArray("Childs")
break
}
}
for (d in 0 until jsonDaysObject.length()) {
val jsonDayObject = jsonDaysObject.getJSONObject(d)
@@ -201,20 +213,6 @@ private fun createDataFolder(context: Context) : File {
return folder
}
private fun clearFolder(directory: File) {
if (directory.exists()) {
val files = directory.listFiles()
if (files != null) {
for (file in files) {
if (file.isDirectory) {
clearFolder(file)
}
file.delete()
}
}
}
}
private fun isInternetAvailable(context: Context): Boolean {
val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val network = connectivityManager.activeNetwork

View File

@@ -86,11 +86,15 @@ fun MainContent(activity: ComponentActivity){
MainButton(onClick = { switchToActivity(activity, StundenplanActivity::class.java) }, color = Color(0xFFFF4081), text = "Stundenplan", sharedPreferences)
MainButton(onClick = { switchToActivity(activity, NotenActivity::class.java) }, color = Color(0xFFE040FB), text = "Noten", sharedPreferences)
MainButton(onClick = { switchToActivity(activity, PSEActivity::class.java) }, color = Color(0xFF536DFE), text = "Periodensystem", sharedPreferences)
MainButton(onClick = {
MainButton(onClick = { switchToActivity(activity, DSBActivity::class.java) }, color = Color(0xFFFF6E40), text = "DSBmobile", sharedPreferences)
MainButton(
onClick = {
val intent = Intent(Intent.ACTION_VIEW, Uri.parse("https://mebis.bycs.de/"))
activity.startActivity(intent)
}, color = Color(0xFF7C4DFF), text = "Mebis", sharedPreferences)
MainButton(onClick = { switchToActivity(activity, DSBActivity::class.java) }, color = Color(0xFFFF6E40), text = "DSBmobile", sharedPreferences)
},
color = Color(0xFF7C4DFF),
text = "Mebis", sharedPreferences
)
}
}
}

View File

@@ -309,6 +309,5 @@ private fun readElementData(int: Int): String {
"künstlich:\n${elementData.get("künstlich")}\n\n" +
"radioaktiv:\n${elementData.get("radioaktiv")}\n\n" +
"Halbwertszeit:\n${elementData.get("Halbwertszeit")}\n\n" +
"Strahlungsart:\n${elementData.get("Strahlungsart")}\n\n" +
"langlebigstes Isotop:\n${elementData.get("langlebigstes Isotop")}"
"Strahlungsart:\n${elementData.get("Strahlungsart")}"
}

View File

@@ -24,6 +24,7 @@ import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Divider
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
@@ -35,8 +36,10 @@ import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
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.Modifier
import androidx.compose.ui.unit.dp
@@ -64,6 +67,10 @@ fun SettingsContent(activity: ComponentActivity) {
val sharedPreferences = activity.getSharedPreferences("Settings", Context.MODE_PRIVATE)
val editor = sharedPreferences.edit()
var showDeleteConfirmation by remember {
mutableStateOf(false)
}
Column(modifier = Modifier.fillMaxSize()) {
// Top AppBar
TopAppBar(
@@ -94,14 +101,14 @@ fun SettingsContent(activity: ComponentActivity) {
.weight(1f)
.verticalScroll(rememberScrollState())
.fillMaxWidth()
) {
Setting(text = "Stundenplan", sharedPreferences, editor)
Setting(text = "Noten", sharedPreferences, editor)
Setting(text = "Periodensystem", sharedPreferences, editor)
Setting(text = "Mebis", sharedPreferences, editor)
Setting(text = "DSBmobile", sharedPreferences, editor)
Setting(text = "Mebis", sharedPreferences, editor)
Spacer(modifier = Modifier.height(16.dp))
Divider()
Box(
modifier = Modifier
@@ -120,6 +127,19 @@ fun SettingsContent(activity: ComponentActivity) {
modifier = Modifier.padding(16.dp)
)
}
Divider()
Box(
modifier = Modifier
.fillMaxWidth()
.clickable { showDeleteConfirmation = true }
) {
Text(
text = "Alle Daten löschen",
color = MaterialTheme.colorScheme.onBackground,
style = MaterialTheme.typography.labelMedium,
modifier = Modifier.padding(16.dp)
)
}
}
// About Button
@@ -150,6 +170,43 @@ fun SettingsContent(activity: ComponentActivity) {
Spacer(modifier = Modifier.height(8.dp))
}
}
if(showDeleteConfirmation){
AlertDialog(
onDismissRequest = { showDeleteConfirmation = false },
text = {
Text(
text = "Möchten Sie wirklich alle Daten aus dieser App löschen?\n" +
"Dieser Vorgang kann nicht rückgängig gemacht werden.",
color = MaterialTheme.colorScheme.onPrimaryContainer,
style = MaterialTheme.typography.labelMedium
)
},
confirmButton = {
Row(modifier = Modifier.fillMaxWidth()){
Text(
text = "Löschen",
color = MaterialTheme.colorScheme.secondary,
style = MaterialTheme.typography.labelMedium,
modifier = Modifier.clickable {
deleteAllData(activity)
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

View File

@@ -2,20 +2,28 @@ package com.schoolapp.cleverclass
import android.content.Context
import android.content.Intent
import android.graphics.drawable.Icon
import android.icu.text.DecimalFormat
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.horizontalScroll
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
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.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material.icons.outlined.Edit
import androidx.compose.material.icons.outlined.Info
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
@@ -25,15 +33,14 @@ import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
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.platform.LocalContext
import androidx.compose.ui.draw.scale
import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.unit.dp
import androidx.core.content.ContextCompat.startActivity
import com.schoolapp.cleverclass.LessonStoreManager.getLessons
@@ -43,7 +50,7 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
private val listOfDays = listOf("Mo", "Di", "Mi", "Do", "Fr")
private val lessonGrabberIndex = 0
private val listOfBreakIndexes = mutableListOf<Int>()
class StundenplanActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
@@ -52,12 +59,26 @@ class StundenplanActivity : ComponentActivity() {
val sharedPreferences = this.getSharedPreferences("TimeTable", Context.MODE_PRIVATE)
val setupDone = sharedPreferences.getBoolean("setupDone", false)
val lessons = MutableList(5) { listOf<LessonData>() }
//Loading saved lessons when NOT auto-loading the setup
if (setupDone) {
listOfDays.forEachIndexed { index, dayLessons ->
CoroutineScope(Dispatchers.IO).launch {
getLessons(this@StundenplanActivity, dayLessons).collect { savedLessons ->
lessons[index] = savedLessons.toMutableList()
}
}
}
}
setContent {
CleverClassTheme {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
//Auto-load setup, if incomplete
if (!setupDone) {
val intent = Intent(this@StundenplanActivity, TimeTableSetupActivity::class.java).apply {
putExtra(TimeTableSetupActivity.TYPE_KEY, "TimeSetup")
@@ -65,7 +86,7 @@ class StundenplanActivity : ComponentActivity() {
startActivity(intent)
}
StundenplanContent(activity = this)
StundenplanContent(activity = this, lessons)
}
}
}
@@ -75,8 +96,24 @@ class StundenplanActivity : ComponentActivity() {
// Content of Stundenplan
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun StundenplanContent(activity: ComponentActivity){
Column() {
fun StundenplanContent(activity: ComponentActivity, loadedLessons: List<List<LessonData>>){
//Declaration of most sharedPreferences-stored data (same SharedPreferences as in TimeTableSetupActivity.kt)
val sharedPreferences = activity.getSharedPreferences("TimeTable", Context.MODE_PRIVATE)
val lessonLength = sharedPreferences.getInt("lessonLength", 0)
val firstLesson = sharedPreferences.getFloat("firstLesson", 0.0f).toString()
val breakAmnt = sharedPreferences.getInt("breakAmnt", 0)
val listOfBreakStartTimes = mutableListOf<String>()
val listOfBreakLengths = mutableListOf<Int>()
for (i in 0 until breakAmnt) {
listOfBreakStartTimes.add(sharedPreferences.getFloat("break${i}StartTime", 0.0f).toString())
listOfBreakLengths.add(sharedPreferences.getInt("break${i}Length", 0))
}
var showInfo by remember {
mutableStateOf(false)
}
Column {
TopAppBar(
colors = TopAppBarDefaults.centerAlignedTopAppBarColors(MaterialTheme.colorScheme.primaryContainer),
title = {
@@ -95,8 +132,20 @@ fun StundenplanContent(activity: ComponentActivity){
}
},
actions ={
IconButton(onClick = {
val intent = Intent(activity, TimeTableSetupActivity::class.java).apply {
//Info button
IconButton(
onClick = { showInfo = !showInfo }) {
Icon(
imageVector = Icons.Outlined.Info,
contentDescription = null,
modifier = Modifier.size(28.dp),
tint = MaterialTheme.colorScheme.onPrimaryContainer
)
}
//Edit button
IconButton(
onClick = {
val intent = Intent(activity, TimeTableSetupActivity::class.java).apply {
putExtra(TimeTableSetupActivity.TYPE_KEY, "TimeSetup")
}
startActivity(activity, intent, null)
@@ -112,48 +161,295 @@ fun StundenplanContent(activity: ComponentActivity){
modifier = Modifier.fillMaxWidth()
)
Column() {
listOfDays.forEach() {currentDay ->
Day(currentDay)
//Start of the timetable --> One Row() with multiple Column() to create the table
Row(
modifier = Modifier
.verticalScroll(rememberScrollState())
.horizontalScroll(rememberScrollState())
) {
//Left-handed lesson indexing with beginning time of each lesson or break
InfoColumn(
loadedLessons = loadedLessons,
breakAmnt = breakAmnt,
breaksStartTime = listOfBreakStartTimes,
firstLesson = firstLesson,
lessonLength = lessonLength,
breaksLength = listOfBreakLengths
)
//Creation of 5 Columns
loadedLessons.forEachIndexed { index, dailyLessons ->
//Width variable for variable Box sizes
Column(modifier = Modifier.width(250.dp)) {
//Additional extraIndex to count lessons without breaks getting into the way
var extraIndex = 0
//Box with the day on top of each Column()
Box(
modifier = Modifier
.size(250.dp, 50.dp)
.padding(3.dp)
.align(Alignment.CenterHorizontally)
.border(
width = 1.dp,
color = MaterialTheme.colorScheme.primaryContainer
)
) {
Text(
text = listOfDays[index],
modifier = Modifier.align(Alignment.Center),
style = MaterialTheme.typography.labelMedium
)
}
//Core timetable
//One Box for each lesson or break
for (i in 0 until (dailyLessons.size + breakAmnt)) {
//If the current index is saved as a break in listOfBreakIndexes --> Spacer Box
if (listOfBreakIndexes.indexOf(i) != -1) {
Box(
modifier = Modifier
.size(250.dp, 100.dp)
)
}
//Else creation of a Box containing all the information from the LessonData object
else if (dailyLessons != emptyList<LessonData>() && dailyLessons.size != extraIndex) {
LessonBox(subject = dailyLessons[extraIndex].subject, teacher = dailyLessons[extraIndex].teacher, room = dailyLessons[extraIndex].room)
//ExtraIndex counted up only here as it does only index the lessons and NOT the breaks
extraIndex++
}
}
}
}
//Right-handed lesson indexing with beginning time of each lesson or break
InfoColumn(
loadedLessons = loadedLessons,
breakAmnt = breakAmnt,
breaksStartTime = listOfBreakStartTimes,
firstLesson = firstLesson,
lessonLength = lessonLength,
breaksLength = listOfBreakLengths
)
}
}
if (showInfo) {
AlertDialog(
onDismissRequest = { showInfo = false },
text = {
Text(
text = "Die Breite der Spalten ist auf eine bestimmte Größe festgelegt.\n\n" +
"Zu lange Eingaben können horizontal gescrollt werden.",
color = MaterialTheme.colorScheme.onPrimaryContainer,
style = MaterialTheme.typography.labelMedium)
},
confirmButton = {
Text(
text = "Schließen",
color = MaterialTheme.colorScheme.secondary,
style = MaterialTheme.typography.labelMedium,
modifier = Modifier.clickable { showInfo = false }
)
},
containerColor = MaterialTheme.colorScheme.primaryContainer,
modifier = Modifier
.padding(5.dp)
)
}
}
//Data class to save objects via DataShare containing information about lessons
data class LessonData(
var subject: String,
var teacher: String,
var room: String
)
//Implementation of Box with a darker border than the other Boxes
// contains the information from the corresponding LessonData object
@Composable
fun Day(day: String) {
var lessons = emptyList<LessonData>()
val context = LocalContext.current
Column {
LaunchedEffect(lessons, context) {
getLessons(context, day).collect { savedLessons ->
lessons = savedLessons.toMutableList()
fun LessonBox(subject: String, teacher: String, room: String) {
Box(
modifier = Modifier
.size(250.dp, 100.dp)
.padding(3.dp)
.border(
width = 1.dp,
color = MaterialTheme.colorScheme.onPrimaryContainer
),
contentAlignment = Alignment.Center
) {
Column {
if (subject != "") {
Text(
modifier = Modifier
.horizontalScroll(rememberScrollState())
.align(Alignment.CenterHorizontally)
.padding(horizontal = 5.dp),
text = subject,
style = MaterialTheme.typography.labelMedium
)
}
if (room != "") {
Text(
modifier = Modifier
.horizontalScroll(rememberScrollState())
.align(Alignment.CenterHorizontally)
.padding(horizontal = 5.dp),
text = room,
style = MaterialTheme.typography.labelMedium
)
}
if (teacher != "") {
Text(
modifier = Modifier
.horizontalScroll(rememberScrollState())
.align(Alignment.CenterHorizontally)
.padding(horizontal = 5.dp),
text = teacher,
style = MaterialTheme.typography.labelMedium
)
}
}
lessons.forEach() {lessonData ->
Lesson(subject = lessonData.subject, teacher = lessonData.teacher, room = lessonData.room)
}
}
//Left-/Right-Handed info Column
@Composable
fun InfoColumn(loadedLessons: List<List<LessonData>>, breakAmnt: Int, breaksStartTime: List<String>, firstLesson: String, lessonLength: Int, breaksLength: List<Int>) {
Column {
//Determining how much lessons the longest day of the week has
var maxLessons = 0
for (dailyLessons in loadedLessons) {
if (dailyLessons.size > maxLessons) {
maxLessons = dailyLessons.size
}
}
//Variable for time management with custom break times
var lessonTimeIncrement = 0
//Variable for decreasing the number in the InfoColumn after a "Pause" String
var lessonNegIncrement = 0
//Additional extraIndex to count lessons without breaks getting into the way
var extraIndex = 0
//Clear the list of brake indexes needed earlier in the timetable core
listOfBreakIndexes.drop(listOfBreakIndexes.size)
//Spacer Box
Box(
modifier = Modifier
.size(100.dp, 50.dp)
.padding(3.dp)
)
//Loop for creating Boxes on the side
for (i in 0 until (maxLessons + breakAmnt)) {
//Boolean to avoid double creation of the same Box
var loopDone = false
//Loop through all saved break start time
for (breakTime in breaksStartTime) {
if (!loopDone) {
//Variable = minutes of the currently looked at break
var formattedBreakSubstring = breakTime.substringAfter('.')
//When the Float wos like XX.n, it the n-Part will be n0 (fix for values 10, 20, etc.)
if (formattedBreakSubstring == "1" || formattedBreakSubstring == "2" || formattedBreakSubstring == "3" || formattedBreakSubstring == "4" || formattedBreakSubstring == "5") {
formattedBreakSubstring += "0"
}
//Format start time of the break the same way as the lesson start time is formatted
val formattedBreakTime = "@" + DecimalFormat("00").format(breakTime.substringBefore('.').toInt()) + ":" + DecimalFormat("00").format(formattedBreakSubstring.toInt())
//Check whether the start time of the currently looked at brake and lesson are the sa,e
if (substringHelper(extraIndex, firstLesson, lessonLength, lessonTimeIncrement) == formattedBreakTime) {
Box(
modifier = Modifier
.size(100.dp)
.padding(3.dp)
.border(
width = 1.dp,
color = MaterialTheme.colorScheme.primaryContainer
)
) {
//"Pause" String instead of indexing
Text(
modifier = Modifier
.align(Alignment.Center)
.scale(1.1f),
text = "Pause",
textDecoration = TextDecoration.Underline,
style = MaterialTheme.typography.labelLarge
)
//String with the starting time of the current break
Text(
modifier = Modifier
.align(Alignment.BottomCenter)
.padding(3.dp)
.scale(0.8f),
text = formattedBreakTime,
style = MaterialTheme.typography.labelMedium
)
//Add length of current break to the increment
lessonTimeIncrement += breaksLength[breaksStartTime.indexOf(breakTime)]
//Add info that one moe brake exists to the indexing increment
lessonNegIncrement++
//Add the extraIndex (lessonIndex) into the listOfBreakIndexes list to include breaks in timetable core
listOfBreakIndexes.add(i)
//Prevent double creation of Boxes
loopDone = true
}
}
//When looped through all breaks, but none fitted
else if (breakTime == breaksStartTime.last()) {
Box(
modifier = Modifier
.size(100.dp)
.padding(3.dp)
.border(
width = 1.dp,
color = MaterialTheme.colorScheme.primaryContainer
)
) {
//String with the indexing of the lessons
Text(
modifier = Modifier
.align(Alignment.Center)
.scale(1.1f),
text = "${i + 1 - lessonNegIncrement}:",
textDecoration = TextDecoration.Underline,
style = MaterialTheme.typography.labelLarge
)
//String with the starting time of the lesson
Text(
modifier = Modifier
.align(Alignment.BottomCenter)
.padding(3.dp)
.scale(0.8f),
text = substringHelper(extraIndex, firstLesson, lessonLength, lessonTimeIncrement),
style = MaterialTheme.typography.labelMedium
)
//Prevent double creation of Boxes
loopDone = true
//Counting up the lesson only index
extraIndex++
}
}
}
}
}
}
}
@Composable
fun Lesson(subject: String, teacher: String, room: String) {
Box(modifier = Modifier
.size(200.dp, 100.dp)
.padding(3.dp)
) {
Text(
modifier = Modifier.align(Alignment.Center),
text = "$subject\n@$room\n/w$teacher")
//Function that moves the formatting and calculation of the lesson start times away from in-line
fun substringHelper (int: Int, eductString: String, lessonLength: Int, increment: Int): String {
//Variable = minutes of the entered Time
var subString = eductString.substringAfter('.')
//Fix of 10, 20, etc.
if (subString == "1" || subString == "2" || subString == "3" || subString == "4" || subString == "5") {
subString += "0"
}
}
fun currentDay(): String {
return "hi"
//Calculation based on start time of the first hour, lesson length, indexing of the current lesson (extraIndex!) and the increment calculated from the break times
//Formatting to "@hh:mm"
val productString = "@" + DecimalFormat("00").format((((subString.toInt() + int * lessonLength) + increment) / 60) + eductString.substringBefore('.').toInt()) + ":" + DecimalFormat("00").format((((subString.toInt()) + int * lessonLength) + increment) % 60)
//Return statement to use the formatted and calculated product in the timetable
return productString
}

View File

@@ -22,6 +22,7 @@ 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.text.KeyboardOptions
@@ -29,21 +30,30 @@ import androidx.compose.foundation.text.selection.TextSelectionColors
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material.icons.outlined.Delete
import androidx.compose.material.icons.outlined.Edit
import androidx.compose.material.icons.outlined.Info
import androidx.compose.material.ripple.LocalRippleTheme
import androidx.compose.material.ripple.RippleAlpha
import androidx.compose.material.ripple.RippleTheme
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.Checkbox
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.FilledTonalButton
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Surface
import androidx.compose.material3.Tab
import androidx.compose.material3.TabRow
import androidx.compose.material3.Text
import androidx.compose.material3.TextFieldDefaults
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
@@ -53,32 +63,22 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.unit.dp
import com.schoolapp.cleverclass.ui.theme.CleverClassTheme
import com.schoolapp.cleverclass.ui.theme.InputPrimaryColor
import com.schoolapp.cleverclass.ui.theme.InputSecondaryColor
import androidx.compose.foundation.layout.width
import androidx.compose.material.icons.outlined.Edit
import androidx.compose.material.ripple.LocalRippleTheme
import androidx.compose.material.ripple.RippleAlpha
import androidx.compose.material.ripple.RippleTheme
import androidx.compose.material3.FilledTonalButton
import androidx.compose.material3.OutlinedButton
import java.util.Locale
import androidx.compose.material3.Checkbox
import androidx.compose.material3.Tab
import androidx.compose.material3.TabRow
import androidx.compose.runtime.CompositionLocalProvider
import androidx.core.content.ContextCompat.startActivity
import com.schoolapp.cleverclass.LessonStoreManager.getLessons
import com.schoolapp.cleverclass.LessonStoreManager.saveLessons
import com.schoolapp.cleverclass.ui.theme.CleverClassTheme
import com.schoolapp.cleverclass.ui.theme.InputPrimaryColor
import com.schoolapp.cleverclass.ui.theme.InputSecondaryColor
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.util.Locale
private lateinit var activityType : String
private lateinit var activityState : String
private val listOfDays = listOf("Mo", "Di", "Mi", "Do", "Fr")
//Custom ripple to remove effect when touching tabs
private class CustomRippleTheme : RippleTheme {
@Composable
override fun defaultColor(): Color = Color.Unspecified
@@ -100,11 +100,13 @@ class TimeTableSetupActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//Defines setup type --> Time vs. Day
activityType = intent.getStringExtra(TYPE_KEY).toString()
//Defines curent day of week
activityState = intent.getStringExtra(STATE_KEY).toString()
//Load lessons of defined day from activityState
var lessons = listOf<LessonData>()
if (activityType == "DaySetup") {
CoroutineScope(Dispatchers.IO).launch {
getLessons(this@TimeTableSetupActivity, listOfDays[activityState.toInt()]).collect { savedLessons ->
@@ -131,6 +133,7 @@ class TimeTableSetupActivity : ComponentActivity() {
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun TimeTableSetupContent(activity: ComponentActivity, loadedLessons: List<LessonData>){
//One-time definition of the inputField colorscheme
val inputFieldColors = TextFieldDefaults.outlinedTextFieldColors(
textColor = MaterialTheme.colorScheme.onPrimaryContainer,
containerColor = MaterialTheme.colorScheme.secondaryContainer,
@@ -143,32 +146,36 @@ fun TimeTableSetupContent(activity: ComponentActivity, loadedLessons: List<Lesso
unfocusedBorderColor = Color.Transparent
)
//Declaration of most sharedPreferences-stored data
val sharedPreferences = activity.getSharedPreferences("TimeTable", Context.MODE_PRIVATE)
val editor = sharedPreferences.edit()
//Length of one lesson
var lessonLength by remember {
mutableStateOf(sharedPreferences.getInt("lessonLength", 0).toString())
}
//Number of breaks on one day
var breakAmnt by remember {
mutableStateOf(sharedPreferences.getInt("breakAmnt", 0).toString())
}
//Beginning time of the first lesson (Format: hh.mm)
var firstLesson by remember {
mutableStateOf(sharedPreferences.getFloat("firstLesson", 0.0f))
}
//Value to determine whether the first setup will be loaded again
var setupDone by remember {
mutableStateOf(sharedPreferences.getBoolean("setupDone", false))
}
//AlertDialog
var showInfo by remember {
mutableStateOf(false)
}
var showDeleteConfirmation by remember {
mutableStateOf(false)
}
//Variable for loaded lessons from onCreate()
var lessons by remember {
mutableStateOf(loadedLessons)
}
@@ -179,7 +186,23 @@ fun TimeTableSetupContent(activity: ComponentActivity, loadedLessons: List<Lesso
colors = TopAppBarDefaults.centerAlignedTopAppBarColors(MaterialTheme.colorScheme.primaryContainer),
title = { Text(text = "") },
navigationIcon = {
IconButton(onClick = { activity.finish() }) {
IconButton(
onClick = {
activity.finish()
if (setupDone) {
val intent = Intent(activity, StundenplanActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
startActivity(activity, intent, null)
}
else {
val intent = Intent(activity, MainActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
startActivity(activity, intent, null)
}
}
) {
Icon(
imageVector = Icons.Filled.ArrowBack,
contentDescription = null,
@@ -197,6 +220,7 @@ fun TimeTableSetupContent(activity: ComponentActivity, loadedLessons: List<Lesso
.fillMaxHeight()
.verticalScroll(rememberScrollState())
) {
//Background
Surface(
color = MaterialTheme.colorScheme.primaryContainer,
shape = RoundedCornerShape(20),
@@ -205,6 +229,7 @@ fun TimeTableSetupContent(activity: ComponentActivity, loadedLessons: List<Lesso
Column(horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.padding(16.dp)
) {
//Title
Row(verticalAlignment = Alignment.CenterVertically) {
Text(
text = "Stundenplan Setup",
@@ -215,6 +240,7 @@ fun TimeTableSetupContent(activity: ComponentActivity, loadedLessons: List<Lesso
Spacer(modifier = Modifier.weight(1f))
//Info Button --> AlertDialog
IconButton(onClick = { showInfo = !showInfo }) {
Icon(
imageVector = Icons.Outlined.Info,
@@ -222,20 +248,13 @@ fun TimeTableSetupContent(activity: ComponentActivity, loadedLessons: List<Lesso
tint = MaterialTheme.colorScheme.onPrimaryContainer
)
}
if (activityType == "Settings")
IconButton(onClick = { showDeleteConfirmation = !showDeleteConfirmation }) {
Icon(
imageVector = Icons.Outlined.Delete,
contentDescription = null,
modifier = Modifier.size(28.dp),
tint = MaterialTheme.colorScheme.onPrimaryContainer
)
}
}
Spacer(modifier = Modifier.height(16.dp))
//Setup for basic time data (lesson/break length etc.)
if (activityType == "TimeSetup") {
//Time input begin of first lesson
Text(
text = "Beginn der 1. Stunde",
modifier = Modifier.fillMaxWidth(),
@@ -268,6 +287,7 @@ fun TimeTableSetupContent(activity: ComponentActivity, loadedLessons: List<Lesso
Spacer(modifier = Modifier.height(16.dp))
//Duration of one lesson
OutlinedTextField(
value = lessonLength,
onValueChange = { lessonLength = it },
@@ -282,6 +302,7 @@ fun TimeTableSetupContent(activity: ComponentActivity, loadedLessons: List<Lesso
Spacer(modifier = Modifier.height(16.dp))
//Input amount of breaks
OutlinedTextField(
value = breakAmnt,
onValueChange = { breakAmnt = it},
@@ -294,17 +315,20 @@ fun TimeTableSetupContent(activity: ComponentActivity, loadedLessons: List<Lesso
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.NumberPassword)
)
//Input of length and start time for each break
if (breakAmnt != "") {
//declaration of sharedPreferences for break data
for (i in 0 until breakAmnt.toInt()) {
var currentBrakeStartTime by remember{
mutableStateOf(sharedPreferences.getFloat("Brake${i}StartTime", 0.0f))
var currentBreakStartTime by remember{
mutableStateOf(sharedPreferences.getFloat("break${i}StartTime", 0.0f))
}
var currentBrakeLength by remember{
mutableStateOf(sharedPreferences.getInt("Brake${i}Length", 0).toString())
var currentBreakLength by remember{
mutableStateOf(sharedPreferences.getInt("break${i}Length", 0).toString())
}
Spacer(modifier = Modifier.height(16.dp))
//Input start time (break)
Text(
text = "Startzeit der ${i + 1}. Pause:",
modifier = Modifier.fillMaxWidth(),
@@ -316,8 +340,8 @@ fun TimeTableSetupContent(activity: ComponentActivity, loadedLessons: List<Lesso
val mHour = c.get(Calendar.HOUR_OF_DAY)
val mMinute = c.get(Calendar.MINUTE)
val timePickerDialog = TimePickerDialog(activity, TimePickerDialog.OnTimeSetListener(function = { view, h, m ->
currentBrakeStartTime = h.toFloat() + (m.toFloat() / 100)
editor.putFloat("Brake${i}StartTime", currentBrakeStartTime)
currentBreakStartTime = h.toFloat() + (m.toFloat() / 100)
editor.putFloat("break${i}StartTime", currentBreakStartTime)
}), mHour, mMinute, true)
timePickerDialog.show()
},
@@ -329,7 +353,7 @@ fun TimeTableSetupContent(activity: ComponentActivity, loadedLessons: List<Lesso
val decimalFormat = DecimalFormat("00.00", symbols)
Text(
text = decimalFormat.format(currentBrakeStartTime) + " Uhr ",
text = decimalFormat.format(currentBreakStartTime) + " Uhr ",
color = MaterialTheme.colorScheme.onPrimaryContainer,
style = MaterialTheme.typography.labelMedium
)
@@ -339,11 +363,14 @@ fun TimeTableSetupContent(activity: ComponentActivity, loadedLessons: List<Lesso
Spacer(modifier = Modifier.height(5.dp))
//Input duration (break)
OutlinedTextField(
value = currentBrakeLength,
value = currentBreakLength,
onValueChange = {
currentBrakeLength = it
editor.putInt("Brake${i}Length", currentBrakeLength.toInt())},
currentBreakLength = it
if (currentBreakLength != "") {
editor.putInt("break${i}Length", currentBreakLength.toInt())
}},
label = { Text(text = "Länge der ${i + 1}. Pause in min") },
modifier = Modifier.fillMaxWidth(),
singleLine = true,
@@ -358,9 +385,27 @@ fun TimeTableSetupContent(activity: ComponentActivity, loadedLessons: List<Lesso
Spacer(modifier = Modifier.height(10.dp))
Row {
//Go back to StundenplanActivity
FilledTonalButton(
onClick = {
editor.putInt("lessonLength", lessonLength.toInt())
editor.putInt("breakAmnt", breakAmnt.toInt())
editor.apply()
activity.finish()
if (setupDone) {
//Reopen of activity so values will be updated
val intent = Intent(activity, StundenplanActivity::class.java)
//Remove previous StundenplanActivity from activity stack so when going back later it won't exist twice
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
startActivity(activity, intent, null)
}
else {
val intent = Intent(activity, MainActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
startActivity(activity, intent, null)
}
},
modifier = Modifier
.padding(5.dp)
@@ -377,6 +422,7 @@ fun TimeTableSetupContent(activity: ComponentActivity, loadedLessons: List<Lesso
.width(5.dp)
)
//Move on to DaySetup
Button(
onClick = {
editor.putInt("lessonLength", lessonLength.toInt())
@@ -385,6 +431,7 @@ fun TimeTableSetupContent(activity: ComponentActivity, loadedLessons: List<Lesso
activity.finish()
val intent = Intent(activity, TimeTableSetupActivity::class.java).apply {
putExtra(TimeTableSetupActivity.TYPE_KEY, "DaySetup")
//State 0 for indexing days (0..4)
putExtra(TimeTableSetupActivity.STATE_KEY, "0")
}
startActivity(activity, intent, null)
@@ -400,15 +447,20 @@ fun TimeTableSetupContent(activity: ComponentActivity, loadedLessons: List<Lesso
}
}
}
//DaySetup for information on the lessons (teacher, subject, amount per day, etc.)
else if (activityType == "DaySetup") {
var state by remember {
//State that defines the current day (e.g. for LessonData or the Tab highlighting)
val state by remember {
mutableStateOf(activityState.toInt())
}
//SharedPreferences for the amount of hours of each day (indexed by state --> 0..4)
var currentLessonAmount by remember {
mutableStateOf(sharedPreferences.getInt("lessonAmount${listOfDays[state]}", 0).toString())
}
//TabRow with Tabs to visualize the days; no onClick fun and thus the custom ripple theme
CompositionLocalProvider(LocalRippleTheme provides CustomRippleTheme()) {
TabRow(selectedTabIndex = state,
containerColor = MaterialTheme.colorScheme.primaryContainer) {
@@ -429,6 +481,7 @@ fun TimeTableSetupContent(activity: ComponentActivity, loadedLessons: List<Lesso
Spacer(modifier = Modifier.height(16.dp))
//Input of the amount of lessons on the current day
OutlinedTextField(
value = currentLessonAmount,
onValueChange = {
@@ -449,70 +502,89 @@ fun TimeTableSetupContent(activity: ComponentActivity, loadedLessons: List<Lesso
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.NumberPassword)
)
//Creation of TextField for further input for the lessons themselves + saveUsage into DataStore --> saveLessonUsage(...)
if (currentLessonAmount != "") {
for (i in lessons.size until currentLessonAmount.toInt()) {
lessons = lessons + LessonData("", "", "")
}
while (currentLessonAmount.toInt() < lessons.size) {
lessons = lessons.drop(1)
}
lessons.forEachIndexed() { index, lessonData ->
var currentSubject by remember {
mutableStateOf(lessonData.subject)
if (currentLessonAmount != "0") {
//Creation/Removal of the current amount of LessonData object depending pn currentLessonAmount
for (i in lessons.size until currentLessonAmount.toInt()) {
lessons = lessons + LessonData("", "", "")
}
var currentTeacher by remember {
mutableStateOf(lessonData.teacher)
while (currentLessonAmount.toInt() < lessons.size) {
lessons = lessons.dropLast(1)
}
var currentRoom by remember {
mutableStateOf(lessonData.room)
lessons.forEachIndexed { index, lessonData ->
//Input variables
var currentSubject by remember {
mutableStateOf(lessonData.subject)
}
var currentTeacher by remember {
mutableStateOf(lessonData.teacher)
}
var currentRoom by remember {
mutableStateOf(lessonData.room)
}
//Input of the subject of the current lesson
OutlinedTextField(
value = currentSubject,
onValueChange = {
currentSubject = it
lessonData.subject = it
saveLessonsUsage(activity, lessons, state)
},
label = { Text(text = "Fach der ${index + 1}. Stunde") },
modifier = Modifier.fillMaxWidth(),
singleLine = true,
shape = RoundedCornerShape(20),
textStyle = MaterialTheme.typography.labelMedium,
colors = inputFieldColors,
)
//Input of the room of the current lesson
OutlinedTextField(
value = currentRoom,
onValueChange = {
currentRoom = it
lessonData.room = it
saveLessonsUsage(activity, lessons, state)
},
label = { Text(text = "Raum der ${index + 1}. Stunde") },
modifier = Modifier.fillMaxWidth(),
singleLine = true,
shape = RoundedCornerShape(20),
textStyle = MaterialTheme.typography.labelMedium,
colors = inputFieldColors,
)
//Input of the teacher of the current lesson
OutlinedTextField(
value = currentTeacher,
onValueChange = {
currentTeacher = it
lessonData.teacher = it
saveLessonsUsage(activity, lessons, state)
},
label = { Text(text = "Lehrer der ${index + 1}. Stunde") },
modifier = Modifier.fillMaxWidth(),
singleLine = true,
shape = RoundedCornerShape(20),
textStyle = MaterialTheme.typography.labelMedium,
colors = inputFieldColors,
)
}
OutlinedTextField(
value = currentSubject,
onValueChange = {
currentSubject = it
lessonData.subject = it
saveLessonsUsage(activity, lessons, state)
},
label = { Text(text = "Fach der ${index + 1}. Stunde") },
modifier = Modifier.fillMaxWidth(),
singleLine = true,
shape = RoundedCornerShape(20),
textStyle = MaterialTheme.typography.labelMedium,
colors = inputFieldColors,
)
OutlinedTextField(
value = currentTeacher,
onValueChange = {
currentTeacher = it
lessonData.teacher = it
saveLessonsUsage(activity, lessons, state)
},
label = { Text(text = "Lehrer der ${index + 1}. Stunde") },
modifier = Modifier.fillMaxWidth(),
singleLine = true,
shape = RoundedCornerShape(20),
textStyle = MaterialTheme.typography.labelMedium,
colors = inputFieldColors,
)
OutlinedTextField(
value = currentRoom,
onValueChange = {
currentRoom = it
lessonData.room = it
saveLessonsUsage(activity, lessons, state)
},
label = { Text(text = "Raum der ${index + 1}. Stunde") },
modifier = Modifier.fillMaxWidth(),
singleLine = true,
shape = RoundedCornerShape(20),
textStyle = MaterialTheme.typography.labelMedium,
colors = inputFieldColors,
)
saveLessonsUsage(activity, lessons, state)
}
//save an empty list into DataStore currentLessonAmount == 0
else {
saveLessonsUsage(activity, emptyList(), state)
}
}
Spacer(modifier = Modifier.height(16.dp))
//Checkbox on the friday page (state == 4) to prevent setup from automatically openening next time
if (state == 4) {
Box(
modifier = Modifier
@@ -521,7 +593,7 @@ fun TimeTableSetupContent(activity: ComponentActivity, loadedLessons: List<Lesso
.background(color = MaterialTheme.colorScheme.onPrimaryContainer)
)
Row () {
Row {
Text(
text = "Ertes Setup beendet?",
modifier = Modifier.align(Alignment.CenterVertically),
@@ -531,16 +603,19 @@ fun TimeTableSetupContent(activity: ComponentActivity, loadedLessons: List<Lesso
}
}
//Go back
Row {
FilledTonalButton(
onClick = {
activity.finish()
//To TimeSetup
if (state == 0) {
val intent = Intent(activity, TimeTableSetupActivity::class.java).apply {
putExtra(TimeTableSetupActivity.TYPE_KEY, "TimeSetup")
}
startActivity(activity, intent, null)
}
//To the day before (STATE_KEY -= 1)
else {
val intent = Intent(activity, TimeTableSetupActivity::class.java).apply {
putExtra(TimeTableSetupActivity.TYPE_KEY, "DaySetup")
@@ -548,7 +623,6 @@ fun TimeTableSetupContent(activity: ComponentActivity, loadedLessons: List<Lesso
}
startActivity(activity, intent, null)
}
},
modifier = Modifier
.padding(5.dp)
@@ -565,9 +639,11 @@ fun TimeTableSetupContent(activity: ComponentActivity, loadedLessons: List<Lesso
.width(5.dp)
)
//Go forwards
Button(
onClick = {
activity.finish()
//To next day (STATE_KEY += 1)
if (state != 4) {
val intent = Intent(activity, TimeTableSetupActivity::class.java).apply {
putExtra(TimeTableSetupActivity.TYPE_KEY, "DaySetup")
@@ -575,8 +651,14 @@ fun TimeTableSetupContent(activity: ComponentActivity, loadedLessons: List<Lesso
}
startActivity(activity, intent, null)
}
//To Stundenplan
else {
editor.putBoolean("setupDone", setupDone)
//Reopen of activity so values will be updated
val intent = Intent(activity, StundenplanActivity::class.java)
//Remove previous StundenplanActivity from activity stack so when going back later it won't exist twice
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
startActivity(activity, intent, null)
}
editor.apply()
},
@@ -596,6 +678,7 @@ fun TimeTableSetupContent(activity: ComponentActivity, loadedLessons: List<Lesso
}
}
//AlertDialog to inform the user of the possibility of changing all inputs later
if (showInfo) {
AlertDialog(
onDismissRequest = { showInfo = false },
@@ -618,53 +701,9 @@ fun TimeTableSetupContent(activity: ComponentActivity, loadedLessons: List<Lesso
.padding(5.dp)
)
}
if (showDeleteConfirmation) {
AlertDialog(
onDismissRequest = { showDeleteConfirmation = false },
text = {
Text(
text = "Möchten Sie wirklich die Anmeldedaten 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 {
editor.putString("maxLessons", "")
editor.apply()
showDeleteConfirmation = false
activity.finish()
}
)
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 TestButton(text: String, onClick: ()-> Unit){
Button(onClick = onClick,) {
Text(text = text)
}
}
//Function that implements the save of List<LessonData>
fun saveLessonsUsage(context: Context, lessons: List<LessonData>, int: Int) {
CoroutineScope(Dispatchers.IO).launch {
saveLessons(context, lessons, listOfDays[int])

View File

@@ -1,5 +1,9 @@
package com.schoolapp.cleverclass
import android.app.Activity
import android.content.Context
import android.content.Intent
import androidx.activity.ComponentActivity
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
@@ -17,6 +21,10 @@ import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.io.File
const val NO_INTERNET_CONNECTION_CODE = -1
@@ -64,3 +72,46 @@ fun StaticLoadingScreen(){
}
}
}
fun deleteAllData(activity: ComponentActivity){
val sharedPrefs = listOf("Settings", "DSBmobile", "gradeAverages", "TimeTable")
for (prefName in sharedPrefs) {
val sharedPreferences = activity.getSharedPreferences(prefName, Context.MODE_PRIVATE)
val editor = sharedPreferences.edit()
editor.clear()
editor.apply()
}
clearFolder(activity.filesDir)
clearFolder(activity.cacheDir)
CoroutineScope(Dispatchers.Main).launch {
restartApp(activity)
}
}
fun clearFolder(directory: File) {
if (directory.exists()) {
val files = directory.listFiles()
if (files != null) {
for (file in files) {
if (file.isDirectory) {
clearFolder(file)
}
file.delete()
}
}
}
}
fun restartApp(context: Context) {
val packageManager = context.packageManager
val intent = packageManager.getLaunchIntentForPackage(context.packageName)
intent?.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
intent?.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
context.startActivity(intent)
if (context is Activity) {
context.finish()
}
Runtime.getRuntime().exit(0)
}

View File

@@ -8,9 +8,9 @@ val Black80 = Color(0xFF333333)
val Black70 = Color(0xFF4B4B4B)
val White100 = Color(0xFFFFFFFF)
val White90 = Color(0xFFEBEBEB)
val White90 = Color(0xFFFAFAFA)
val White80 = Color(0xFFD3D3D3)
val White70 = Color(0xFFBBBBBB)
val White70 = Color(0xFFAFAFAF)
val TextOnColouredButton = Color(0xFF121212)

View File

@@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#000000"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M19,4L5,4c-1.11,0 -2,0.9 -2,2v12c0,1.1 0.89,2 2,2h4v-2L5,18L5,8h14v10h-4v2h4c1.1,0 2,-0.9 2,-2L21,6c0,-1.1 -0.89,-2 -2,-2zM12,10l-4,4h3v6h2v-6h3l-4,-4z"/>
</vector>