fixed app crashes and some other improvements
This commit is contained in:
Generated
+340
@@ -0,0 +1,340 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="DeviceStreaming">
|
||||||
|
<option name="deviceSelectionList">
|
||||||
|
<list>
|
||||||
|
<PersistentDeviceSelectionData>
|
||||||
|
<option name="api" value="27" />
|
||||||
|
<option name="brand" value="DOCOMO" />
|
||||||
|
<option name="codename" value="F01L" />
|
||||||
|
<option name="id" value="F01L" />
|
||||||
|
<option name="manufacturer" value="FUJITSU" />
|
||||||
|
<option name="name" value="F-01L" />
|
||||||
|
<option name="screenDensity" value="360" />
|
||||||
|
<option name="screenX" value="720" />
|
||||||
|
<option name="screenY" value="1280" />
|
||||||
|
</PersistentDeviceSelectionData>
|
||||||
|
<PersistentDeviceSelectionData>
|
||||||
|
<option name="api" value="34" />
|
||||||
|
<option name="brand" value="OPPO" />
|
||||||
|
<option name="codename" value="OP573DL1" />
|
||||||
|
<option name="id" value="OP573DL1" />
|
||||||
|
<option name="manufacturer" value="OPPO" />
|
||||||
|
<option name="name" value="CPH2557" />
|
||||||
|
<option name="screenDensity" value="480" />
|
||||||
|
<option name="screenX" value="1080" />
|
||||||
|
<option name="screenY" value="2400" />
|
||||||
|
</PersistentDeviceSelectionData>
|
||||||
|
<PersistentDeviceSelectionData>
|
||||||
|
<option name="api" value="28" />
|
||||||
|
<option name="brand" value="DOCOMO" />
|
||||||
|
<option name="codename" value="SH-01L" />
|
||||||
|
<option name="id" value="SH-01L" />
|
||||||
|
<option name="manufacturer" value="SHARP" />
|
||||||
|
<option name="name" value="AQUOS sense2 SH-01L" />
|
||||||
|
<option name="screenDensity" value="480" />
|
||||||
|
<option name="screenX" value="1080" />
|
||||||
|
<option name="screenY" value="2160" />
|
||||||
|
</PersistentDeviceSelectionData>
|
||||||
|
<PersistentDeviceSelectionData>
|
||||||
|
<option name="api" value="34" />
|
||||||
|
<option name="brand" value="Lenovo" />
|
||||||
|
<option name="codename" value="TB370FU" />
|
||||||
|
<option name="id" value="TB370FU" />
|
||||||
|
<option name="manufacturer" value="Lenovo" />
|
||||||
|
<option name="name" value="Tab P12" />
|
||||||
|
<option name="screenDensity" value="340" />
|
||||||
|
<option name="screenX" value="1840" />
|
||||||
|
<option name="screenY" value="2944" />
|
||||||
|
</PersistentDeviceSelectionData>
|
||||||
|
<PersistentDeviceSelectionData>
|
||||||
|
<option name="api" value="31" />
|
||||||
|
<option name="brand" value="samsung" />
|
||||||
|
<option name="codename" value="a51" />
|
||||||
|
<option name="id" value="a51" />
|
||||||
|
<option name="manufacturer" value="Samsung" />
|
||||||
|
<option name="name" value="Galaxy A51" />
|
||||||
|
<option name="screenDensity" value="420" />
|
||||||
|
<option name="screenX" value="1080" />
|
||||||
|
<option name="screenY" value="2400" />
|
||||||
|
</PersistentDeviceSelectionData>
|
||||||
|
<PersistentDeviceSelectionData>
|
||||||
|
<option name="api" value="34" />
|
||||||
|
<option name="brand" value="google" />
|
||||||
|
<option name="codename" value="akita" />
|
||||||
|
<option name="id" value="akita" />
|
||||||
|
<option name="manufacturer" value="Google" />
|
||||||
|
<option name="name" value="Pixel 8a" />
|
||||||
|
<option name="screenDensity" value="420" />
|
||||||
|
<option name="screenX" value="1080" />
|
||||||
|
<option name="screenY" value="2400" />
|
||||||
|
</PersistentDeviceSelectionData>
|
||||||
|
<PersistentDeviceSelectionData>
|
||||||
|
<option name="api" value="33" />
|
||||||
|
<option name="brand" value="samsung" />
|
||||||
|
<option name="codename" value="b0q" />
|
||||||
|
<option name="id" value="b0q" />
|
||||||
|
<option name="manufacturer" value="Samsung" />
|
||||||
|
<option name="name" value="Galaxy S22 Ultra" />
|
||||||
|
<option name="screenDensity" value="600" />
|
||||||
|
<option name="screenX" value="1440" />
|
||||||
|
<option name="screenY" value="3088" />
|
||||||
|
</PersistentDeviceSelectionData>
|
||||||
|
<PersistentDeviceSelectionData>
|
||||||
|
<option name="api" value="32" />
|
||||||
|
<option name="brand" value="google" />
|
||||||
|
<option name="codename" value="bluejay" />
|
||||||
|
<option name="id" value="bluejay" />
|
||||||
|
<option name="manufacturer" value="Google" />
|
||||||
|
<option name="name" value="Pixel 6a" />
|
||||||
|
<option name="screenDensity" value="420" />
|
||||||
|
<option name="screenX" value="1080" />
|
||||||
|
<option name="screenY" value="2400" />
|
||||||
|
</PersistentDeviceSelectionData>
|
||||||
|
<PersistentDeviceSelectionData>
|
||||||
|
<option name="api" value="34" />
|
||||||
|
<option name="brand" value="google" />
|
||||||
|
<option name="codename" value="caiman" />
|
||||||
|
<option name="id" value="caiman" />
|
||||||
|
<option name="manufacturer" value="Google" />
|
||||||
|
<option name="name" value="Pixel 9 Pro" />
|
||||||
|
<option name="screenDensity" value="360" />
|
||||||
|
<option name="screenX" value="960" />
|
||||||
|
<option name="screenY" value="2142" />
|
||||||
|
</PersistentDeviceSelectionData>
|
||||||
|
<PersistentDeviceSelectionData>
|
||||||
|
<option name="api" value="34" />
|
||||||
|
<option name="brand" value="google" />
|
||||||
|
<option name="codename" value="comet" />
|
||||||
|
<option name="id" value="comet" />
|
||||||
|
<option name="manufacturer" value="Google" />
|
||||||
|
<option name="name" value="Pixel 9 Pro Fold" />
|
||||||
|
<option name="screenDensity" value="390" />
|
||||||
|
<option name="screenX" value="2076" />
|
||||||
|
<option name="screenY" value="2152" />
|
||||||
|
</PersistentDeviceSelectionData>
|
||||||
|
<PersistentDeviceSelectionData>
|
||||||
|
<option name="api" value="29" />
|
||||||
|
<option name="brand" value="samsung" />
|
||||||
|
<option name="codename" value="crownqlteue" />
|
||||||
|
<option name="id" value="crownqlteue" />
|
||||||
|
<option name="manufacturer" value="Samsung" />
|
||||||
|
<option name="name" value="Galaxy Note9" />
|
||||||
|
<option name="screenDensity" value="420" />
|
||||||
|
<option name="screenX" value="2220" />
|
||||||
|
<option name="screenY" value="1080" />
|
||||||
|
</PersistentDeviceSelectionData>
|
||||||
|
<PersistentDeviceSelectionData>
|
||||||
|
<option name="api" value="34" />
|
||||||
|
<option name="brand" value="samsung" />
|
||||||
|
<option name="codename" value="dm3q" />
|
||||||
|
<option name="id" value="dm3q" />
|
||||||
|
<option name="manufacturer" value="Samsung" />
|
||||||
|
<option name="name" value="Galaxy S23 Ultra" />
|
||||||
|
<option name="screenDensity" value="600" />
|
||||||
|
<option name="screenX" value="1440" />
|
||||||
|
<option name="screenY" value="3088" />
|
||||||
|
</PersistentDeviceSelectionData>
|
||||||
|
<PersistentDeviceSelectionData>
|
||||||
|
<option name="api" value="34" />
|
||||||
|
<option name="brand" value="samsung" />
|
||||||
|
<option name="codename" value="e1q" />
|
||||||
|
<option name="id" value="e1q" />
|
||||||
|
<option name="manufacturer" value="Samsung" />
|
||||||
|
<option name="name" value="Galaxy S24" />
|
||||||
|
<option name="screenDensity" value="480" />
|
||||||
|
<option name="screenX" value="1080" />
|
||||||
|
<option name="screenY" value="2340" />
|
||||||
|
</PersistentDeviceSelectionData>
|
||||||
|
<PersistentDeviceSelectionData>
|
||||||
|
<option name="api" value="33" />
|
||||||
|
<option name="brand" value="google" />
|
||||||
|
<option name="codename" value="felix" />
|
||||||
|
<option name="id" value="felix" />
|
||||||
|
<option name="manufacturer" value="Google" />
|
||||||
|
<option name="name" value="Pixel Fold" />
|
||||||
|
<option name="screenDensity" value="420" />
|
||||||
|
<option name="screenX" value="2208" />
|
||||||
|
<option name="screenY" value="1840" />
|
||||||
|
</PersistentDeviceSelectionData>
|
||||||
|
<PersistentDeviceSelectionData>
|
||||||
|
<option name="api" value="34" />
|
||||||
|
<option name="brand" value="google" />
|
||||||
|
<option name="codename" value="felix" />
|
||||||
|
<option name="id" value="felix" />
|
||||||
|
<option name="manufacturer" value="Google" />
|
||||||
|
<option name="name" value="Pixel Fold" />
|
||||||
|
<option name="screenDensity" value="420" />
|
||||||
|
<option name="screenX" value="2208" />
|
||||||
|
<option name="screenY" value="1840" />
|
||||||
|
</PersistentDeviceSelectionData>
|
||||||
|
<PersistentDeviceSelectionData>
|
||||||
|
<option name="api" value="33" />
|
||||||
|
<option name="brand" value="google" />
|
||||||
|
<option name="codename" value="felix_camera" />
|
||||||
|
<option name="id" value="felix_camera" />
|
||||||
|
<option name="manufacturer" value="Google" />
|
||||||
|
<option name="name" value="Pixel Fold (Camera-enabled)" />
|
||||||
|
<option name="screenDensity" value="420" />
|
||||||
|
<option name="screenX" value="2208" />
|
||||||
|
<option name="screenY" value="1840" />
|
||||||
|
</PersistentDeviceSelectionData>
|
||||||
|
<PersistentDeviceSelectionData>
|
||||||
|
<option name="api" value="33" />
|
||||||
|
<option name="brand" value="samsung" />
|
||||||
|
<option name="codename" value="gts8uwifi" />
|
||||||
|
<option name="id" value="gts8uwifi" />
|
||||||
|
<option name="manufacturer" value="Samsung" />
|
||||||
|
<option name="name" value="Galaxy Tab S8 Ultra" />
|
||||||
|
<option name="screenDensity" value="320" />
|
||||||
|
<option name="screenX" value="1848" />
|
||||||
|
<option name="screenY" value="2960" />
|
||||||
|
</PersistentDeviceSelectionData>
|
||||||
|
<PersistentDeviceSelectionData>
|
||||||
|
<option name="api" value="34" />
|
||||||
|
<option name="brand" value="google" />
|
||||||
|
<option name="codename" value="husky" />
|
||||||
|
<option name="id" value="husky" />
|
||||||
|
<option name="manufacturer" value="Google" />
|
||||||
|
<option name="name" value="Pixel 8 Pro" />
|
||||||
|
<option name="screenDensity" value="390" />
|
||||||
|
<option name="screenX" value="1008" />
|
||||||
|
<option name="screenY" value="2244" />
|
||||||
|
</PersistentDeviceSelectionData>
|
||||||
|
<PersistentDeviceSelectionData>
|
||||||
|
<option name="api" value="30" />
|
||||||
|
<option name="brand" value="motorola" />
|
||||||
|
<option name="codename" value="java" />
|
||||||
|
<option name="id" value="java" />
|
||||||
|
<option name="manufacturer" value="Motorola" />
|
||||||
|
<option name="name" value="G20" />
|
||||||
|
<option name="screenDensity" value="280" />
|
||||||
|
<option name="screenX" value="720" />
|
||||||
|
<option name="screenY" value="1600" />
|
||||||
|
</PersistentDeviceSelectionData>
|
||||||
|
<PersistentDeviceSelectionData>
|
||||||
|
<option name="api" value="34" />
|
||||||
|
<option name="brand" value="google" />
|
||||||
|
<option name="codename" value="komodo" />
|
||||||
|
<option name="id" value="komodo" />
|
||||||
|
<option name="manufacturer" value="Google" />
|
||||||
|
<option name="name" value="Pixel 9 Pro XL" />
|
||||||
|
<option name="screenDensity" value="360" />
|
||||||
|
<option name="screenX" value="1008" />
|
||||||
|
<option name="screenY" value="2244" />
|
||||||
|
</PersistentDeviceSelectionData>
|
||||||
|
<PersistentDeviceSelectionData>
|
||||||
|
<option name="api" value="33" />
|
||||||
|
<option name="brand" value="google" />
|
||||||
|
<option name="codename" value="lynx" />
|
||||||
|
<option name="id" value="lynx" />
|
||||||
|
<option name="manufacturer" value="Google" />
|
||||||
|
<option name="name" value="Pixel 7a" />
|
||||||
|
<option name="screenDensity" value="420" />
|
||||||
|
<option name="screenX" value="1080" />
|
||||||
|
<option name="screenY" value="2400" />
|
||||||
|
</PersistentDeviceSelectionData>
|
||||||
|
<PersistentDeviceSelectionData>
|
||||||
|
<option name="api" value="31" />
|
||||||
|
<option name="brand" value="google" />
|
||||||
|
<option name="codename" value="oriole" />
|
||||||
|
<option name="id" value="oriole" />
|
||||||
|
<option name="manufacturer" value="Google" />
|
||||||
|
<option name="name" value="Pixel 6" />
|
||||||
|
<option name="screenDensity" value="420" />
|
||||||
|
<option name="screenX" value="1080" />
|
||||||
|
<option name="screenY" value="2400" />
|
||||||
|
</PersistentDeviceSelectionData>
|
||||||
|
<PersistentDeviceSelectionData>
|
||||||
|
<option name="api" value="33" />
|
||||||
|
<option name="brand" value="google" />
|
||||||
|
<option name="codename" value="panther" />
|
||||||
|
<option name="id" value="panther" />
|
||||||
|
<option name="manufacturer" value="Google" />
|
||||||
|
<option name="name" value="Pixel 7" />
|
||||||
|
<option name="screenDensity" value="420" />
|
||||||
|
<option name="screenX" value="1080" />
|
||||||
|
<option name="screenY" value="2400" />
|
||||||
|
</PersistentDeviceSelectionData>
|
||||||
|
<PersistentDeviceSelectionData>
|
||||||
|
<option name="api" value="34" />
|
||||||
|
<option name="brand" value="samsung" />
|
||||||
|
<option name="codename" value="q5q" />
|
||||||
|
<option name="id" value="q5q" />
|
||||||
|
<option name="manufacturer" value="Samsung" />
|
||||||
|
<option name="name" value="Galaxy Z Fold5" />
|
||||||
|
<option name="screenDensity" value="420" />
|
||||||
|
<option name="screenX" value="1812" />
|
||||||
|
<option name="screenY" value="2176" />
|
||||||
|
</PersistentDeviceSelectionData>
|
||||||
|
<PersistentDeviceSelectionData>
|
||||||
|
<option name="api" value="34" />
|
||||||
|
<option name="brand" value="samsung" />
|
||||||
|
<option name="codename" value="q6q" />
|
||||||
|
<option name="id" value="q6q" />
|
||||||
|
<option name="manufacturer" value="Samsung" />
|
||||||
|
<option name="name" value="Galaxy Z Fold6" />
|
||||||
|
<option name="screenDensity" value="420" />
|
||||||
|
<option name="screenX" value="1856" />
|
||||||
|
<option name="screenY" value="2160" />
|
||||||
|
</PersistentDeviceSelectionData>
|
||||||
|
<PersistentDeviceSelectionData>
|
||||||
|
<option name="api" value="30" />
|
||||||
|
<option name="brand" value="google" />
|
||||||
|
<option name="codename" value="r11" />
|
||||||
|
<option name="id" value="r11" />
|
||||||
|
<option name="manufacturer" value="Google" />
|
||||||
|
<option name="name" value="Pixel Watch" />
|
||||||
|
<option name="screenDensity" value="320" />
|
||||||
|
<option name="screenX" value="384" />
|
||||||
|
<option name="screenY" value="384" />
|
||||||
|
<option name="type" value="WEAR_OS" />
|
||||||
|
</PersistentDeviceSelectionData>
|
||||||
|
<PersistentDeviceSelectionData>
|
||||||
|
<option name="api" value="30" />
|
||||||
|
<option name="brand" value="google" />
|
||||||
|
<option name="codename" value="redfin" />
|
||||||
|
<option name="id" value="redfin" />
|
||||||
|
<option name="manufacturer" value="Google" />
|
||||||
|
<option name="name" value="Pixel 5" />
|
||||||
|
<option name="screenDensity" value="440" />
|
||||||
|
<option name="screenX" value="1080" />
|
||||||
|
<option name="screenY" value="2340" />
|
||||||
|
</PersistentDeviceSelectionData>
|
||||||
|
<PersistentDeviceSelectionData>
|
||||||
|
<option name="api" value="34" />
|
||||||
|
<option name="brand" value="google" />
|
||||||
|
<option name="codename" value="shiba" />
|
||||||
|
<option name="id" value="shiba" />
|
||||||
|
<option name="manufacturer" value="Google" />
|
||||||
|
<option name="name" value="Pixel 8" />
|
||||||
|
<option name="screenDensity" value="420" />
|
||||||
|
<option name="screenX" value="1080" />
|
||||||
|
<option name="screenY" value="2400" />
|
||||||
|
</PersistentDeviceSelectionData>
|
||||||
|
<PersistentDeviceSelectionData>
|
||||||
|
<option name="api" value="33" />
|
||||||
|
<option name="brand" value="google" />
|
||||||
|
<option name="codename" value="tangorpro" />
|
||||||
|
<option name="id" value="tangorpro" />
|
||||||
|
<option name="manufacturer" value="Google" />
|
||||||
|
<option name="name" value="Pixel Tablet" />
|
||||||
|
<option name="screenDensity" value="320" />
|
||||||
|
<option name="screenX" value="1600" />
|
||||||
|
<option name="screenY" value="2560" />
|
||||||
|
</PersistentDeviceSelectionData>
|
||||||
|
<PersistentDeviceSelectionData>
|
||||||
|
<option name="api" value="34" />
|
||||||
|
<option name="brand" value="google" />
|
||||||
|
<option name="codename" value="tokay" />
|
||||||
|
<option name="id" value="tokay" />
|
||||||
|
<option name="manufacturer" value="Google" />
|
||||||
|
<option name="name" value="Pixel 9" />
|
||||||
|
<option name="screenDensity" value="420" />
|
||||||
|
<option name="screenX" value="1080" />
|
||||||
|
<option name="screenY" value="2424" />
|
||||||
|
</PersistentDeviceSelectionData>
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
@@ -32,7 +32,7 @@ android {
|
|||||||
applicationId = "com.odweta.solon"
|
applicationId = "com.odweta.solon"
|
||||||
minSdk = 28
|
minSdk = 28
|
||||||
targetSdk = 34
|
targetSdk = 34
|
||||||
versionCode = 208
|
versionCode = 210
|
||||||
versionName = "2.3.0"
|
versionName = "2.3.0"
|
||||||
|
|
||||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@@ -11,9 +11,9 @@
|
|||||||
"type": "SINGLE",
|
"type": "SINGLE",
|
||||||
"filters": [],
|
"filters": [],
|
||||||
"attributes": [],
|
"attributes": [],
|
||||||
"versionCode": 1,
|
"versionCode": 208,
|
||||||
"versionName": "2.0",
|
"versionName": "2.3.0",
|
||||||
"outputFile": "app-release.apk"
|
"outputFile": "com.odweta.solon_2.3.0.apk"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"elementType": "File",
|
"elementType": "File",
|
||||||
@@ -22,14 +22,14 @@
|
|||||||
"minApi": 28,
|
"minApi": 28,
|
||||||
"maxApi": 30,
|
"maxApi": 30,
|
||||||
"baselineProfiles": [
|
"baselineProfiles": [
|
||||||
"baselineProfiles/1/app-release.dm"
|
"baselineProfiles/1/com.odweta.solon_2.3.0.dm"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"minApi": 31,
|
"minApi": 31,
|
||||||
"maxApi": 2147483647,
|
"maxApi": 2147483647,
|
||||||
"baselineProfiles": [
|
"baselineProfiles": [
|
||||||
"baselineProfiles/0/app-release.dm"
|
"baselineProfiles/0/com.odweta.solon_2.3.0.dm"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.odweta.solon
|
package com.odweta.solon
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
@@ -8,17 +9,10 @@ import java.nio.charset.Charset
|
|||||||
|
|
||||||
class Account(val username: String, val password: String, private val error: Int) {
|
class Account(val username: String, val password: String, private val error: Int) {
|
||||||
companion object {
|
companion object {
|
||||||
private fun parseAccountDataFile(file: File): Account {
|
private fun parseAccountDataFile(): Account {
|
||||||
val lines: List<String> = file.readLines()
|
val lines: List<String> = File(global.fileDir, global.filePaths.accountData).readLines()
|
||||||
|
|
||||||
if (lines.size >= 2) {
|
|
||||||
if (lines[0] != "" && lines[1] != "") {
|
|
||||||
return Account(lines[0], lines[1], 0)
|
return Account(lines[0], lines[1], 0)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return Account("", "", 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun haveSaved(): Boolean {
|
fun haveSaved(): Boolean {
|
||||||
/* check if a file exists
|
/* check if a file exists
|
||||||
@@ -27,15 +21,17 @@ class Account(val username: String, val password: String, private val error: Int
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// check if file exists
|
// check if file exists
|
||||||
val file = File(global.fileDir, global.filePaths.accountData)
|
|
||||||
|
|
||||||
return if (!file.exists()) {
|
return if (
|
||||||
|
!Util.fileExists(global.filePaths.accountData) ||
|
||||||
|
Util.fileIsEmpty(global.filePaths.accountData)
|
||||||
|
) {
|
||||||
// it does not exist
|
// it does not exist
|
||||||
file.createNewFile()
|
File(global.fileDir, global.filePaths.accountData).createNewFile()
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
// it exists, so it shall be parsed
|
// it exists, so it shall be parsed
|
||||||
val acc: Account = parseAccountDataFile(file)
|
val acc: Account = parseAccountDataFile()
|
||||||
global.username = acc.username
|
global.username = acc.username
|
||||||
global.password = acc.password
|
global.password = acc.password
|
||||||
acc.error == 0
|
acc.error == 0
|
||||||
@@ -43,23 +39,20 @@ class Account(val username: String, val password: String, private val error: Int
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun save(acc: Account): Boolean {
|
fun save(acc: Account): Boolean {
|
||||||
return try {
|
val payload = "${acc.username}\n${acc.password}"
|
||||||
val file = File(global.fileDir, global.filePaths.accountData)
|
return Util.saveStringToFile(global.filePaths.accountData, payload)
|
||||||
file.writeText("${acc.username}\n${acc.password}\n", Charset.forName("UTF-8"))
|
|
||||||
|
|
||||||
true
|
|
||||||
} catch (e: Exception) {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun isValid(acc: Account): Boolean {
|
fun isValid(acc: Account): Boolean {
|
||||||
return withContext(Dispatchers.IO) {
|
|
||||||
global.username = acc.username
|
global.username = acc.username
|
||||||
global.password = acc.password
|
global.password = acc.password
|
||||||
|
|
||||||
val token = networkRequestFactory.perform(NetworkRequestType.Token).getString("token")
|
val tokenJSON = networkRequestFactory.perform(NetworkRequestType.Token)
|
||||||
!JSONObject(token).has("error")
|
return if (tokenJSON.has("token")) {
|
||||||
|
val token = tokenJSON.getString("token")
|
||||||
|
!token.contains("\"error\"")
|
||||||
|
} else {
|
||||||
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,7 +76,15 @@ fun String.toLectureNoteType(): LectureNoteType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class LectureNote(id: Int, note: MutableState<String>, type: MutableState<LectureNoteType>, number: Int, lectureName: String) {
|
data class LectureNote(
|
||||||
|
var id: Int,
|
||||||
|
var note: MutableState<String> = mutableStateOf(""),
|
||||||
|
var type: MutableState<LectureNoteType> = mutableStateOf(LectureNoteType.Normal),
|
||||||
|
var number: Int,
|
||||||
|
var lectureName: String
|
||||||
|
)
|
||||||
|
|
||||||
|
class LectureNoteOLD(id: Int, note: MutableState<String>, type: MutableState<LectureNoteType>, number: Int, lectureName: String) {
|
||||||
var id: Int = 0
|
var id: Int = 0
|
||||||
var note: MutableState<String> =
|
var note: MutableState<String> =
|
||||||
mutableStateOf("")
|
mutableStateOf("")
|
||||||
|
|||||||
@@ -81,6 +81,7 @@ fun launchContinue(
|
|||||||
global.settings = settingsData
|
global.settings = settingsData
|
||||||
|
|
||||||
// load the lecture notes
|
// load the lecture notes
|
||||||
|
Util.loadLectureNotes()
|
||||||
Util.csvToLectureNotes()
|
Util.csvToLectureNotes()
|
||||||
|
|
||||||
// listen for internet availability in case of disconnection
|
// listen for internet availability in case of disconnection
|
||||||
|
|||||||
@@ -14,12 +14,16 @@ import androidx.compose.foundation.layout.fillMaxSize
|
|||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.layout.width
|
import androidx.compose.foundation.layout.width
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.AutoAwesome
|
import androidx.compose.material.icons.filled.AutoAwesome
|
||||||
|
import androidx.compose.material.icons.filled.WorkspacePremium
|
||||||
|
import androidx.compose.material3.Button
|
||||||
|
import androidx.compose.material3.ButtonColors
|
||||||
import androidx.compose.material3.FloatingActionButton
|
import androidx.compose.material3.FloatingActionButton
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
@@ -57,6 +61,7 @@ import java.time.LocalDate
|
|||||||
import java.time.format.DateTimeFormatter
|
import java.time.format.DateTimeFormatter
|
||||||
|
|
||||||
var showNewMarksDialog by mutableStateOf(false)
|
var showNewMarksDialog by mutableStateOf(false)
|
||||||
|
var showFinalMarksDialog by mutableStateOf(false)
|
||||||
|
|
||||||
enum class MarksDepthLevel {
|
enum class MarksDepthLevel {
|
||||||
All,
|
All,
|
||||||
@@ -71,8 +76,14 @@ fun MarksScreen() {
|
|||||||
MarksDepthLevel.Subject -> MarksSubject()
|
MarksDepthLevel.Subject -> MarksSubject()
|
||||||
MarksDepthLevel.Detail -> MarksDetail()
|
MarksDepthLevel.Detail -> MarksDetail()
|
||||||
}
|
}
|
||||||
|
NewMarksDialog()
|
||||||
|
FinalMarksDialog()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun NewMarksDialog() {
|
||||||
if (showNewMarksDialog) {
|
if (showNewMarksDialog) {
|
||||||
val scrollStateNewMarks = rememberScrollState()
|
val ss = rememberScrollState()
|
||||||
|
|
||||||
Dialog(
|
Dialog(
|
||||||
onDismissRequest = { showNewMarksDialog = false },
|
onDismissRequest = { showNewMarksDialog = false },
|
||||||
@@ -82,7 +93,9 @@ fun MarksScreen() {
|
|||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
Column(
|
Column(
|
||||||
Modifier.verticalScroll(scrollStateNewMarks).padding(vertical = 10.dp),
|
Modifier
|
||||||
|
.verticalScroll(ss)
|
||||||
|
.padding(vertical = 10.dp),
|
||||||
horizontalAlignment = Alignment.CenterHorizontally
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
@@ -91,14 +104,17 @@ fun MarksScreen() {
|
|||||||
fontWeight = FontWeight.Bold,
|
fontWeight = FontWeight.Bold,
|
||||||
fontSize = 30.sp,
|
fontSize = 30.sp,
|
||||||
textAlign = TextAlign.Center,
|
textAlign = TextAlign.Center,
|
||||||
modifier = Modifier.background(
|
modifier = Modifier
|
||||||
|
.background(
|
||||||
color = Color.Black,
|
color = Color.Black,
|
||||||
shape = RoundedCornerShape(global.dimens.roundedCorner)
|
shape = RoundedCornerShape(global.dimens.roundedCorner)
|
||||||
).border(
|
)
|
||||||
|
.border(
|
||||||
shape = RoundedCornerShape(global.dimens.roundedCorner),
|
shape = RoundedCornerShape(global.dimens.roundedCorner),
|
||||||
color = PastelYellow,
|
color = PastelYellow,
|
||||||
width = global.dimens.borderWidth
|
width = global.dimens.borderWidth
|
||||||
).padding(10.dp)
|
)
|
||||||
|
.padding(10.dp)
|
||||||
)
|
)
|
||||||
Spacer(Modifier.height(10.dp))
|
Spacer(Modifier.height(10.dp))
|
||||||
for ((k, v) in global.newMarks) {
|
for ((k, v) in global.newMarks) {
|
||||||
@@ -133,7 +149,8 @@ fun MarksScreen() {
|
|||||||
Text(
|
Text(
|
||||||
i.theme,
|
i.theme,
|
||||||
color = Color.White,
|
color = Color.White,
|
||||||
modifier = Modifier.padding(end = 5.dp, top = 5.dp)
|
modifier = Modifier
|
||||||
|
.padding(end = 5.dp, top = 5.dp)
|
||||||
.weight(1f)
|
.weight(1f)
|
||||||
)
|
)
|
||||||
Column(
|
Column(
|
||||||
@@ -146,7 +163,8 @@ fun MarksScreen() {
|
|||||||
.background(
|
.background(
|
||||||
color = getAvgColor(i.grade, true),
|
color = getAvgColor(i.grade, true),
|
||||||
shape = RoundedCornerShape(global.dimens.roundedCorner)
|
shape = RoundedCornerShape(global.dimens.roundedCorner)
|
||||||
).padding(5.dp),
|
)
|
||||||
|
.padding(5.dp),
|
||||||
style = TextStyle(
|
style = TextStyle(
|
||||||
shadow = Shadow(
|
shadow = Shadow(
|
||||||
color = Color.Black,
|
color = Color.Black,
|
||||||
@@ -173,6 +191,47 @@ fun MarksScreen() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun FinalMarksDialog() {
|
||||||
|
if (showFinalMarksDialog) {
|
||||||
|
val ss = rememberScrollState()
|
||||||
|
|
||||||
|
Dialog(
|
||||||
|
onDismissRequest = { showFinalMarksDialog = false },
|
||||||
|
properties = DialogProperties(
|
||||||
|
dismissOnBackPress = true,
|
||||||
|
dismissOnClickOutside = true
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
Modifier
|
||||||
|
.verticalScroll(ss)
|
||||||
|
.padding(vertical = 10.dp),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
"Uzavřené známky",
|
||||||
|
color = Color.White,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
fontSize = 30.sp,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
modifier = Modifier
|
||||||
|
.background(
|
||||||
|
color = Color.Black,
|
||||||
|
shape = RoundedCornerShape(global.dimens.roundedCorner)
|
||||||
|
)
|
||||||
|
.border(
|
||||||
|
shape = RoundedCornerShape(global.dimens.roundedCorner),
|
||||||
|
color = PastelYellow,
|
||||||
|
width = global.dimens.borderWidth
|
||||||
|
)
|
||||||
|
.padding(10.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun getAvgColor(avg: String, isBorder: Boolean = false): Color {
|
private fun getAvgColor(avg: String, isBorder: Boolean = false): Color {
|
||||||
val aux = avg.replace(",", ".").toFloat()
|
val aux = avg.replace(",", ".").toFloat()
|
||||||
return if (aux in 1f..<1.5f) {
|
return if (aux in 1f..<1.5f) {
|
||||||
@@ -360,22 +419,47 @@ fun MarksAll() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Box(Modifier.fillMaxSize()) {
|
Box(Modifier.fillMaxSize()) {
|
||||||
|
Row(
|
||||||
|
modifier = Modifier.align(Alignment.BottomCenter)
|
||||||
|
) {
|
||||||
FloatingActionButton(
|
FloatingActionButton(
|
||||||
onClick = { showNewMarksDialog = true },
|
onClick = { showNewMarksDialog = true },
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.align(Alignment.BottomEnd)
|
// .size(40.dp)
|
||||||
.padding(10.dp)
|
.padding(10.dp)
|
||||||
.background(Color.Black, shape = RoundedCornerShape(global.dimens.roundedCorner)),
|
.background(
|
||||||
containerColor = Color.Black,
|
Color.Black,
|
||||||
contentColor = PastelYellow
|
shape = RoundedCornerShape(global.dimens.roundedCorner)
|
||||||
|
),
|
||||||
|
contentColor = PastelYellow,
|
||||||
|
containerColor = Color.Black
|
||||||
) {
|
) {
|
||||||
Icon(
|
Icon(
|
||||||
modifier = Modifier.padding(start = 4.dp, top = 4.dp),
|
|
||||||
imageVector = Icons.Default.AutoAwesome,
|
imageVector = Icons.Default.AutoAwesome,
|
||||||
contentDescription = "New marks in subject",
|
contentDescription = "New marks in subject",
|
||||||
tint = PastelYellow // You can customize the icon color
|
tint = PastelYellow // You can customize the icon color
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FloatingActionButton(
|
||||||
|
onClick = { showFinalMarksDialog = true },
|
||||||
|
modifier = Modifier
|
||||||
|
// .size(40.dp)
|
||||||
|
.padding(10.dp)
|
||||||
|
.background(
|
||||||
|
Color.Black,
|
||||||
|
shape = RoundedCornerShape(global.dimens.roundedCorner)
|
||||||
|
),
|
||||||
|
contentColor = PastelYellow,
|
||||||
|
containerColor = Color.Black
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Default.WorkspacePremium,
|
||||||
|
contentDescription = "Final marks",
|
||||||
|
tint = PastelYellow // You can customize the icon color
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -40,7 +40,10 @@ fun MenuScreen() {
|
|||||||
|
|
||||||
Spacer(modifier = Modifier.height(80.dp))
|
Spacer(modifier = Modifier.height(80.dp))
|
||||||
|
|
||||||
MenuButton({ global.currentScreen = Screen.SignIn }, "Změnit přihlášení")
|
MenuButton({
|
||||||
|
global.noSignInBackHandle = false
|
||||||
|
global.currentScreen = Screen.SignIn
|
||||||
|
}, "Změnit přihlášení")
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(80.dp))
|
Spacer(modifier = Modifier.height(80.dp))
|
||||||
|
|
||||||
|
|||||||
@@ -11,15 +11,21 @@ import org.json.JSONObject
|
|||||||
|
|
||||||
fun setupAPI() {
|
fun setupAPI() {
|
||||||
global.token = "NETWORK_UNREACHABLE"
|
global.token = "NETWORK_UNREACHABLE"
|
||||||
val token = networkRequestFactory.perform(NetworkRequestType.Token).getString("token")
|
|
||||||
if (""""error": """ !in token) {
|
val tokenJSON = networkRequestFactory.perform(NetworkRequestType.Token)
|
||||||
|
if (tokenJSON.has("token")) {
|
||||||
|
val token = tokenJSON.getString("token")
|
||||||
|
if ("\"error\": " !in token) {
|
||||||
global.token = token
|
global.token = token
|
||||||
}
|
}
|
||||||
if (global.token == "NETWORK_UNREACHABLE" || """"error": """ in global.token) {
|
}
|
||||||
|
|
||||||
|
if (global.token == "NETWORK_UNREACHABLE" || "\"error\":" in global.token) {
|
||||||
global.userData = JSONObject()
|
global.userData = JSONObject()
|
||||||
global.studentId = ""
|
global.studentId = ""
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
global.userData = networkRequestFactory.perform(NetworkRequestType.UserData)
|
global.userData = networkRequestFactory.perform(NetworkRequestType.UserData)
|
||||||
Util.saveStringToFile(global.filePaths.userData, global.userData.toString())
|
Util.saveStringToFile(global.filePaths.userData, global.userData.toString())
|
||||||
global.studentClass = Parsing.getStudentClass()
|
global.studentClass = Parsing.getStudentClass()
|
||||||
@@ -90,7 +96,6 @@ object NetworkRequestFactory: NetworkRequestInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun getAPI(url: String): JSONObject {
|
private fun getAPI(url: String): JSONObject {
|
||||||
Log.d("debug TOKEN", global.token)
|
|
||||||
val response = get(url, headersOf(
|
val response = get(url, headersOf(
|
||||||
"Content-Type", "application/x-www-form-urlencoded",
|
"Content-Type", "application/x-www-form-urlencoded",
|
||||||
"Authorization", "Bearer ${global.token}"
|
"Authorization", "Bearer ${global.token}"
|
||||||
|
|||||||
@@ -153,9 +153,12 @@ class Parsing {
|
|||||||
subject.name = subj.getJSONObject("subject").getString("abbrev")
|
subject.name = subj.getJSONObject("subject").getString("abbrev")
|
||||||
subject.place =
|
subject.place =
|
||||||
subj.getJSONArray("rooms").getJSONObject(0).getString("abbrev")
|
subj.getJSONArray("rooms").getJSONObject(0).getString("abbrev")
|
||||||
subject.teacher = if (subj.getJSONArray("teachers").length() > 0) {
|
subject.teacher =
|
||||||
subj.getJSONArray("teachers").getJSONObject(0)
|
if (subj.getJSONArray("teachers").length() > 0) {
|
||||||
.getString("fullName") // TODO: keep in mind that fullName might not be a valid field (name and surname are!)
|
subj.getJSONArray("teachers")
|
||||||
|
.getJSONObject(0).getString("name") + " " +
|
||||||
|
subj.getJSONArray("teachers")
|
||||||
|
.getJSONObject(0).getString("name")
|
||||||
} else {
|
} else {
|
||||||
""
|
""
|
||||||
}
|
}
|
||||||
@@ -322,7 +325,6 @@ class Parsing {
|
|||||||
timetable.add(day)
|
timetable.add(day)
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.d("debug", "timetable: $timetable")
|
|
||||||
return timetable
|
return timetable
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.odweta.solon
|
package com.odweta.solon
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.util.Log
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.activity.compose.BackHandler
|
import androidx.activity.compose.BackHandler
|
||||||
import androidx.compose.foundation.Image
|
import androidx.compose.foundation.Image
|
||||||
@@ -40,6 +41,7 @@ import androidx.compose.foundation.layout.*
|
|||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
private var buttonText by mutableStateOf("Přihlásit se")
|
private var buttonText by mutableStateOf("Přihlásit se")
|
||||||
|
|
||||||
@@ -96,6 +98,7 @@ fun signInButtonCallback(ctx: Context, usernameText: String, passwordText: Strin
|
|||||||
global.currentScreen = Screen.Splash
|
global.currentScreen = Screen.Splash
|
||||||
launchStart(ctx)
|
launchStart(ctx)
|
||||||
} else {
|
} else {
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
Toast.makeText(
|
Toast.makeText(
|
||||||
ctx,
|
ctx,
|
||||||
"Neplatné přihlašovací údaje nebo nejste připojeni k internetu, zkuste to znovu.",
|
"Neplatné přihlašovací údaje nebo nejste připojeni k internetu, zkuste to znovu.",
|
||||||
@@ -103,6 +106,7 @@ fun signInButtonCallback(ctx: Context, usernameText: String, passwordText: Strin
|
|||||||
).show()
|
).show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@@ -115,7 +119,6 @@ fun SignInScreen() {
|
|||||||
var usernameText by remember { mutableStateOf("") }
|
var usernameText by remember { mutableStateOf("") }
|
||||||
var passwordText by remember { mutableStateOf("") }
|
var passwordText by remember { mutableStateOf("") }
|
||||||
val ctx = LocalContext.current
|
val ctx = LocalContext.current
|
||||||
val coscope = rememberCoroutineScope()
|
|
||||||
var isPasswordVisible by remember { mutableStateOf(false) } // State for visibility toggle
|
var isPasswordVisible by remember { mutableStateOf(false) } // State for visibility toggle
|
||||||
val visualTransformation = if (isPasswordVisible) VisualTransformation.None else PasswordVisualTransformation()
|
val visualTransformation = if (isPasswordVisible) VisualTransformation.None else PasswordVisualTransformation()
|
||||||
|
|
||||||
|
|||||||
@@ -356,6 +356,8 @@ private fun DayScreen(day: Day) {
|
|||||||
) {
|
) {
|
||||||
for ((subjectIndex, subject) in day.subjects.withIndex()) {
|
for ((subjectIndex, subject) in day.subjects.withIndex()) {
|
||||||
val lectureId = Util.getLectureId(day.date, subjectIndex)
|
val lectureId = Util.getLectureId(day.date, subjectIndex)
|
||||||
|
global.lectureNotes[lectureId]?.number = subject.number.toInt()
|
||||||
|
global.lectureNotes[lectureId]?.lectureName = subject.name
|
||||||
|
|
||||||
val amoledModifier = if (settings.useAmoledMode.checked.value) {
|
val amoledModifier = if (settings.useAmoledMode.checked.value) {
|
||||||
Modifier
|
Modifier
|
||||||
|
|||||||
Reference in New Issue
Block a user