refresh button working (not 100% test coverage)
This commit is contained in:
Generated
-340
@@ -1,340 +0,0 @@
|
|||||||
<?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>
|
|
||||||
@@ -181,24 +181,6 @@ class LectureNote(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var lectureNotes: HashMap<Int, LectureNote> = hashMapOf()
|
|
||||||
var selectedLecture: Int = 0
|
|
||||||
|
|
||||||
var selectedDay: Int = 0
|
|
||||||
var dayEndString: String = ""
|
|
||||||
|
|
||||||
var isChecked: Boolean = true
|
|
||||||
|
|
||||||
const val apiBaseUrl = "https://aplikace.skolaonline.cz/solapi/api"
|
|
||||||
const val tokenUrl = "$apiBaseUrl/connect/token"
|
|
||||||
var token: String = ""
|
|
||||||
const val userDataUrl = "$apiBaseUrl/v1/user"
|
|
||||||
var userData: String = ""
|
|
||||||
//var studentId: String = ""
|
|
||||||
const val timeTableUrl = "$apiBaseUrl/v1/timeTable"
|
|
||||||
var syid = "" // school year id
|
|
||||||
var marksUrl = "$apiBaseUrl/v1/students/abc/marks/list?SemesterId=$syid"
|
|
||||||
|
|
||||||
class Subject {
|
class Subject {
|
||||||
lateinit var name: String
|
lateinit var name: String
|
||||||
lateinit var place: String
|
lateinit var place: String
|
||||||
@@ -284,48 +266,62 @@ enum class ScreenElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class Global {
|
class Global {
|
||||||
lateinit var token: String
|
|
||||||
lateinit var userData: JSONObject
|
|
||||||
lateinit var timetable: List<Day>
|
|
||||||
lateinit var timetableJSON: JSONObject
|
lateinit var timetableJSON: JSONObject
|
||||||
lateinit var marks: MutableMap<String, MutableList<Mark>>
|
|
||||||
lateinit var marksJSON: JSONObject
|
lateinit var marksJSON: JSONObject
|
||||||
lateinit var studentClass: String
|
lateinit var marks: MutableMap<String, MutableList<Mark>>
|
||||||
lateinit var settings: SettingsData
|
lateinit var settings: SettingsData
|
||||||
lateinit var studentId: String
|
|
||||||
lateinit var fileDir: File
|
lateinit var fileDir: File
|
||||||
|
|
||||||
|
lateinit var token: String
|
||||||
|
lateinit var studentClass: String
|
||||||
|
lateinit var studentId: String
|
||||||
|
|
||||||
|
var userData: JSONObject = JSONObject()
|
||||||
|
var timetable: List<Day> = listOf()
|
||||||
|
var lectureNotes: HashMap<Int, LectureNote> = hashMapOf()
|
||||||
|
|
||||||
var username: String = ""
|
var username: String = ""
|
||||||
var password: String = ""
|
var password: String = ""
|
||||||
var isAPISetUp: Boolean = false
|
|
||||||
var noSignInBackHandle: Boolean = false
|
var noSignInBackHandle: Boolean = false
|
||||||
var lectureNotes: HashMap<Int, LectureNote> = hashMapOf()
|
|
||||||
var status by mutableStateOf("")
|
var selectedLecture: Int = 0
|
||||||
|
var currentLectureNumber: Int = 0
|
||||||
|
|
||||||
var currentScreen by mutableStateOf(Screen.Main)
|
var currentScreen by mutableStateOf(Screen.Main)
|
||||||
var currentScreenElement by mutableStateOf(ScreenElement.Timetable)
|
var currentScreenElement by mutableStateOf(ScreenElement.Timetable)
|
||||||
|
|
||||||
|
var status by mutableStateOf("")
|
||||||
|
|
||||||
|
var isAPISetUp by mutableStateOf(false)
|
||||||
|
var launched by mutableStateOf(false)
|
||||||
|
var refreshed by mutableStateOf(false)
|
||||||
|
|
||||||
inner class FilePaths {
|
inner class FilePaths {
|
||||||
val accountData: String = "account_data.txt"
|
val accountData: String = "account_data.txt"
|
||||||
val timeTable: String = "timetable.json"
|
val timetable: String = "timetable.json"
|
||||||
val userData: String = "userdata.json"
|
val userData: String = "userdata.json"
|
||||||
val marks: String = "marks.json"
|
val marks: String = "marks.json"
|
||||||
val settings: String = "settings.txt"
|
val settings: String = "settings.txt"
|
||||||
val lectureNotes: String = "lecture_notes.csv"
|
val lectureNotes: String = "lecture_notes.csv"
|
||||||
}
|
}
|
||||||
val filePaths = FilePaths()
|
val filePaths = FilePaths()
|
||||||
|
|
||||||
inner class APIEndPoints {
|
inner class APIEndPoints {
|
||||||
val apiBaseUrl = "https://aplikace.skolaonline.cz/solapi/api"
|
val apiBase = "https://aplikace.skolaonline.cz/solapi/api"
|
||||||
val tokenUrl = "$apiBaseUrl/connect/token"
|
val token = "$apiBase/connect/token"
|
||||||
lateinit var token: String
|
val userData = "$apiBase/v1/user"
|
||||||
val userDataUrl = "$apiBaseUrl/v1/user"
|
val timetable = "$apiBase/v1/timeTable"
|
||||||
lateinit var userData: String
|
var marks: String = "$apiBase/v1/students/<student id>/marks/list"
|
||||||
val timeTableUrl = "$apiBaseUrl/v1/timeTable"
|
|
||||||
lateinit var marksUrl: String
|
|
||||||
}
|
}
|
||||||
val apiEndPoints = APIEndPoints()
|
val apiEndPoints = APIEndPoints()
|
||||||
|
|
||||||
inner class Dimens {
|
inner class Dimens {
|
||||||
val borderWidth = 5.dp
|
val borderWidth = 5.dp
|
||||||
val roundedCorner = 8.dp
|
val roundedCorner = 8.dp
|
||||||
}
|
}
|
||||||
val dimens = Dimens()
|
val dimens = Dimens()
|
||||||
|
|
||||||
inner class Modifiers {
|
inner class Modifiers {
|
||||||
var bar = Modifier
|
var bar = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package com.odweta.solon
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
@@ -9,8 +10,10 @@ import kotlinx.coroutines.launch
|
|||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
|
|
||||||
fun launchStart(ctx: Context) {
|
fun launchStart(ctx: Context) {
|
||||||
|
global.launched = false
|
||||||
if (Account.haveSaved()) {
|
if (Account.haveSaved()) {
|
||||||
if (Util.internetAvail(ctx)) {
|
if (Util.internetAvail(ctx)) {
|
||||||
|
global.currentScreen = Screen.Splash
|
||||||
remoteLoad(ctx)
|
remoteLoad(ctx)
|
||||||
} else {
|
} else {
|
||||||
localLoad(ctx)
|
localLoad(ctx)
|
||||||
@@ -22,34 +25,38 @@ fun launchStart(ctx: Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun remoteLoad(ctx: Context) {
|
fun remoteLoad(ctx: Context) {
|
||||||
var remoteTimetable: JSONObject
|
Log.d("debug", "remoteLoad called")
|
||||||
var remoteMarks: JSONObject
|
|
||||||
if (!global.isAPISetUp) {
|
if (!global.isAPISetUp) {
|
||||||
CoroutineScope(Dispatchers.IO)
|
CoroutineScope(Dispatchers.IO)
|
||||||
.launch {
|
.launch {
|
||||||
Network.setupAPI()
|
Network.setupAPI()
|
||||||
remoteTimetable = Network.getTimeTable()
|
global.timetableJSON = Network.getTimeTable()
|
||||||
global.timetableJSON = remoteTimetable
|
global.marksJSON = Network.getMarks()
|
||||||
remoteMarks = Network.getMarks()
|
|
||||||
global.marksJSON = remoteMarks
|
|
||||||
|
|
||||||
launchContinue(
|
launchContinue(
|
||||||
ctx,
|
ctx,
|
||||||
remoteTimetable,
|
global.timetableJSON,
|
||||||
remoteMarks
|
global.marksJSON
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
launchContinue(
|
Log.d("debug", "API set up, continuing")
|
||||||
ctx,
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
global.timetableJSON,
|
launchContinue(
|
||||||
global.marksJSON
|
ctx,
|
||||||
)
|
Network.getTimeTable(),
|
||||||
|
Network.getMarks()
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun localLoad(ctx: Context) {
|
fun localLoad(ctx: Context) {
|
||||||
val localTimetable = JSONObject(Util.fileToString(timeTableFilePath))
|
global.userData = JSONObject(Util.fileToString(global.filePaths.userData))
|
||||||
|
global.studentId = Network.getStudentId()
|
||||||
|
global.studentClass = Network.getStudentClass()
|
||||||
|
global.apiEndPoints.marks = "${global.apiEndPoints.apiBase}/v1/students/${global.studentId}/marks/list"
|
||||||
|
val localTimetable = JSONObject(Util.fileToString(global.filePaths.timetable))
|
||||||
val localMarks = JSONObject(Util.fileToString(marksFilePath))
|
val localMarks = JSONObject(Util.fileToString(marksFilePath))
|
||||||
|
|
||||||
launchContinue(
|
launchContinue(
|
||||||
@@ -78,10 +85,16 @@ fun launchContinue(
|
|||||||
val lectureNotes = Util.fileToString(global.filePaths.lectureNotes)
|
val lectureNotes = Util.fileToString(global.filePaths.lectureNotes)
|
||||||
Parsing.parseLectureNotes(lectureNotes)
|
Parsing.parseLectureNotes(lectureNotes)
|
||||||
|
|
||||||
|
Log.d("debug", "parsed the things")
|
||||||
|
|
||||||
// listen for internet availability in case of disconnection
|
// listen for internet availability in case of disconnection
|
||||||
if (!internetAwaitListenerRunning)
|
if (!internetAwaitListenerRunning)
|
||||||
setOnInternetAvailListener(ctx)
|
setOnInternetAvailListener(ctx)
|
||||||
|
|
||||||
|
global.launched = true
|
||||||
|
global.refreshed = true
|
||||||
|
refreshButtonContentColor.value = Color.White
|
||||||
|
|
||||||
// show the default (main) screen
|
// show the default (main) screen
|
||||||
global.currentScreen = Screen.Main
|
global.currentScreen = Screen.Main
|
||||||
|
|
||||||
@@ -90,6 +103,8 @@ fun launchContinue(
|
|||||||
|
|
||||||
// show the full name of the user in the toolbar as a status
|
// show the full name of the user in the toolbar as a status
|
||||||
statusFactory.show(StatusType.NameRole)
|
statusFactory.show(StatusType.NameRole)
|
||||||
|
|
||||||
|
Log.d("debug", "done and should show nameRole status")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setOnInternetAvailListener(ctx: Context) {
|
private fun setOnInternetAvailListener(ctx: Context) {
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ class MainActivity : ComponentActivity() {
|
|||||||
setContent {
|
setContent {
|
||||||
SolonTheme {
|
SolonTheme {
|
||||||
when (global.currentScreen) {
|
when (global.currentScreen) {
|
||||||
Screen.Main -> MainScreen()
|
Screen.Main -> if (global.launched) MainScreen()
|
||||||
Screen.Splash -> SplashScreen()
|
Screen.Splash -> SplashScreen()
|
||||||
Screen.SignIn -> SignInScreen()
|
Screen.SignIn -> SignInScreen()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ import androidx.compose.ui.res.painterResource
|
|||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import com.odweta.solon.ui.theme.PastelYellow
|
import com.odweta.solon.ui.theme.PastelYellow
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
private var timetableColor: MutableState<Color> = mutableStateOf(PastelYellow)
|
private var timetableColor: MutableState<Color> = mutableStateOf(PastelYellow)
|
||||||
private var marksColor: MutableState<Color> = mutableStateOf(Color.White)
|
private var marksColor: MutableState<Color> = mutableStateOf(Color.White)
|
||||||
@@ -47,6 +49,7 @@ fun NavbarScreen() {
|
|||||||
Button(
|
Button(
|
||||||
onClick = {
|
onClick = {
|
||||||
remoteLoad(ctx)
|
remoteLoad(ctx)
|
||||||
|
statusFactory.show(StatusType.Loading)
|
||||||
refreshButtonContentColor.value = PastelYellow
|
refreshButtonContentColor.value = PastelYellow
|
||||||
},
|
},
|
||||||
colors = ButtonDefaults.buttonColors(
|
colors = ButtonDefaults.buttonColors(
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
package com.odweta.solon
|
package com.odweta.solon
|
||||||
|
|
||||||
import android.util.Log
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
import okhttp3.FormBody
|
import okhttp3.FormBody
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
import org.json.JSONException
|
import org.json.JSONException
|
||||||
@@ -13,7 +10,7 @@ class Network {
|
|||||||
companion object {
|
companion object {
|
||||||
fun getToken(): String {
|
fun getToken(): String {
|
||||||
val request = Request.Builder()
|
val request = Request.Builder()
|
||||||
.url(global.apiEndPoints.tokenUrl)
|
.url(global.apiEndPoints.token)
|
||||||
.header("Content-Type", "application/x-www-form-urlencoded")
|
.header("Content-Type", "application/x-www-form-urlencoded")
|
||||||
.post(
|
.post(
|
||||||
FormBody.Builder()
|
FormBody.Builder()
|
||||||
@@ -57,7 +54,16 @@ class Network {
|
|||||||
}
|
}
|
||||||
global.userData = getUserData()
|
global.userData = getUserData()
|
||||||
Util.saveStringToFile(global.filePaths.userData, global.userData.toString())
|
Util.saveStringToFile(global.filePaths.userData, global.userData.toString())
|
||||||
global.studentClass = if (!Parsing.userIsParent()) {
|
global.studentClass = getStudentClass()
|
||||||
|
global.studentId = getStudentId()
|
||||||
|
|
||||||
|
global.apiEndPoints.marks = "${global.apiEndPoints.apiBase}/v1/students/${global.studentId}/marks/list"
|
||||||
|
|
||||||
|
global.isAPISetUp = true
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getStudentClass(): String { // TODO: move to Parsing
|
||||||
|
return if (!Parsing.userIsParent()) {
|
||||||
JSONObject(
|
JSONObject(
|
||||||
Util.fileToString(global.filePaths.userData)
|
Util.fileToString(global.filePaths.userData)
|
||||||
).getJSONObject("class").getString("name")
|
).getJSONObject("class").getString("name")
|
||||||
@@ -67,14 +73,9 @@ class Network {
|
|||||||
Util.fileToString(global.filePaths.userData)
|
Util.fileToString(global.filePaths.userData)
|
||||||
).getJSONArray("children").getJSONObject(0).getString("className")
|
).getJSONArray("children").getJSONObject(0).getString("className")
|
||||||
}
|
}
|
||||||
global.studentId = getStudentId()
|
|
||||||
|
|
||||||
global.apiEndPoints.marksUrl = "$apiBaseUrl/v1/students/${global.studentId}/marks/list"
|
|
||||||
|
|
||||||
global.isAPISetUp = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getStudentId(): String {
|
fun getStudentId(): String { // TODO: move to Parsing
|
||||||
return if (!Parsing.userIsParent()) {
|
return if (!Parsing.userIsParent()) {
|
||||||
global.userData.getString("personID")
|
global.userData.getString("personID")
|
||||||
} else {
|
} else {
|
||||||
@@ -86,7 +87,7 @@ class Network {
|
|||||||
|
|
||||||
fun getUserData(): JSONObject {
|
fun getUserData(): JSONObject {
|
||||||
val request = Request.Builder()
|
val request = Request.Builder()
|
||||||
.url(global.apiEndPoints.userDataUrl)
|
.url(global.apiEndPoints.userData)
|
||||||
.header("Content-Type", "application/x-www-form-urlencoded")
|
.header("Content-Type", "application/x-www-form-urlencoded")
|
||||||
.header("Authorization", "Bearer ${global.token}") // using Bearer auth token
|
.header("Authorization", "Bearer ${global.token}") // using Bearer auth token
|
||||||
.get()
|
.get()
|
||||||
@@ -105,8 +106,8 @@ class Network {
|
|||||||
|
|
||||||
fun getTimeTable(): JSONObject {
|
fun getTimeTable(): JSONObject {
|
||||||
val userIsParent = Parsing.userIsParent()
|
val userIsParent = Parsing.userIsParent()
|
||||||
val url = if (!userIsParent) global.apiEndPoints.timeTableUrl
|
val url = if (!userIsParent) global.apiEndPoints.timetable
|
||||||
else "${global.apiEndPoints.timeTableUrl}?studentId=${global.studentId}"
|
else "${global.apiEndPoints.timetable}?studentId=${global.studentId}"
|
||||||
|
|
||||||
val request = Request.Builder()
|
val request = Request.Builder()
|
||||||
.url(url)
|
.url(url)
|
||||||
@@ -127,7 +128,7 @@ class Network {
|
|||||||
|
|
||||||
fun getMarks(): JSONObject {
|
fun getMarks(): JSONObject {
|
||||||
val request = Request.Builder()
|
val request = Request.Builder()
|
||||||
.url(global.apiEndPoints.marksUrl)
|
.url(global.apiEndPoints.marks)
|
||||||
.header("Content-Type", "application/x-www-form-urlencoded")
|
.header("Content-Type", "application/x-www-form-urlencoded")
|
||||||
.header("Authorization", "Bearer ${global.token}")
|
.header("Authorization", "Bearer ${global.token}")
|
||||||
.get()
|
.get()
|
||||||
|
|||||||
@@ -47,29 +47,26 @@ class Parsing {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun userIsParent(): Boolean {
|
fun userIsParent(): Boolean {
|
||||||
return if (userData != "")
|
return if (global.userData != JSONObject())
|
||||||
JSONObject(userData).getString("userType") == "parent"
|
global.userData.getString("userType") == "parent"
|
||||||
else false
|
else false
|
||||||
}
|
}
|
||||||
|
|
||||||
fun parseTimetable(jsonString: JSONObject): List<Day> {
|
fun parseTimetable(json: JSONObject): List<Day> {
|
||||||
Log.d("debug", "gotten json: $jsonString")
|
|
||||||
val jsonObject = jsonString
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* return a List that looks like this:
|
* return a List that looks like this:
|
||||||
* [<name>, <date>, [<subj_name>, <subj_place>, <teacher>, <substitute>, <number>, <start_time>, <end_time>]]
|
* [<name>, <date>, [<subj_name>, <subj_place>, <teacher>, <substitute>, <number>, <start_time>, <end_time>]]
|
||||||
* ["Po", "8.1.", ["D", "207", "Strakova S.", 0, 1, "08:00", "08:45" ]]
|
* ["Po", "8.1.", ["D", "207", "Strakova S.", 0, 1, "08:00", "08:45" ]]
|
||||||
*/
|
*/
|
||||||
|
|
||||||
val week = mutableListOf<Day>()
|
val timetable = mutableListOf<Day>()
|
||||||
|
|
||||||
if (jsonObject.has("error")) {
|
if (json.has("error")) {
|
||||||
return week
|
return timetable
|
||||||
}
|
}
|
||||||
|
|
||||||
// Access the "body" array from the main JSON object
|
// Access the "body" array from the main JSON object
|
||||||
val bodyArray = jsonObject.getJSONArray("days")
|
val bodyArray = json.getJSONArray("days")
|
||||||
|
|
||||||
// Convert the JSON array to a list of JSON objects
|
// Convert the JSON array to a list of JSON objects
|
||||||
val jsonObjectList = mutableListOf<JSONObject>()
|
val jsonObjectList = mutableListOf<JSONObject>()
|
||||||
@@ -88,8 +85,12 @@ class Parsing {
|
|||||||
.split("-")
|
.split("-")
|
||||||
|
|
||||||
// remove leading zeros
|
// remove leading zeros
|
||||||
while (dayStr[0] == '0') { dayStr = dayStr.slice(1..<dayStr.length) }
|
while (dayStr[0] == '0') {
|
||||||
while (monthStr[0] == '0') { monthStr = monthStr.slice(1..<monthStr.length) }
|
dayStr = dayStr.slice(1..<dayStr.length)
|
||||||
|
}
|
||||||
|
while (monthStr[0] == '0') {
|
||||||
|
monthStr = monthStr.slice(1..<monthStr.length)
|
||||||
|
}
|
||||||
|
|
||||||
// format it into a string that is readable
|
// format it into a string that is readable
|
||||||
val date = "$dayStr. $monthStr."
|
val date = "$dayStr. $monthStr."
|
||||||
@@ -130,35 +131,34 @@ class Parsing {
|
|||||||
if (type != "SUPLOVANI" && type != "ROZVRH") {
|
if (type != "SUPLOVANI" && type != "ROZVRH") {
|
||||||
when (kind) {
|
when (kind) {
|
||||||
"ZRUSENI_VYUKY_ROZVRH" -> {
|
"ZRUSENI_VYUKY_ROZVRH" -> {
|
||||||
subject.name = subj.get("title").toString()
|
subject.name = subj.getString("title")
|
||||||
subject.place = ""
|
subject.place = ""
|
||||||
subject.teacher = ""
|
subject.teacher = ""
|
||||||
subject.substitute = "2" // 2 means school event
|
subject.substitute = "2" // 2 means school event
|
||||||
|
|
||||||
val hourspan = subj.getJSONArray("detailHours").length()
|
val hourspan = subj.getJSONArray("detailHours").length()
|
||||||
subject.number = "1 - $hourspan"
|
subject.number = "1 - $hourspan"
|
||||||
subject.start = subj.get("beginTime").toString()
|
subject.start = subj.getString("beginTime")
|
||||||
subject.start = subject.start.slice(0..subject.start.length - 4)
|
subject.start = subject.start.slice(0..subject.start.length - 4)
|
||||||
subject.end = subj.get("endTime").toString()
|
subject.end = subj.getString("endTime")
|
||||||
subject.end = subject.end.slice(0..subject.end.length - 4)
|
subject.end = subject.end.slice(0..subject.end.length - 4)
|
||||||
|
|
||||||
subjects.add(subject)
|
subjects.add(subject)
|
||||||
}
|
}
|
||||||
|
|
||||||
"S_NAHRADOU_SKOL_AKCE" -> eventLecture(subject, subj, subjects)
|
"S_NAHRADOU_SKOL_AKCE" -> eventLecture(subject, subj, subjects)
|
||||||
"S_NAHRADOU_VYUKA" -> eventLecture(subject, subj, subjects)
|
"S_NAHRADOU_VYUKA" -> eventLecture(subject, subj, subjects)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
subject.name = subj.getJSONObject("subject").get("abbrev").toString()
|
subject.name = subj.getJSONObject("subject").getString("abbrev")
|
||||||
subject.place =
|
subject.place =
|
||||||
subj.getJSONArray("rooms").getJSONObject(0).get("abbrev").toString()
|
subj.getJSONArray("rooms").getJSONObject(0).getString("abbrev")
|
||||||
subject.teacher = "" +
|
subject.teacher = if (subj.getJSONArray("teachers").length() > 0) {
|
||||||
"${
|
subj.getJSONArray("teachers").getJSONObject(0)
|
||||||
subj.getJSONArray("teachers").getJSONObject(0).get("name")
|
.getString("fullName") // TODO: keep in mind that fullName might not be a valid field (name and surname are!)
|
||||||
} " +
|
} else {
|
||||||
"${
|
""
|
||||||
subj.getJSONArray("teachers").getJSONObject(0)
|
}
|
||||||
.get("surname")
|
|
||||||
}"
|
|
||||||
subject.substitute = when (type) {
|
subject.substitute = when (type) {
|
||||||
"ROZVRH" -> "0"
|
"ROZVRH" -> "0"
|
||||||
"SUPLOVANI" -> "1"
|
"SUPLOVANI" -> "1"
|
||||||
@@ -244,7 +244,7 @@ class Parsing {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
if (subjects.size > 1) {
|
if (subjects.size > 1) {
|
||||||
for (i in 0..<subjects.size-1) {
|
for (i in 0..<subjects.size - 1) {
|
||||||
if (subjects[i].number == ((subjects[i + 1].number.toInt() - 1).toString())) {
|
if (subjects[i].number == ((subjects[i + 1].number.toInt() - 1).toString())) {
|
||||||
auxSubjects.add(subjects[i])
|
auxSubjects.add(subjects[i])
|
||||||
} else {
|
} else {
|
||||||
@@ -257,8 +257,8 @@ class Parsing {
|
|||||||
auxSubjects.add(
|
auxSubjects.add(
|
||||||
Subject.freeSubject(
|
Subject.freeSubject(
|
||||||
previous.toString(),
|
previous.toString(),
|
||||||
subjects[i-1].end,
|
subjects[i - 1].end,
|
||||||
subjects[i+1].start
|
subjects[i + 1].start
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
previous += 1
|
previous += 1
|
||||||
@@ -292,8 +292,8 @@ class Parsing {
|
|||||||
|
|
||||||
for ((i, s) in auxSubjects.withIndex()) {
|
for ((i, s) in auxSubjects.withIndex()) {
|
||||||
if (s.free) {
|
if (s.free) {
|
||||||
s.start = auxSubjects[i-1].end
|
s.start = auxSubjects[i - 1].end
|
||||||
s.end = auxSubjects[i+1].start
|
s.end = auxSubjects[i + 1].start
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -313,15 +313,17 @@ class Parsing {
|
|||||||
prevSubject = s
|
prevSubject = s
|
||||||
}
|
}
|
||||||
|
|
||||||
nextSubjects[nextSubjects.size-1].start = day.subjects[day.subjects.size-1].start
|
nextSubjects[nextSubjects.size - 1].start =
|
||||||
nextSubjects[nextSubjects.size-1].end = day.subjects[day.subjects.size-1].end
|
day.subjects[day.subjects.size - 1].start
|
||||||
|
nextSubjects[nextSubjects.size - 1].end = day.subjects[day.subjects.size - 1].end
|
||||||
|
|
||||||
day.subjects = nextSubjects
|
day.subjects = nextSubjects
|
||||||
|
|
||||||
week.add(day)
|
timetable.add(day)
|
||||||
}
|
}
|
||||||
|
|
||||||
return week
|
Log.d("debug", "timetable: $timetable")
|
||||||
|
return timetable
|
||||||
}
|
}
|
||||||
|
|
||||||
fun parseMarks(jsonString: JSONObject): MutableMap<String, MutableList<Mark>> {
|
fun parseMarks(jsonString: JSONObject): MutableMap<String, MutableList<Mark>> {
|
||||||
|
|||||||
@@ -39,20 +39,21 @@ import kotlinx.coroutines.launch
|
|||||||
import androidx.compose.foundation.layout.*
|
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
|
||||||
|
|
||||||
private var buttonText: MutableState<String> = mutableStateOf("Přihlásit se")
|
private var buttonText by mutableStateOf("Přihlásit se")
|
||||||
|
|
||||||
private fun changeButtonText(s: String) {
|
private fun changeButtonText(s: String) {
|
||||||
buttonText.value = s
|
buttonText = s
|
||||||
}
|
}
|
||||||
|
|
||||||
fun signInButtonCallback(ctx: Context, coscope: CoroutineScope, buttonText: String, usernameText: String, passwordText: String) {
|
fun signInButtonCallback(ctx: Context, usernameText: String, passwordText: String) {
|
||||||
username = usernameText
|
username = usernameText
|
||||||
password = passwordText
|
password = passwordText
|
||||||
val acc = Account(username, password, 0)
|
val acc = Account(username, password, 0)
|
||||||
var checked = false
|
var checked = false
|
||||||
|
|
||||||
coscope.launch {
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
while (!checked) {
|
while (!checked) {
|
||||||
delay(300)
|
delay(300)
|
||||||
changeButtonText("Přihlašování")
|
changeButtonText("Přihlašování")
|
||||||
@@ -85,7 +86,7 @@ fun signInButtonCallback(ctx: Context, coscope: CoroutineScope, buttonText: Stri
|
|||||||
changeButtonText("Přihlásit se")
|
changeButtonText("Přihlásit se")
|
||||||
}
|
}
|
||||||
|
|
||||||
coscope.launch {
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
val valid = Account.isValid(acc)
|
val valid = Account.isValid(acc)
|
||||||
|
|
||||||
checked = true
|
checked = true
|
||||||
@@ -108,9 +109,7 @@ fun signInButtonCallback(ctx: Context, coscope: CoroutineScope, buttonText: Stri
|
|||||||
fun SignInScreen() {
|
fun SignInScreen() {
|
||||||
// handle the back gesture (back swipe form side or back button on bottom android navbar)
|
// handle the back gesture (back swipe form side or back button on bottom android navbar)
|
||||||
if (!global.noSignInBackHandle) {
|
if (!global.noSignInBackHandle) {
|
||||||
BackHandler {
|
BackHandler { global.currentScreen = Screen.Main }
|
||||||
global.currentScreen = Screen.Main
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var usernameText by remember { mutableStateOf("") }
|
var usernameText by remember { mutableStateOf("") }
|
||||||
@@ -200,7 +199,7 @@ fun SignInScreen() {
|
|||||||
|
|
||||||
Button(
|
Button(
|
||||||
onClick = {
|
onClick = {
|
||||||
signInButtonCallback(ctx, coscope, buttonText.value, usernameText, passwordText)
|
signInButtonCallback(ctx, usernameText, passwordText)
|
||||||
},
|
},
|
||||||
colors = ButtonDefaults.buttonColors(
|
colors = ButtonDefaults.buttonColors(
|
||||||
contentColor = Color.White,
|
contentColor = Color.White,
|
||||||
@@ -215,7 +214,7 @@ fun SignInScreen() {
|
|||||||
.width(230.dp)
|
.width(230.dp)
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = buttonText.value,
|
text = buttonText,
|
||||||
fontSize = 23.sp
|
fontSize = 23.sp
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,12 +40,7 @@ fun SplashScreen() {
|
|||||||
|
|
||||||
AndroidView(
|
AndroidView(
|
||||||
modifier = Modifier.size(200.dp),
|
modifier = Modifier.size(200.dp),
|
||||||
factory = { context: Context ->
|
factory = { context: Context -> ImageView(context) },
|
||||||
ImageView(context).apply {
|
|
||||||
// Set a placeholder if needed
|
|
||||||
// setImageResource(R.drawable.placeholder)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
update = { imageView ->
|
update = { imageView ->
|
||||||
Glide.with(imageView.context)
|
Glide.with(imageView.context)
|
||||||
.load(R.drawable.loading)
|
.load(R.drawable.loading)
|
||||||
|
|||||||
@@ -69,19 +69,16 @@ import java.time.LocalDate
|
|||||||
import java.time.LocalTime
|
import java.time.LocalTime
|
||||||
import java.time.format.DateTimeFormatter
|
import java.time.format.DateTimeFormatter
|
||||||
|
|
||||||
var showDetailDialog = mutableStateOf(false)
|
var showDetailDialog by mutableStateOf(false)
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun TimetableScreen() {
|
fun TimetableScreen() {
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier.fillMaxSize(),
|
||||||
.fillMaxSize(),
|
|
||||||
contentAlignment = Alignment.BottomCenter
|
contentAlignment = Alignment.BottomCenter
|
||||||
) {
|
) {
|
||||||
DayPager()
|
DayPager()
|
||||||
if (showDetailDialog.value) {
|
if (showDetailDialog) DetailDialog()
|
||||||
DetailDialog()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,7 +87,7 @@ fun TimetableScreen() {
|
|||||||
@Composable
|
@Composable
|
||||||
fun DetailDialog() {
|
fun DetailDialog() {
|
||||||
Dialog(
|
Dialog(
|
||||||
onDismissRequest = { showDetailDialog.value = false }, // Close the dialog on dismiss
|
onDismissRequest = { showDetailDialog = false }, // Close the dialog on dismiss
|
||||||
properties = DialogProperties(
|
properties = DialogProperties(
|
||||||
dismissOnBackPress = true,
|
dismissOnBackPress = true,
|
||||||
dismissOnClickOutside = true
|
dismissOnClickOutside = true
|
||||||
@@ -102,7 +99,7 @@ fun DetailDialog() {
|
|||||||
.padding(horizontal = 20.dp)
|
.padding(horizontal = 20.dp)
|
||||||
.background(
|
.background(
|
||||||
color = Color.Black,
|
color = Color.Black,
|
||||||
shape = RoundedCornerShape(roundedCornerDimen)
|
shape = RoundedCornerShape(global.dimens.roundedCorner)
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
Column(
|
Column(
|
||||||
@@ -110,9 +107,9 @@ fun DetailDialog() {
|
|||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = "" +
|
text = "" +
|
||||||
lectureNotes[selectedLecture]?.number.toString() +
|
global.lectureNotes[global.selectedLecture]?.number.toString() +
|
||||||
" – " +
|
" – " +
|
||||||
lectureNotes[selectedLecture]?.lectureName.toString(),
|
global.lectureNotes[global.selectedLecture]?.lectureName.toString(),
|
||||||
color = Color.White,
|
color = Color.White,
|
||||||
textAlign = TextAlign.Left,
|
textAlign = TextAlign.Left,
|
||||||
modifier = Modifier.padding(top = 10.dp)
|
modifier = Modifier.padding(top = 10.dp)
|
||||||
@@ -125,7 +122,7 @@ fun DetailDialog() {
|
|||||||
Button(
|
Button(
|
||||||
modifier = Modifier.background(
|
modifier = Modifier.background(
|
||||||
color = Color.Black,
|
color = Color.Black,
|
||||||
shape = RoundedCornerShape(roundedCornerDimen)
|
shape = RoundedCornerShape(global.dimens.roundedCorner)
|
||||||
),
|
),
|
||||||
onClick = { isExpanded = true },
|
onClick = { isExpanded = true },
|
||||||
colors = ButtonColors(
|
colors = ButtonColors(
|
||||||
@@ -135,7 +132,7 @@ fun DetailDialog() {
|
|||||||
disabledContentColor = Color.White
|
disabledContentColor = Color.White
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
val type = when (lectureNotes[selectedLecture]?.type?.value) {
|
val type = when (global.lectureNotes[global.selectedLecture]?.type?.value) {
|
||||||
LectureNoteType.Normal -> "Normální"
|
LectureNoteType.Normal -> "Normální"
|
||||||
LectureNoteType.Writing -> "Písemný test"
|
LectureNoteType.Writing -> "Písemný test"
|
||||||
LectureNoteType.Speaking -> "Ústní zkoušení"
|
LectureNoteType.Speaking -> "Ústní zkoušení"
|
||||||
@@ -160,7 +157,7 @@ fun DetailDialog() {
|
|||||||
enabled = true,
|
enabled = true,
|
||||||
onClick = {
|
onClick = {
|
||||||
isExpanded = false
|
isExpanded = false
|
||||||
lectureNotes[selectedLecture]?.type?.value = LectureNoteType.Normal
|
global.lectureNotes[global.selectedLecture]?.type?.value = LectureNoteType.Normal
|
||||||
Util.saveLectureNotes()
|
Util.saveLectureNotes()
|
||||||
},
|
},
|
||||||
text = { Text("Normální poznámka", color = Color.White) }
|
text = { Text("Normální poznámka", color = Color.White) }
|
||||||
@@ -170,7 +167,7 @@ fun DetailDialog() {
|
|||||||
enabled = true,
|
enabled = true,
|
||||||
onClick = {
|
onClick = {
|
||||||
isExpanded = false
|
isExpanded = false
|
||||||
lectureNotes[selectedLecture]?.type?.value = LectureNoteType.Writing
|
global.lectureNotes[global.selectedLecture]?.type?.value = LectureNoteType.Writing
|
||||||
Util.saveLectureNotes()
|
Util.saveLectureNotes()
|
||||||
},
|
},
|
||||||
text = { Text("Písemný test", color = Color.White) }
|
text = { Text("Písemný test", color = Color.White) }
|
||||||
@@ -180,7 +177,7 @@ fun DetailDialog() {
|
|||||||
enabled = true,
|
enabled = true,
|
||||||
onClick = {
|
onClick = {
|
||||||
isExpanded = false
|
isExpanded = false
|
||||||
lectureNotes[selectedLecture]?.type?.value = LectureNoteType.Speaking
|
global.lectureNotes[global.selectedLecture]?.type?.value = LectureNoteType.Speaking
|
||||||
Util.saveLectureNotes()
|
Util.saveLectureNotes()
|
||||||
},
|
},
|
||||||
text = { Text("Ústní zkoušení", color = Color.White) }
|
text = { Text("Ústní zkoušení", color = Color.White) }
|
||||||
@@ -190,7 +187,7 @@ fun DetailDialog() {
|
|||||||
enabled = true,
|
enabled = true,
|
||||||
onClick = {
|
onClick = {
|
||||||
isExpanded = false
|
isExpanded = false
|
||||||
lectureNotes[selectedLecture]?.type?.value = LectureNoteType.Other
|
global.lectureNotes[global.selectedLecture]?.type?.value = LectureNoteType.Other
|
||||||
Util.saveLectureNotes()
|
Util.saveLectureNotes()
|
||||||
},
|
},
|
||||||
text = { Text("Jiné", color = Color.White) }
|
text = { Text("Jiné", color = Color.White) }
|
||||||
@@ -200,9 +197,9 @@ fun DetailDialog() {
|
|||||||
////////////////////////////////////////////////
|
////////////////////////////////////////////////
|
||||||
|
|
||||||
TextField(
|
TextField(
|
||||||
value = lectureNotes[selectedLecture]?.note?.value ?: "",
|
value = global.lectureNotes[global.selectedLecture]?.note?.value ?: "",
|
||||||
onValueChange = { newText: String ->
|
onValueChange = { newText: String ->
|
||||||
lectureNotes[selectedLecture]?.note?.value = newText
|
global.lectureNotes[global.selectedLecture]?.note?.value = newText
|
||||||
Util.saveLectureNotes()
|
Util.saveLectureNotes()
|
||||||
},
|
},
|
||||||
singleLine = true,
|
singleLine = true,
|
||||||
@@ -228,12 +225,12 @@ fun DetailDialog() {
|
|||||||
@OptIn(ExperimentalFoundationApi::class)
|
@OptIn(ExperimentalFoundationApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun DayPager() {
|
fun DayPager() {
|
||||||
val pagerState = rememberPagerState(pageCount = { days.size })
|
val pagerState = rememberPagerState(pageCount = { if (global.timetable.isNotEmpty()) global.timetable.size else 6 }) // FIXME
|
||||||
HorizontalPager(
|
HorizontalPager(
|
||||||
state = pagerState,
|
state = pagerState,
|
||||||
modifier = Modifier.fillMaxSize()
|
modifier = Modifier.fillMaxSize()
|
||||||
) { pageIndex ->
|
) { pageIndex ->
|
||||||
DayScreen(days[pageIndex])
|
DayScreen(global.timetable[pageIndex])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -287,7 +284,7 @@ fun subjectModifier(d: Day, s: Subject, lectureNumber: Int): Modifier {
|
|||||||
val now = LocalTime.now()
|
val now = LocalTime.now()
|
||||||
|
|
||||||
if (dateParsed == todayDate && isTimeBetween(now, startTimeParsed, endTimeParsed)) {
|
if (dateParsed == todayDate && isTimeBetween(now, startTimeParsed, endTimeParsed)) {
|
||||||
currentLectureNumber = lectureNumber
|
global.currentLectureNumber = lectureNumber
|
||||||
}
|
}
|
||||||
|
|
||||||
val m = if (settings.useAmoledMode.checked.value) {
|
val m = if (settings.useAmoledMode.checked.value) {
|
||||||
@@ -295,9 +292,9 @@ fun subjectModifier(d: Day, s: Subject, lectureNumber: Int): Modifier {
|
|||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.height(70.dp)
|
.height(70.dp)
|
||||||
.border(
|
.border(
|
||||||
width = borderWidthDimen,
|
width = global.dimens.borderWidth,
|
||||||
color = getSubjectColor(s, false), // decide on the color (transparent)
|
color = getSubjectColor(s, false), // decide on the color (transparent)
|
||||||
shape = RoundedCornerShape(roundedCornerDimen)
|
shape = RoundedCornerShape(global.dimens.roundedCorner)
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
Modifier
|
Modifier
|
||||||
@@ -305,15 +302,15 @@ fun subjectModifier(d: Day, s: Subject, lectureNumber: Int): Modifier {
|
|||||||
.height(70.dp)
|
.height(70.dp)
|
||||||
.background(
|
.background(
|
||||||
color = getSubjectColor(s, true), // decide on the color (transparent)
|
color = getSubjectColor(s, true), // decide on the color (transparent)
|
||||||
shape = RoundedCornerShape(roundedCornerDimen)
|
shape = RoundedCornerShape(global.dimens.roundedCorner)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return if (lectureNumber == currentLectureNumber && dateParsed == todayDate) {
|
return if (lectureNumber == global.currentLectureNumber && dateParsed == todayDate) {
|
||||||
m.border(
|
m.border(
|
||||||
width = borderWidthDimen,
|
width = global.dimens.borderWidth,
|
||||||
color = getSubjectColor(s, false),
|
color = getSubjectColor(s, false),
|
||||||
shape = RoundedCornerShape(roundedCornerDimen)
|
shape = RoundedCornerShape(global.dimens.roundedCorner)
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
m
|
m
|
||||||
@@ -359,12 +356,12 @@ private fun DayScreen(day: Day) {
|
|||||||
.width(50.dp)
|
.width(50.dp)
|
||||||
.fillMaxHeight()
|
.fillMaxHeight()
|
||||||
.border(
|
.border(
|
||||||
width = borderWidthDimen,
|
width = global.dimens.borderWidth,
|
||||||
color = getSubjectColor(
|
color = getSubjectColor(
|
||||||
subject,
|
subject,
|
||||||
false
|
false
|
||||||
),
|
),
|
||||||
shape = RoundedCornerShape(roundedCornerDimen)
|
shape = RoundedCornerShape(global.dimens.roundedCorner)
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
Modifier
|
Modifier
|
||||||
@@ -375,7 +372,7 @@ private fun DayScreen(day: Day) {
|
|||||||
subject,
|
subject,
|
||||||
true
|
true
|
||||||
),
|
),
|
||||||
shape = RoundedCornerShape(roundedCornerDimen)
|
shape = RoundedCornerShape(global.dimens.roundedCorner)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -482,7 +479,7 @@ private fun DayScreen(day: Day) {
|
|||||||
if (settings.useSvobodaMode.checked.value) {
|
if (settings.useSvobodaMode.checked.value) {
|
||||||
if (
|
if (
|
||||||
subject.teacher == "Jindřich Svoboda" &&
|
subject.teacher == "Jindřich Svoboda" &&
|
||||||
studentClass == "5. G"
|
global.studentClass == "5. G"
|
||||||
) {
|
) {
|
||||||
Image(
|
Image(
|
||||||
painter = painterResource(R.drawable.spock),
|
painter = painterResource(R.drawable.spock),
|
||||||
@@ -529,14 +526,14 @@ private fun DayScreen(day: Day) {
|
|||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.zIndex(99f)
|
.zIndex(99f)
|
||||||
.clickable {
|
.clickable {
|
||||||
selectedLecture = lectureId
|
global.selectedLecture = lectureId
|
||||||
showDetailDialog.value = true
|
showDetailDialog = true
|
||||||
})
|
})
|
||||||
|
|
||||||
if (
|
if (
|
||||||
(lectureNotes[lectureId] != null && lectureNotes[lectureId]?.note?.value != "") ||
|
(global.lectureNotes[lectureId] != null && global.lectureNotes[lectureId]?.note?.value != "") ||
|
||||||
(lectureNotes[lectureId] != null && lectureNotes[lectureId]?.type?.value != LectureNoteType.Normal) &&
|
(global.lectureNotes[lectureId] != null && global.lectureNotes[lectureId]?.type?.value != LectureNoteType.Normal) &&
|
||||||
(lectureNotes[lectureId] != null && lectureNotes[lectureId]?.type?.value != LectureNoteType.Other)
|
(global.lectureNotes[lectureId] != null && global.lectureNotes[lectureId]?.type?.value != LectureNoteType.Other)
|
||||||
) {
|
) {
|
||||||
Icon(
|
Icon(
|
||||||
modifier = Modifier.padding(start = 3.dp, top = 1.dp),
|
modifier = Modifier.padding(start = 3.dp, top = 1.dp),
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import androidx.compose.foundation.layout.height
|
|||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.DisposableEffect
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
@@ -14,6 +15,10 @@ import androidx.compose.ui.Modifier
|
|||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@@ -48,10 +53,11 @@ fun ToolbarScreen() {
|
|||||||
|
|
||||||
enum class StatusType {
|
enum class StatusType {
|
||||||
NameRole,
|
NameRole,
|
||||||
NoInternet
|
NoInternet,
|
||||||
|
Loading
|
||||||
}
|
}
|
||||||
|
|
||||||
interface StatusFactoryInterface {
|
private interface StatusFactoryInterface {
|
||||||
fun show(type: StatusType)
|
fun show(type: StatusType)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,6 +76,25 @@ object StatusFactory: StatusFactoryInterface {
|
|||||||
StatusType.NoInternet -> {
|
StatusType.NoInternet -> {
|
||||||
showStatus("Bez připojení k internetu.")
|
showStatus("Bez připojení k internetu.")
|
||||||
}
|
}
|
||||||
|
StatusType.Loading -> {
|
||||||
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
global.refreshed = false
|
||||||
|
val anim = listOf(
|
||||||
|
"Přihlašování",
|
||||||
|
"Přihlašování.",
|
||||||
|
"Přihlašování..",
|
||||||
|
"Přihlašování...",
|
||||||
|
"Přihlašování..",
|
||||||
|
"Přihlašování."
|
||||||
|
)
|
||||||
|
var i = 0
|
||||||
|
while (!global.refreshed) {
|
||||||
|
if (i == anim.size) i = 0
|
||||||
|
showStatus(anim[i++])
|
||||||
|
delay(300)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -280,8 +280,8 @@ class Util {
|
|||||||
note += ",${parts[part]}"
|
note += ",${parts[part]}"
|
||||||
}
|
}
|
||||||
|
|
||||||
lectureNotes[id]?.note = mutableStateOf(note)
|
global.lectureNotes[id]?.note = mutableStateOf(note)
|
||||||
lectureNotes[id]?.type = mutableStateOf(type)
|
global.lectureNotes[id]?.type = mutableStateOf(type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -301,7 +301,7 @@ class Util {
|
|||||||
for (day in days) {
|
for (day in days) {
|
||||||
for ((subjectIndex, subject) in day.subjects.withIndex()) {
|
for ((subjectIndex, subject) in day.subjects.withIndex()) {
|
||||||
val id = getLectureId(day.date, subjectIndex)
|
val id = getLectureId(day.date, subjectIndex)
|
||||||
lectureNotes[id] = LectureNote(
|
global.lectureNotes[id] = LectureNote(
|
||||||
id = id,
|
id = id,
|
||||||
type = mutableStateOf(LectureNoteType.Normal),
|
type = mutableStateOf(LectureNoteType.Normal),
|
||||||
note = mutableStateOf(""),
|
note = mutableStateOf(""),
|
||||||
@@ -315,8 +315,8 @@ class Util {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun saveLectureNotes() {
|
fun saveLectureNotes() {
|
||||||
val toSave = lectureNotesToCsvString(lectureNotes)
|
val toSave = lectureNotesToCsvString(global.lectureNotes)
|
||||||
saveStringToFile(lectureNotesFilePath, toSave)
|
saveStringToFile(global.filePaths.lectureNotes, toSave)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user