Compare commits

..

14 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
8 changed files with 267 additions and 61 deletions

View File

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

View File

@@ -83,7 +83,7 @@ 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()
@@ -98,7 +98,7 @@ fun AboutContent(activity: ComponentActivity){
) {
Row {
Text(
text = "Unterstütze die Entwickler",
text = "Support the Devs",
style = MaterialTheme.typography.bodySmall,
color = 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

@@ -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

@@ -7,21 +7,23 @@ import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
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.defaultMinSize
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.wrapContentWidth
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
@@ -31,8 +33,13 @@ 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.draw.scale
import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.unit.dp
import androidx.core.content.ContextCompat.startActivity
@@ -56,7 +63,7 @@ class StundenplanActivity : ComponentActivity() {
//Loading saved lessons when NOT auto-loading the setup
if (setupDone) {
listOfDays.forEachIndexed() { index, dayLessons ->
listOfDays.forEachIndexed { index, dayLessons ->
CoroutineScope(Dispatchers.IO).launch {
getLessons(this@StundenplanActivity, dayLessons).collect { savedLessons ->
lessons[index] = savedLessons.toMutableList()
@@ -102,7 +109,11 @@ fun StundenplanContent(activity: ComponentActivity, loadedLessons: List<List<Les
listOfBreakLengths.add(sharedPreferences.getInt("break${i}Length", 0))
}
Column() {
var showInfo by remember {
mutableStateOf(false)
}
Column {
TopAppBar(
colors = TopAppBarDefaults.centerAlignedTopAppBarColors(MaterialTheme.colorScheme.primaryContainer),
title = {
@@ -121,6 +132,16 @@ fun StundenplanContent(activity: ComponentActivity, loadedLessons: List<List<Les
}
},
actions ={
//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 = {
@@ -157,16 +178,18 @@ fun StundenplanContent(activity: ComponentActivity, loadedLessons: List<List<Les
)
//Creation of 5 Columns
loadedLessons.forEachIndexed() { index, dailyLessons ->
Column(modifier = Modifier.wrapContentWidth()) {
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(200.dp, 50.dp)
.size(250.dp, 50.dp)
.padding(3.dp)
.align(Alignment.CenterHorizontally)
.border(
width = 1.dp,
color = MaterialTheme.colorScheme.primaryContainer
@@ -186,12 +209,11 @@ fun StundenplanContent(activity: ComponentActivity, loadedLessons: List<List<Les
if (listOfBreakIndexes.indexOf(i) != -1) {
Box(
modifier = Modifier
.size(200.dp, 100.dp)
.padding(3.dp)
.size(250.dp, 100.dp)
)
}
//Else creation of a Box containing all the information from the LessonData object
else if (dailyLessons != emptyList<LessonData>()) {
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++
@@ -211,6 +233,29 @@ fun StundenplanContent(activity: ComponentActivity, loadedLessons: List<List<Les
)
}
}
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
@@ -225,21 +270,51 @@ data class LessonData(
// contains the information from the corresponding LessonData object
@Composable
fun LessonBox(subject: String, teacher: String, room: String) {
Box(modifier = Modifier
.defaultMinSize(200.dp, 100.dp)
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.align(Alignment.Center),
text = "$subject\n@$room\n/w$teacher",
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
)
}
}
}
}
//Left-/Right-Handed info Column
@Composable
@@ -297,7 +372,9 @@ fun InfoColumn(loadedLessons: List<List<LessonData>>, breakAmnt: Int, breaksStar
) {
//"Pause" String instead of indexing
Text(
modifier = Modifier.align(Alignment.Center),
modifier = Modifier
.align(Alignment.Center)
.scale(1.1f),
text = "Pause",
textDecoration = TextDecoration.Underline,
style = MaterialTheme.typography.labelLarge
@@ -306,7 +383,8 @@ fun InfoColumn(loadedLessons: List<List<LessonData>>, breakAmnt: Int, breaksStar
Text(
modifier = Modifier
.align(Alignment.BottomCenter)
.padding(3.dp),
.padding(3.dp)
.scale(0.8f),
text = formattedBreakTime,
style = MaterialTheme.typography.labelMedium
)
@@ -314,8 +392,8 @@ fun InfoColumn(loadedLessons: List<List<LessonData>>, breakAmnt: Int, breaksStar
lessonTimeIncrement += breaksLength[breaksStartTime.indexOf(breakTime)]
//Add info that one moe brake exists to the indexing increment
lessonNegIncrement++
//Add the extraIndex (overallIndex) into the listOfBreakIndexes list to include breaks in timetable core
listOfBreakIndexes.add(extraIndex)
//Add the extraIndex (lessonIndex) into the listOfBreakIndexes list to include breaks in timetable core
listOfBreakIndexes.add(i)
//Prevent double creation of Boxes
loopDone = true
}
@@ -333,7 +411,9 @@ fun InfoColumn(loadedLessons: List<List<LessonData>>, breakAmnt: Int, breaksStar
) {
//String with the indexing of the lessons
Text(
modifier = Modifier.align(Alignment.Center),
modifier = Modifier
.align(Alignment.Center)
.scale(1.1f),
text = "${i + 1 - lessonNegIncrement}:",
textDecoration = TextDecoration.Underline,
style = MaterialTheme.typography.labelLarge
@@ -342,7 +422,8 @@ fun InfoColumn(loadedLessons: List<List<LessonData>>, breakAmnt: Int, breaksStar
Text(
modifier = Modifier
.align(Alignment.BottomCenter)
.padding(3.dp),
.padding(3.dp)
.scale(0.8f),
text = substringHelper(extraIndex, firstLesson, lessonLength, lessonTimeIncrement),
style = MaterialTheme.typography.labelMedium
)

View File

@@ -189,10 +189,19 @@ fun TimeTableSetupContent(activity: ComponentActivity, loadedLessons: List<Lesso
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,
@@ -383,11 +392,20 @@ fun TimeTableSetupContent(activity: ComponentActivity, loadedLessons: List<Lesso
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)
@@ -492,10 +510,10 @@ fun TimeTableSetupContent(activity: ComponentActivity, loadedLessons: List<Lesso
lessons = lessons + LessonData("", "", "")
}
while (currentLessonAmount.toInt() < lessons.size) {
lessons = lessons.drop(1)
lessons = lessons.dropLast(1)
}
lessons.forEachIndexed() { index, lessonData ->
lessons.forEachIndexed { index, lessonData ->
//Input variables
var currentSubject by remember {
mutableStateOf(lessonData.subject)
@@ -555,6 +573,7 @@ fun TimeTableSetupContent(activity: ComponentActivity, loadedLessons: List<Lesso
colors = inputFieldColors,
)
}
saveLessonsUsage(activity, lessons, state)
}
//save an empty list into DataStore currentLessonAmount == 0
else {
@@ -574,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),
@@ -604,7 +623,6 @@ fun TimeTableSetupContent(activity: ComponentActivity, loadedLessons: List<Lesso
}
startActivity(activity, intent, null)
}
},
modifier = Modifier
.padding(5.dp)

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)