227 lines
8.0 KiB
Kotlin
227 lines
8.0 KiB
Kotlin
/**
|
|
* ProjectLaogai
|
|
*
|
|
* Copyright 2019-2020 <seil0@mosad.xyz>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
* MA 02110-1301, USA.
|
|
*
|
|
*/
|
|
|
|
package org.mosad.seil0.projectlaogai.fragments
|
|
|
|
import android.graphics.Rect
|
|
import android.os.Bundle
|
|
import android.view.LayoutInflater
|
|
import android.view.View
|
|
import android.view.ViewGroup
|
|
import android.widget.TextView
|
|
import androidx.core.content.res.ResourcesCompat
|
|
import androidx.fragment.app.Fragment
|
|
import kotlinx.android.synthetic.main.fragment_grades.*
|
|
import kotlinx.coroutines.*
|
|
import org.mosad.seil0.projectlaogai.R
|
|
import org.mosad.seil0.projectlaogai.controller.QISPOSParser
|
|
import org.mosad.seil0.projectlaogai.controller.cache.CacheController
|
|
import org.mosad.seil0.projectlaogai.controller.preferences.EncryptedPreferences
|
|
import org.mosad.seil0.projectlaogai.controller.preferences.Preferences
|
|
import org.mosad.seil0.projectlaogai.uicomponents.DayCardView
|
|
import org.mosad.seil0.projectlaogai.uicomponents.GradeLinearLayout
|
|
import org.mosad.seil0.projectlaogai.uicomponents.dialogs.LoginDialog
|
|
import kotlin.system.measureTimeMillis
|
|
|
|
/**
|
|
* The grades fragment class
|
|
* contains all needed parts to display and the grades screen
|
|
*/
|
|
class GradesFragment : Fragment() {
|
|
|
|
private lateinit var parser: QISPOSParser
|
|
|
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
|
return inflater.inflate(R.layout.fragment_grades, container, false)
|
|
}
|
|
|
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
|
super.onViewCreated(view, savedInstanceState)
|
|
|
|
refreshLayout_Grades.setProgressBackgroundColorSchemeColor(Preferences.themeSecondary)
|
|
initActions()
|
|
|
|
parser = QISPOSParser(context!!)// init the parser
|
|
|
|
// TODO if loading from cache, don't check Qispos state
|
|
if (checkCredentials() && checkQisposStatus()) {
|
|
GlobalScope.launch(Dispatchers.Default) {
|
|
addGrades()
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* initialize the actions
|
|
*/
|
|
private fun initActions() = GlobalScope.launch(Dispatchers.Default) {
|
|
refreshLayout_Grades.setOnRefreshListener {
|
|
linLayout_Grades.removeAllViews() // clear layout
|
|
// TODO add loading textView
|
|
|
|
GlobalScope.launch(Dispatchers.Default) {
|
|
CacheController.updateGrades(context!!).join()
|
|
addGrades()
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* check if the credentials are set, if not show a login dialog
|
|
*/
|
|
private fun checkCredentials(): Boolean {
|
|
val credentials = EncryptedPreferences.readCredentials(context!!)
|
|
var credentialsPresent = false
|
|
|
|
// if there is no password set, show the login dialog
|
|
if (credentials.first.isEmpty() || credentials.second.isEmpty()) {
|
|
LoginDialog(this.context!!)
|
|
.positiveButton {
|
|
EncryptedPreferences.saveCredentials(email, password, context)
|
|
addGrades()
|
|
}
|
|
.negativeButton {
|
|
txtView_Loading.text = resources.getString(R.string.credentials_missing)
|
|
}
|
|
.show {
|
|
email = EncryptedPreferences.email
|
|
password = ""
|
|
}
|
|
} else {
|
|
credentialsPresent = true
|
|
}
|
|
|
|
return credentialsPresent
|
|
}
|
|
|
|
/**
|
|
* check if qispos is available, if not show an error
|
|
*/
|
|
private fun checkQisposStatus(): Boolean {
|
|
val statusCode = parser.checkQISPOSStatus()
|
|
|
|
// show error if the status code is not 200
|
|
if (statusCode != 200) {
|
|
val infoText = resources.getString(when(statusCode) {
|
|
503 -> R.string.qispos_unavailable
|
|
else -> R.string.qispos_generic_error
|
|
})
|
|
|
|
val img = ResourcesCompat.getDrawable(resources, R.drawable.ic_error_outline_black_24dp, null)?.apply {
|
|
bounds = Rect(0, 0, 75, 75)
|
|
}
|
|
|
|
txtView_Loading?.apply {
|
|
text = infoText
|
|
setCompoundDrawables(null, null, null, img)
|
|
}
|
|
}
|
|
|
|
return statusCode == 200
|
|
}
|
|
|
|
/**
|
|
* add the grades to the layout, async
|
|
* TODO this is slow as hell
|
|
*/
|
|
private fun addGrades() = GlobalScope.launch(Dispatchers.Default) {
|
|
val addGradesTime = measureTimeMillis {
|
|
|
|
withContext(Dispatchers.Main) {
|
|
refreshLayout_Grades.isRefreshing = true
|
|
}
|
|
|
|
// if the cache is older than 24hr, update blocking
|
|
val currentTime = System.currentTimeMillis() / 1000
|
|
if ((currentTime - Preferences.gradesCacheTime) > 86400) {
|
|
CacheController.updateGrades(context!!).join()
|
|
}
|
|
|
|
val grades = CacheController(context!!).readGrades()
|
|
|
|
withContext(Dispatchers.Main) {
|
|
linLayout_Grades.removeAllViews() // clear layout
|
|
}
|
|
|
|
// TODO this loop takes 3/4 of the time
|
|
// for each semester add a new card
|
|
grades.forEach { semester ->
|
|
val usedSubjects = ArrayList<String>()
|
|
val semesterCard = DayCardView(context!!)
|
|
semesterCard.setDayHeading(semester.key)
|
|
|
|
// for each subject add a new linLayout
|
|
semester.value.forEachIndexed { index, subject ->
|
|
if (usedSubjects.contains(subject.name)) {
|
|
return@forEachIndexed
|
|
}
|
|
|
|
// get the first sub subjects
|
|
val subSubject = semester.value.firstOrNull {
|
|
it.name.contains(subject.name) && it.name != subject.name
|
|
}
|
|
|
|
// if sub subject is not null, add it to used subjects
|
|
subSubject?.let {
|
|
usedSubjects.add(it.name)
|
|
}
|
|
|
|
val subjectLayout = GradeLinearLayout(context).set {
|
|
subjectName = subject.name
|
|
grade = subject.grade
|
|
subSubjectName = subSubject?.name.toString()
|
|
subGrade = subSubject?.grade.toString()
|
|
}
|
|
|
|
// disable sub-subject if not set
|
|
if (subSubject == null)
|
|
subjectLayout.disableSubSubject()
|
|
|
|
// disable divider if last element
|
|
if (index == semester.value.lastIndex || semester.value.indexOf(subSubject) == semester.value.lastIndex)
|
|
subjectLayout.disableDivider()
|
|
|
|
semesterCard.getLinLayoutDay().addView(subjectLayout)
|
|
}
|
|
|
|
// without context we can't access the view
|
|
withContext(Dispatchers.Main) {
|
|
linLayout_Grades.addView(semesterCard)
|
|
}
|
|
}
|
|
|
|
val txtViewLegal = TextView(context).apply {
|
|
text = resources.getString(R.string.without_guarantee)
|
|
textAlignment = View.TEXT_ALIGNMENT_CENTER
|
|
}
|
|
|
|
// stop refreshing and show legal warning
|
|
withContext(Dispatchers.Main) {
|
|
linLayout_Grades.addView(txtViewLegal)
|
|
refreshLayout_Grades.isRefreshing = false
|
|
}
|
|
|
|
}
|
|
println("added grades in $addGradesTime ms")
|
|
}
|
|
|
|
} |