/** * ProjectLaogai * * Copyright 2019-2020 * * 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 androidx.swiperefreshlayout.widget.SwipeRefreshLayout 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.preferences.EncryptedPreferences import org.mosad.seil0.projectlaogai.uicomponents.DayCardView import org.mosad.seil0.projectlaogai.uicomponents.GradeLinearLayout import org.mosad.seil0.projectlaogai.uicomponents.dialogs.LoginDialog /** * The grades fragment class * contains all needed parts to display and the grades screen */ class GradesFragment : Fragment() { private lateinit var refreshLayoutGrades: SwipeRefreshLayout private lateinit var parser: QISPOSParser override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { val view: View = inflater.inflate(R.layout.fragment_grades, container, false) refreshLayoutGrades = view.findViewById(R.id.refreshLayout_Grades) refreshLayoutGrades.isEnabled = false // disable swipe parser = QISPOSParser(context!!)// init the parser return view } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) if (checkCredentials() && checkQisposStatus()) { GlobalScope.launch(Dispatchers.Default) { 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() 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 private fun addGrades() = GlobalScope.launch(Dispatchers.Default) { withContext(Dispatchers.Main) { refreshLayout_Grades.isRefreshing = true } val grades = parser.parseGrades() withContext(Dispatchers.Main) { linLayout_Grades.removeAllViews() // clear layout } // for each semester add a new card grades.forEach { semester -> val usedSubjects = ArrayList() 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 } } }