Finish DSBmobile
This commit is contained in:
10
.idea/deploymentTargetDropDown.xml
generated
10
.idea/deploymentTargetDropDown.xml
generated
@@ -1,10 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="deploymentTargetDropDown">
|
||||
<value>
|
||||
<entry key="app">
|
||||
<State />
|
||||
</entry>
|
||||
</value>
|
||||
</component>
|
||||
</project>
|
||||
@@ -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")
|
||||
}
|
||||
@@ -15,6 +15,11 @@
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.CleverClass"
|
||||
tools:targetApi="31">
|
||||
<activity
|
||||
android:name=".DSBLoginActivity"
|
||||
android:exported="false"
|
||||
android:label="@string/title_activity_dsblogin"
|
||||
android:theme="@style/Theme.CleverClass" />
|
||||
<activity
|
||||
android:name=".DSBDayViewActivity"
|
||||
android:exported="false"
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.schoolapp.cleverclass
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.SharedPreferences
|
||||
import android.graphics.BitmapFactory
|
||||
import android.os.Bundle
|
||||
import androidx.activity.ComponentActivity
|
||||
@@ -20,7 +21,6 @@ import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.ArrowBack
|
||||
import androidx.compose.material.icons.filled.Refresh
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.Divider
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
@@ -31,6 +31,7 @@ import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.material3.TopAppBarDefaults
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.DisposableEffect
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
@@ -54,12 +55,23 @@ class DSBActivity : ComponentActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
val sharedPreferences = this.getSharedPreferences("DSBmobile", Context.MODE_PRIVATE)
|
||||
val username = sharedPreferences.getString("username", "").toString()
|
||||
val password = sharedPreferences.getString("password", "").toString()
|
||||
|
||||
setContent {
|
||||
CleverClassTheme {
|
||||
Surface(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
color = MaterialTheme.colorScheme.background
|
||||
) {
|
||||
if(username.isEmpty() || password.isEmpty()) {
|
||||
val intent = Intent(this@DSBActivity, DSBLoginActivity::class.java).apply {
|
||||
putExtra(DSBLoginActivity.TYPE_KEY, "FirstTime")
|
||||
}
|
||||
startActivity(intent)
|
||||
}
|
||||
|
||||
DSBContent(activity = this)
|
||||
}
|
||||
}
|
||||
@@ -71,13 +83,20 @@ class DSBActivity : ComponentActivity() {
|
||||
@OptIn(ExperimentalMaterial3Api::class, DelicateCoroutinesApi::class)
|
||||
@Composable
|
||||
fun DSBContent(activity: ComponentActivity){
|
||||
val mainFolder = File(activity.filesDir, "dataDSB")
|
||||
val sharedPreferences = activity.getSharedPreferences("DSBmobile", Context.MODE_PRIVATE)
|
||||
|
||||
var loadingState by remember {
|
||||
mutableStateOf(1)
|
||||
mutableStateOf(-2)
|
||||
}
|
||||
var folders by remember {
|
||||
mutableStateOf(mainFolder.listFiles())
|
||||
}
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
GlobalScope.launch(Dispatchers.IO) {
|
||||
loadingState = downloadDSB(activity)
|
||||
folders = mainFolder.listFiles()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,12 +119,13 @@ fun DSBContent(activity: ComponentActivity){
|
||||
}
|
||||
},
|
||||
actions = {
|
||||
if(loadingState != 1) {
|
||||
if(loadingState != -2) {
|
||||
IconButton(
|
||||
onClick = {
|
||||
loadingState = 1
|
||||
loadingState = -2
|
||||
GlobalScope.launch(Dispatchers.IO) {
|
||||
loadingState = downloadDSB(activity)
|
||||
folders = mainFolder.listFiles()
|
||||
}
|
||||
}
|
||||
) {
|
||||
@@ -122,13 +142,16 @@ fun DSBContent(activity: ComponentActivity){
|
||||
)
|
||||
|
||||
when (loadingState) {
|
||||
1 -> {
|
||||
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
|
||||
)
|
||||
|
||||
@@ -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
|
||||
)},
|
||||
|
||||
@@ -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 {
|
||||
|
||||
316
app/src/main/java/com/schoolapp/cleverclass/DSBLoginActivity.kt
Normal file
316
app/src/main/java/com/schoolapp/cleverclass/DSBLoginActivity.kt
Normal file
@@ -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
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -323,7 +323,7 @@ fun FachButton(
|
||||
}
|
||||
}
|
||||
|
||||
// handles observer creation and disposal
|
||||
// handles observer disposal
|
||||
DisposableEffect(Unit) {
|
||||
sharedPreferences.registerOnSharedPreferenceChangeListener(observer)
|
||||
onDispose {
|
||||
|
||||
@@ -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
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
5
app/src/main/res/drawable/baseline_visibility_24.xml
Normal file
5
app/src/main/res/drawable/baseline_visibility_24.xml
Normal 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="M12,4.5C7,4.5 2.73,7.61 1,12c1.73,4.39 6,7.5 11,7.5s9.27,-3.11 11,-7.5c-1.73,-4.39 -6,-7.5 -11,-7.5zM12,17c-2.76,0 -5,-2.24 -5,-5s2.24,-5 5,-5 5,2.24 5,5 -2.24,5 -5,5zM12,9c-1.66,0 -3,1.34 -3,3s1.34,3 3,3 3,-1.34 3,-3 -1.34,-3 -3,-3z"/>
|
||||
</vector>
|
||||
5
app/src/main/res/drawable/baseline_visibility_off_24.xml
Normal file
5
app/src/main/res/drawable/baseline_visibility_off_24.xml
Normal 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="M12,7c2.76,0 5,2.24 5,5 0,0.65 -0.13,1.26 -0.36,1.83l2.92,2.92c1.51,-1.26 2.7,-2.89 3.43,-4.75 -1.73,-4.39 -6,-7.5 -11,-7.5 -1.4,0 -2.74,0.25 -3.98,0.7l2.16,2.16C10.74,7.13 11.35,7 12,7zM2,4.27l2.28,2.28 0.46,0.46C3.08,8.3 1.78,10.02 1,12c1.73,4.39 6,7.5 11,7.5 1.55,0 3.03,-0.3 4.38,-0.84l0.42,0.42L19.73,22 21,20.73 3.27,3 2,4.27zM7.53,9.8l1.55,1.55c-0.05,0.21 -0.08,0.43 -0.08,0.65 0,1.66 1.34,3 3,3 0.22,0 0.44,-0.03 0.65,-0.08l1.55,1.55c-0.67,0.33 -1.41,0.53 -2.2,0.53 -2.76,0 -5,-2.24 -5,-5 0,-0.79 0.2,-1.53 0.53,-2.2zM11.84,9.02l3.15,3.15 0.02,-0.16c0,-1.66 -1.34,-3 -3,-3l-0.17,0.01z"/>
|
||||
</vector>
|
||||
@@ -9,4 +9,5 @@
|
||||
<string name="title_activity_dsbactivity">DSBActivity</string>
|
||||
<string name="title_activity_mebis">MebisActivity</string>
|
||||
<string name="title_activity_dsbday_view">DSBDayViewActivity</string>
|
||||
<string name="title_activity_dsblogin">DSBLoginActivity</string>
|
||||
</resources>
|
||||
Reference in New Issue
Block a user