diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml
deleted file mode 100644
index 0c0c338..0000000
--- a/.idea/deploymentTargetDropDown.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index f0fdb85..5dd62a3 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -61,11 +61,13 @@ dependencies {
implementation("androidx.datastore:datastore-preferences:1.0.0")
implementation("com.google.code.gson:gson:2.9.0")
implementation(platform("androidx.compose:compose-bom:2023.03.00"))
+ implementation(platform("androidx.compose:compose-bom:2023.03.00"))
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.5")
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
androidTestImplementation("androidx.compose.ui:ui-test-junit4")
androidTestImplementation(platform("androidx.compose:compose-bom:2023.03.00"))
+ androidTestImplementation(platform("androidx.compose:compose-bom:2023.03.00"))
debugImplementation("androidx.compose.ui:ui-tooling")
debugImplementation("androidx.compose.ui:ui-test-manifest")
}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 6071109..912e310 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -15,6 +15,11 @@
android:supportsRtl="true"
android:theme="@style/Theme.CleverClass"
tools:targetApi="31">
+
{
- DSBLoading()
+ -2 -> {
+ LoadingScreen()
}
- -1 -> {
- DSBNoInternet()
+ NO_INTERNET_CONNECTION_CODE -> {
+ DSBError("Keine Internetverbindung")
}
- else -> {
+ 1 ->{
+ DSBError("Login fehlgeschlagen")
+ }
+ 0 -> {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
@@ -137,9 +160,7 @@ fun DSBContent(activity: ComponentActivity){
) {
Spacer(modifier = Modifier.height(32.dp))
- val mainFolder = File(activity.filesDir, "dataDSB")
-
- mainFolder.listFiles()?.forEach { folder ->
+ folders.forEach { folder ->
DayPrefab(folder, activity)
Spacer(modifier = Modifier.height(32.dp))
Divider()
@@ -147,28 +168,43 @@ fun DSBContent(activity: ComponentActivity){
}
}
}
+ else -> {
+ DSBError("Leider ist ein Problem aufgetreten\nFehlercode: $loadingState")
+ }
+ }
+ }
+
+ // changes state when Shared Preference is updated
+ val observer = remember {
+ SharedPreferences.OnSharedPreferenceChangeListener { _, key ->
+ if (key == "password" || key == "username") {
+ loadingState = -2
+
+ GlobalScope.launch(Dispatchers.IO) {
+ loadingState = downloadDSB(activity)
+ folders = mainFolder.listFiles()
+ }
+ }
+ }
+ }
+
+ // handles observer disposal
+ DisposableEffect(Unit) {
+ sharedPreferences.registerOnSharedPreferenceChangeListener(observer)
+ onDispose {
+ sharedPreferences.unregisterOnSharedPreferenceChangeListener(observer)
}
}
}
@Composable
-fun DSBLoading(){
- Box(
- modifier = Modifier.fillMaxSize(),
- contentAlignment = Alignment.Center
- ){
- CircularProgressIndicator()
- }
-}
-
-@Composable
-fun DSBNoInternet(){
+fun DSBError(message: String){
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center
){
Text(
- text = "Keine Internetverbindung",
+ text = message,
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onBackground
)
diff --git a/app/src/main/java/com/schoolapp/cleverclass/DSBDayViewActivity.kt b/app/src/main/java/com/schoolapp/cleverclass/DSBDayViewActivity.kt
index 9e1d0db..12858df 100644
--- a/app/src/main/java/com/schoolapp/cleverclass/DSBDayViewActivity.kt
+++ b/app/src/main/java/com/schoolapp/cleverclass/DSBDayViewActivity.kt
@@ -69,7 +69,7 @@ fun DSBDayViewContent(activity: ComponentActivity){
colors = TopAppBarDefaults.centerAlignedTopAppBarColors(MaterialTheme.colorScheme.primaryContainer),
title = {
Text(
- text = information.get("PlanInfo").toString(),
+ text = information.get("PlanInfo").toString().removeSuffix(".pdf"),
style = MaterialTheme.typography.headlineSmall,
color = MaterialTheme.colorScheme.onPrimaryContainer
)},
diff --git a/app/src/main/java/com/schoolapp/cleverclass/DSBDownloader.kt b/app/src/main/java/com/schoolapp/cleverclass/DSBDownloader.kt
index 7e2d571..9a012f5 100644
--- a/app/src/main/java/com/schoolapp/cleverclass/DSBDownloader.kt
+++ b/app/src/main/java/com/schoolapp/cleverclass/DSBDownloader.kt
@@ -14,26 +14,31 @@ import java.util.zip.GZIPInputStream
import java.util.zip.GZIPOutputStream
import java.io.ByteArrayInputStream
import java.io.FileOutputStream
+import java.net.SocketException
import java.time.LocalDateTime
import java.util.UUID
suspend fun downloadDSB(context: Context): Int{
+ val sharedPreferences = context.getSharedPreferences("DSBmobile", Context.MODE_PRIVATE)
+ val username = sharedPreferences.getString("username", "").toString()
+ val password = sharedPreferences.getString("password", "").toString()
+
if(!isInternetAvailable(context))
- return -1
+ return NO_INTERNET_CONNECTION_CODE
val mainDir = createDataFolder(context)
- val jsonResponse = downloadDataTask()
+ val jsonResponse = JSONObject(downloadDataTask(username = username, password = password))
+ if(jsonResponse.get("Resultcode") != 0)
+ return jsonResponse.getInt("Resultcode")
- downloadImagesTask(jsonResponse, mainDir)
-
- return 0
+ return downloadImagesTask(jsonResponse, mainDir)
}
-private fun downloadDataTask() : String {
+private fun downloadDataTask(username: String, password: String) : String {
return try {
- val requestBody = createRequestBody()
+ val requestBody = createRequestBody(username = username, password = password)
val jsonRequest = createJsonRequest(requestBody)
val responseData = fetchData(jsonRequest)
@@ -45,9 +50,7 @@ private fun downloadDataTask() : String {
}
}
-private fun createRequestBody(): String {
- val username = "149002"
- val password = "Vertretungsplan"
+private fun createRequestBody(username: String, password: String): String {
val currentDateTime = LocalDateTime.now().toString()
val requestBody = JSONObject().apply {
@@ -118,11 +121,10 @@ private fun decompressGZIPAndDecodeBase64(compressedData: String): String {
return outputStream.toString("UTF-8")
}
-private fun downloadImagesTask(jsonResponse: String, mainDir : File){
+private fun downloadImagesTask(jsonResponse: JSONObject, mainDir : File) : Int {
clearFolder(mainDir)
- val jsonResponseObject = JSONObject(jsonResponse)
- val jsonDaysObject = jsonResponseObject.getJSONArray("ResultMenuItems").getJSONObject(0).getJSONArray("Childs").getJSONObject(0).getJSONObject("Root").getJSONArray("Childs")
+ val jsonDaysObject = jsonResponse.getJSONArray("ResultMenuItems").getJSONObject(0).getJSONArray("Childs").getJSONObject(0).getJSONObject("Root").getJSONArray("Childs")
for (d in 0 until jsonDaysObject.length()) {
val jsonDayObject = jsonDaysObject.getJSONObject(d)
@@ -139,9 +141,12 @@ private fun downloadImagesTask(jsonResponse: String, mainDir : File){
val pageIndex = jsonPageObject.get("Index")
val imageLink = jsonPageObject.get("Detail").toString()
- downloadImage(day, URL(imageLink), "$pageIndex.jpg")
+ val downloadState = downloadImage(day, URL(imageLink), "$pageIndex.jpg")
+ if (downloadState != 0)
+ return downloadState
}
}
+ return 0
}
private fun createDayInformationJson(folder: File, jsonDayObject: JSONObject){
@@ -158,22 +163,29 @@ private fun createDayInformationJson(folder: File, jsonDayObject: JSONObject){
infoFile.writeText(infoJson.toString())
}
-private fun downloadImage(folder: File, url: URL, fileName: String){
+private fun downloadImage(folder: File, url: URL, fileName: String) : Int {
val file = File(folder, fileName)
- val connection = url.openConnection()
- val inputStream = connection.getInputStream()
- val outputStream = FileOutputStream(file)
+ try {
+ val connection = url.openConnection()
+ val inputStream = connection.getInputStream()
+ val outputStream = FileOutputStream(file)
- val buffer = ByteArray(1024)
- var bytesRead: Int
+ val buffer = ByteArray(1024)
+ var bytesRead: Int
- while (inputStream.read(buffer).also { bytesRead = it } != -1) {
- outputStream.write(buffer, 0, bytesRead)
+ while (inputStream.read(buffer).also { bytesRead = it } != -1) {
+ outputStream.write(buffer, 0, bytesRead)
+ }
+
+ inputStream.close()
+ outputStream.close()
}
-
- inputStream.close()
- outputStream.close()
+ catch (e: SocketException){
+ Log.d("ImageDownloader", e.toString())
+ return NO_INTERNET_CONNECTION_CODE
+ }
+ return 0
}
private fun createDataFolder(context: Context) : File {
diff --git a/app/src/main/java/com/schoolapp/cleverclass/DSBLoginActivity.kt b/app/src/main/java/com/schoolapp/cleverclass/DSBLoginActivity.kt
new file mode 100644
index 0000000..53557e5
--- /dev/null
+++ b/app/src/main/java/com/schoolapp/cleverclass/DSBLoginActivity.kt
@@ -0,0 +1,316 @@
+package com.schoolapp.cleverclass
+
+import android.content.Context
+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.Arrangement
+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.fillMaxHeight
+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.rememberScrollState
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.foundation.text.KeyboardOptions
+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.Info
+import androidx.compose.material3.AlertDialog
+import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.Icon
+import androidx.compose.material3.IconButton
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.OutlinedTextField
+import androidx.compose.material3.Surface
+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.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.res.painterResource
+import androidx.compose.ui.text.input.KeyboardType
+import androidx.compose.ui.text.input.PasswordVisualTransformation
+import androidx.compose.ui.text.input.VisualTransformation
+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
+
+private lateinit var activityType : String
+
+class DSBLoginActivity : ComponentActivity() {
+ companion object{
+ const val TYPE_KEY = "type_key"
+ }
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ activityType = intent.getStringExtra(TYPE_KEY).toString()
+
+ setContent {
+ CleverClassTheme {
+ Surface(
+ modifier = Modifier.fillMaxSize(),
+ color = MaterialTheme.colorScheme.background
+ ) {
+ DSBLoginContent(activity = this)
+ }
+ }
+ }
+ }
+}
+
+
+// Content of DSBLogin
+@OptIn(ExperimentalMaterial3Api::class)
+@Composable
+fun DSBLoginContent(activity: ComponentActivity){
+ val inputFieldColors = TextFieldDefaults.outlinedTextFieldColors(
+ textColor = MaterialTheme.colorScheme.onPrimaryContainer,
+ containerColor = MaterialTheme.colorScheme.secondaryContainer,
+ cursorColor = InputPrimaryColor,
+ selectionColors = TextSelectionColors(
+ handleColor = InputPrimaryColor,
+ backgroundColor = InputSecondaryColor
+ ),
+ focusedBorderColor = InputSecondaryColor,
+ unfocusedBorderColor = Color.Transparent
+ )
+
+ val sharedPreferences = activity.getSharedPreferences("DSBmobile", Context.MODE_PRIVATE)
+ val editor = sharedPreferences.edit()
+
+ var username by remember {
+ mutableStateOf(sharedPreferences.getString("username", "").toString())
+ }
+ var password by remember {
+ mutableStateOf(sharedPreferences.getString("password", "").toString())
+ }
+ var showPassword by remember {
+ mutableStateOf(false)
+ }
+
+ var showInfo by remember {
+ mutableStateOf(false)
+ }
+ var showDeleteConfirmation by remember {
+ mutableStateOf(false)
+ }
+
+ Column {
+ TopAppBar(
+ colors = TopAppBarDefaults.centerAlignedTopAppBarColors(MaterialTheme.colorScheme.primaryContainer),
+ title = { Text(text = "") },
+ navigationIcon = {
+ IconButton(onClick = { activity.finish() }) {
+ Icon(
+ imageVector = Icons.Filled.ArrowBack,
+ contentDescription = null,
+ modifier = Modifier.size(28.dp),
+ tint = MaterialTheme.colorScheme.onPrimaryContainer
+ )
+ }
+ },
+ modifier = Modifier.fillMaxWidth()
+ )
+
+ Column(
+ verticalArrangement = Arrangement.Center,
+ modifier = Modifier
+ .fillMaxHeight()
+ .verticalScroll(rememberScrollState())
+ ) {
+ Surface(
+ color = MaterialTheme.colorScheme.primaryContainer,
+ shape = RoundedCornerShape(20),
+ modifier = Modifier.padding(16.dp)
+ ) {
+ Column(horizontalAlignment = Alignment.CenterHorizontally,
+ modifier = Modifier.padding(16.dp)
+ ) {
+ Row(verticalAlignment = Alignment.CenterVertically) {
+ Text(
+ text = "DSBmobile Login Daten",
+ style = MaterialTheme.typography.labelMedium,
+ color = MaterialTheme.colorScheme.onPrimaryContainer,
+ modifier = Modifier.padding(10.dp)
+ )
+
+ Spacer(modifier = Modifier.weight(1f))
+
+ if (activityType == "Settings")
+ IconButton(onClick = { showDeleteConfirmation = !showDeleteConfirmation }) {
+ Icon(
+ imageVector = Icons.Outlined.Delete,
+ contentDescription = null,
+ modifier = Modifier.size(28.dp),
+ tint = MaterialTheme.colorScheme.onPrimaryContainer
+ )
+ }
+ else if (activityType == "FirstTime")
+ IconButton(onClick = { showInfo = !showInfo }) {
+ Icon(
+ imageVector = Icons.Outlined.Info,
+ contentDescription = null,
+ tint = MaterialTheme.colorScheme.onPrimaryContainer
+ )
+ }
+ }
+
+ Spacer(modifier = Modifier.height(16.dp))
+
+ OutlinedTextField(
+ value = username,
+ onValueChange = { username = it },
+ placeholder = {
+ Text(
+ text = "Benutzername",
+ style = MaterialTheme.typography.labelMedium,
+ color = MaterialTheme.colorScheme.primaryContainer
+ )
+ },
+ modifier = Modifier.fillMaxWidth(),
+ singleLine = true,
+ shape = RoundedCornerShape(20),
+ textStyle = MaterialTheme.typography.labelMedium,
+ colors = inputFieldColors
+ )
+
+ Spacer(modifier = Modifier.height(16.dp))
+
+ OutlinedTextField(
+ value = password,
+ onValueChange = { password = it },
+ placeholder = {
+ Text(
+ text = "Passwort",
+ style = MaterialTheme.typography.labelMedium,
+ color = MaterialTheme.colorScheme.primaryContainer
+ )
+ },
+ modifier = Modifier.fillMaxWidth(),
+ singleLine = true,
+ shape = RoundedCornerShape(20),
+ textStyle = MaterialTheme.typography.labelMedium,
+ colors = inputFieldColors,
+ visualTransformation = if(showPassword) VisualTransformation.None else PasswordVisualTransformation(),
+ keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password),
+ trailingIcon = {
+ IconButton(onClick = { showPassword = !showPassword })
+ {
+ Image(
+ painter = painterResource(
+ id = if(showPassword)
+ R.drawable.baseline_visibility_24
+ else
+ R.drawable.baseline_visibility_off_24
+ ),
+ contentDescription = null,
+ )
+ }
+ }
+ )
+
+ Spacer(modifier = Modifier.height(10.dp))
+
+ Box(
+ contentAlignment = Alignment.Center,
+ modifier = Modifier.clickable {
+ editor.putString("username", username)
+ editor.putString("password", password)
+ editor.apply()
+ activity.finish()
+ }
+ ) {
+ Text(
+ text = "Speichen",
+ color = MaterialTheme.colorScheme.secondary,
+ style = MaterialTheme.typography.labelMedium,
+ modifier = Modifier.padding(10.dp)
+ )
+ }
+ }
+ }
+ }
+ }
+
+ if (showInfo) {
+ AlertDialog(
+ onDismissRequest = { showInfo = false },
+ text = {
+ Text(
+ text = "Der Benutzername und das Passwort können später in den Einstellungen geändert 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)
+ )
+ }
+
+ 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("username", "")
+ editor.putString("password", "")
+ 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
+ )
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/schoolapp/cleverclass/NotenActivity.kt b/app/src/main/java/com/schoolapp/cleverclass/NotenActivity.kt
index 0c99ee9..15f44b2 100644
--- a/app/src/main/java/com/schoolapp/cleverclass/NotenActivity.kt
+++ b/app/src/main/java/com/schoolapp/cleverclass/NotenActivity.kt
@@ -323,7 +323,7 @@ fun FachButton(
}
}
- // handles observer creation and disposal
+ // handles observer disposal
DisposableEffect(Unit) {
sharedPreferences.registerOnSharedPreferenceChangeListener(observer)
onDispose {
diff --git a/app/src/main/java/com/schoolapp/cleverclass/SettingsActivity.kt b/app/src/main/java/com/schoolapp/cleverclass/SettingsActivity.kt
index 46aa53d..e57cabb 100644
--- a/app/src/main/java/com/schoolapp/cleverclass/SettingsActivity.kt
+++ b/app/src/main/java/com/schoolapp/cleverclass/SettingsActivity.kt
@@ -8,12 +8,14 @@ import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
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
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.layout.wrapContentHeight
@@ -98,6 +100,25 @@ fun SettingsContent(activity: ComponentActivity) {
Setting(text = "Periodensystem", sharedPreferences, editor)
Setting(text = "Mebis", sharedPreferences, editor)
Setting(text = "DSBmobile", sharedPreferences, editor)
+ Spacer(modifier = Modifier.height(16.dp))
+ Divider()
+ Box(
+ modifier = Modifier
+ .fillMaxWidth()
+ .clickable {
+ val intent = Intent(activity, DSBLoginActivity::class.java).apply {
+ putExtra(DSBLoginActivity.TYPE_KEY, "Settings")
+ }
+ activity.startActivity(intent)
+ }
+ ) {
+ Text(
+ text = "DSBmobile Daten",
+ color = MaterialTheme.colorScheme.onBackground,
+ style = MaterialTheme.typography.labelMedium,
+ modifier = Modifier.padding(16.dp)
+ )
+ }
}
// About Button
@@ -123,7 +144,6 @@ fun SettingsContent(activity: ComponentActivity) {
}
}
-
@Composable
fun Setting(text : String, sharedPreferences: SharedPreferences, editor: Editor){
val checkedState = remember { mutableStateOf(sharedPreferences.getBoolean(text, true)) }
@@ -139,8 +159,10 @@ fun Setting(text : String, sharedPreferences: SharedPreferences, editor: Editor)
}
)
Spacer(modifier = Modifier.width(16.dp))
- Text(text = text,
+ Text(
+ text = text,
color = MaterialTheme.colorScheme.onBackground,
- style = MaterialTheme.typography.labelMedium)
+ style = MaterialTheme.typography.labelMedium
+ )
}
}
diff --git a/app/src/main/java/com/schoolapp/cleverclass/Utilities.kt b/app/src/main/java/com/schoolapp/cleverclass/Utilities.kt
index a8d2e04..f191763 100644
--- a/app/src/main/java/com/schoolapp/cleverclass/Utilities.kt
+++ b/app/src/main/java/com/schoolapp/cleverclass/Utilities.kt
@@ -1,5 +1,15 @@
package com.schoolapp.cleverclass
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.material3.CircularProgressIndicator
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+
+
+const val NO_INTERNET_CONNECTION_CODE = -1
+
fun formatFloat(number: Float): String {
var formattedString = number.toString()
@@ -9,4 +19,14 @@ fun formatFloat(number: Float): String {
formattedString = "0.0"
return formattedString
+}
+
+@Composable
+fun LoadingScreen(){
+ Box(
+ modifier = Modifier.fillMaxSize(),
+ contentAlignment = Alignment.Center
+ ){
+ CircularProgressIndicator()
+ }
}
\ No newline at end of file
diff --git a/app/src/main/res/drawable/baseline_visibility_24.xml b/app/src/main/res/drawable/baseline_visibility_24.xml
new file mode 100644
index 0000000..b923c39
--- /dev/null
+++ b/app/src/main/res/drawable/baseline_visibility_24.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/app/src/main/res/drawable/baseline_visibility_off_24.xml b/app/src/main/res/drawable/baseline_visibility_off_24.xml
new file mode 100644
index 0000000..00c8a20
--- /dev/null
+++ b/app/src/main/res/drawable/baseline_visibility_off_24.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 6815568..23f475c 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -9,4 +9,5 @@
DSBActivity
MebisActivity
DSBDayViewActivity
+ DSBLoginActivity
\ No newline at end of file