Update dependencies, AGP and make the app build again

This commit is contained in:
Jannik 2022-12-22 17:26:07 +01:00
parent b76f869ef0
commit 3e52061a20
Signed by: Seil0
GPG Key ID: E8459F3723C52C24
14 changed files with 221 additions and 220 deletions

View File

@ -6,13 +6,13 @@ android {
signingConfigs {
}
compileSdkVersion 30
buildToolsVersion "30.0.2"
compileSdkVersion 33
buildToolsVersion "30.0.3"
defaultConfig {
applicationId "org.mosad.seil0.projectlaogai"
minSdkVersion 23
targetSdkVersion 30
targetSdkVersion 33
versionCode 6091 // 00.06.091
versionName "0.6.1-beta2"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
@ -66,30 +66,30 @@ android {
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.2'
implementation 'androidx.core:core-ktx:1.3.2'
implementation 'androidx.navigation:navigation-fragment-ktx:2.3.1'
implementation 'androidx.navigation:navigation-ui-ktx:2.3.1'
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4'
implementation 'androidx.core:core-ktx:1.9.0'
implementation 'androidx.navigation:navigation-fragment-ktx:2.5.3'
implementation 'androidx.navigation:navigation-ui-ktx:2.5.3'
implementation 'androidx.appcompat:appcompat:1.5.1'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
implementation 'androidx.security:security-crypto:1.1.0-alpha02'
implementation "androidx.work:work-runtime-ktx:2.4.0"
implementation 'com.google.android.material:material:1.2.1'
implementation 'com.google.code.gson:gson:2.8.6'
implementation 'com.afollestad:aesthetic:1.0.0-beta05'
implementation 'androidx.security:security-crypto:1.1.0-alpha04'
implementation "androidx.work:work-runtime-ktx:2.7.1"
implementation 'com.google.android.material:material:1.7.0'
implementation 'com.google.code.gson:gson:2.10'
// implementation 'com.afollestad:aesthetic:1.0.0-beta05'
implementation 'com.afollestad.material-dialogs:core:3.3.0'
implementation 'com.afollestad.material-dialogs:color:3.3.0'
implementation 'com.afollestad.material-dialogs:bottomsheets:3.3.0'
implementation 'de.psdev.licensesdialog:licensesdialog:2.1.0'
implementation 'org.apache.commons:commons-lang3:3.11'
implementation 'org.jsoup:jsoup:1.13.1'
implementation 'org.jsoup:jsoup:1.15.3'
testImplementation 'org.junit.jupiter:junit-jupiter:5.6.2'
androidTestImplementation 'androidx.test:core:1.3.0'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
testImplementation 'org.junit.jupiter:junit-jupiter:5.8.2'
androidTestImplementation 'androidx.test:core:1.5.0'
androidTestImplementation 'androidx.test.ext:junit:1.1.4'
}
static def buildTime() {

View File

@ -1,55 +1,56 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.mosad.seil0.projectlaogai">
<uses-permission android:name="android.permission.INTERNET"/>
package="org.mosad.seil0.projectlaogai">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.NFC" />
<application
android:allowBackup="true"
android:fullBackupContent="@xml/backup_descriptor"
android:icon="@mipmap/ic_laogai_icon"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_laogai_icon"
android:supportsRtl="true"
android:theme="@style/AppTheme.Light">
android:allowBackup="true"
android:fullBackupContent="@xml/backup_descriptor"
android:icon="@mipmap/ic_laogai_icon"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_laogai_icon"
android:supportsRtl="true"
android:theme="@style/AppTheme.Light">
<activity
android:name=".SplashActivity"
android:label="@string/app_name"
android:theme="@style/SplashTheme"
android:screenOrientation="portrait">
android:name=".SplashActivity"
android:screenOrientation="portrait"
android:theme="@style/SplashTheme"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data android:name="android.app.shortcuts"
android:resource="@xml/shortcuts" />
<meta-data
android:name="android.app.shortcuts"
android:resource="@xml/shortcuts" />
</activity>
<activity
android:name=".OnboardingActivity"
android:label="@string/app_name"
android:theme="@style/AppTheme.Light"
android:screenOrientation="portrait"
android:launchMode="singleTop">
</activity>
android:name=".OnboardingActivity"
android:launchMode="singleTop"
android:screenOrientation="portrait"
android:theme="@style/AppTheme.Light" />
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:theme="@style/AppTheme.Light"
android:screenOrientation="portrait"
android:launchMode="singleTop">
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop"
android:screenOrientation="portrait"
android:theme="@style/AppTheme.Light">
<!-- nfc stuff -->
<intent-filter>
<action android:name="android.nfc.action.TECH_DISCOVERED"/>
<action android:name="android.nfc.action.TECH_DISCOVERED" />
</intent-filter>
<meta-data android:name="android.nfc.action.TECH_DISCOVERED"
android:resource="@xml/nfc_tech_filter" />
<meta-data
android:name="android.nfc.action.TECH_DISCOVERED"
android:resource="@xml/nfc_tech_filter" />
</activity>
</application>

View File

@ -34,14 +34,15 @@ import android.util.Log
import android.util.TypedValue
import android.view.Menu
import android.view.MenuItem
import androidx.activity.addCallback
import androidx.appcompat.app.ActionBarDrawerToggle
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.GravityCompat
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentTransaction
import androidx.fragment.app.commit
import com.afollestad.aesthetic.Aesthetic
import com.afollestad.aesthetic.NavigationViewMode
//import com.afollestad.aesthetic.Aesthetic
//import com.afollestad.aesthetic.NavigationViewMode
import com.google.android.material.navigation.NavigationView
import org.mosad.seil0.projectlaogai.controller.NFCMensaCard
import org.mosad.seil0.projectlaogai.controller.cache.CacheController
@ -67,7 +68,7 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
private var useNFC = false
override fun onCreate(savedInstanceState: Bundle?) {
Aesthetic.attach(this)
// Aesthetic.attach(this)
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
@ -100,6 +101,12 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
supportFragmentManager.commit {
replace(R.id.fragment_container, activeFragment, activeFragment.javaClass.simpleName)
}
onBackPressedDispatcher.addCallback {
if (binding.drawerLayout.isDrawerOpen(GravityCompat.START)) {
binding.drawerLayout.closeDrawer(GravityCompat.START)
}
}
}
override fun onNewIntent(intent: Intent) {
@ -112,7 +119,7 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
override fun onResume() {
super.onResume()
Aesthetic.resume(this)
// Aesthetic.resume(this)
if(useNFC)
adapter.enableForegroundDispatch(this, pendingIntent, intentFiltersArray, techListsArray)
@ -120,20 +127,11 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
override fun onPause() {
super.onPause()
Aesthetic.pause(this)
// Aesthetic.pause(this)
if(useNFC)
adapter.disableForegroundDispatch(this)
}
override fun onBackPressed() {
if (binding.drawerLayout.isDrawerOpen(GravityCompat.START)) {
binding.drawerLayout.closeDrawer(GravityCompat.START)
} else {
// TODO only call on double tap
super.onBackPressed()
}
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
// Inflate the menu; this adds items to the action bar if it is present.
menuInflater.inflate(R.menu.main, menu)
@ -186,25 +184,25 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
private fun initAesthetic() {
// If we haven't set any defaults, do that now
if (Aesthetic.isFirstTime) {
// set the default theme at the first app start
Aesthetic.config {
activityTheme(R.style.AppTheme_Light)
apply()
}
// show the onboarding activity
startActivity(Intent(this, OnboardingActivity::class.java))
finish()
}
Aesthetic.config {
colorPrimary(Preferences.colorPrimary)
colorPrimaryDark(Preferences.colorPrimary)
colorAccent(Preferences.colorAccent)
navigationViewMode(NavigationViewMode.SELECTED_ACCENT)
apply()
}
// if (Aesthetic.isFirstTime) {
// // set the default theme at the first app start
// Aesthetic.config {
// activityTheme(R.style.AppTheme_Light)
// apply()
// }
// // TODO needs to be shown on first start
// // show the onboarding activity
// startActivity(Intent(this, OnboardingActivity::class.java))
// finish()
// }
//
// Aesthetic.config {
// colorPrimary(Preferences.colorPrimary)
// colorPrimaryDark(Preferences.colorPrimary)
// colorAccent(Preferences.colorAccent)
// navigationViewMode(NavigationViewMode.SELECTED_ACCENT)
// apply()
// }
// set theme color values
val out = TypedValue()

View File

@ -31,6 +31,7 @@ import android.widget.LinearLayout
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.core.text.HtmlCompat
import androidx.lifecycle.lifecycleScope
import androidx.viewpager.widget.ViewPager
import kotlinx.coroutines.*
import org.mosad.seil0.projectlaogai.controller.cache.CacheController
@ -94,7 +95,7 @@ class OnboardingActivity : AppCompatActivity() {
val loadingDialog = LoadingDialog(context)
loadingDialog.show()
GlobalScope.launch(Dispatchers.Default) {
lifecycleScope.launch(Dispatchers.Default) {
Preferences.saveCourse(context, CacheController.coursesList[selectedIndex]) // save the course
// update current & next weeks timetable

View File

@ -160,7 +160,8 @@ class QISPOSParser(val context: Context) {
// grades root document and url
val rootHtml =Jsoup.parse(res.body())
val gradesRootLink = rootHtml.select("li.menueListStyle > a.auflistung").last().attr("abs:href")
val gradesRootLink =
rootHtml.select("li.menueListStyle > a.auflistung").last()!!.attr("abs:href")
// parse grades url
val gradesHtml = Jsoup.connect(gradesRootLink)
@ -179,7 +180,7 @@ class QISPOSParser(val context: Context) {
.referrer("https://notenverwaltung.hs-offenburg.de/qispos/rds?state=user&type=0")
.get()
val gradesListLink = gradesNextHtml.selectFirst("li.treelist > ul > li").selectFirst("a").attr("abs:href")
val gradesListLink = gradesNextHtml.selectFirst("li.treelist > ul > li")!!.selectFirst("a")!!.attr("abs:href")
// get the grades list
val gradesListHtml = Jsoup.connect(gradesListLink)

View File

@ -84,7 +84,7 @@ class TCoRAPIController {
fun getSubjectListAsync(courseName: String, week: Int): Deferred<ArrayList<String>> {
val url = URL("$tcorBaseURL/subjectList?course=$courseName&week=$week")
return GlobalScope.async {
return CoroutineScope(Dispatchers.IO).async {
Gson().fromJson(url.readText(), ArrayList<String>()::class.java)
}
}

View File

@ -64,7 +64,7 @@ class CacheController(private val context: Context) {
// if a) it's monday and the last cache update was on sunday or b) the cache is older than 24hr, update blocking
if ((currentDay == Calendar.MONDAY && cal.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) || (currentTime - mensaCacheTime) > 86400) {
Log.i(className, "Update mensa blocking")
GlobalScope.launch(Dispatchers.Default) { updateMensaMenu(context).join() }
CoroutineScope(Dispatchers.Default).launch { updateMensaMenu(context).join() }
}
// check if we need to update the timetable before displaying it
@ -74,7 +74,7 @@ class CacheController(private val context: Context) {
if ((currentDay == Calendar.MONDAY && cal.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) || (currentTime - timetableCacheTime) > 86400) {
Log.i(className, "Updating timetable after sunday!")
GlobalScope.launch(Dispatchers.Default) {
CoroutineScope(Dispatchers.Default).launch {
val threads = listOf(
updateTimetable(Preferences.course.courseName, 0, context),
updateTimetable(Preferences.course.courseName, 1, context)
@ -110,7 +110,7 @@ class CacheController(private val context: Context) {
val file = File(context.filesDir, "courses.json")
var courseListUp = CoursesList()
return GlobalScope.launch(Dispatchers.IO) {
return CoroutineScope(Dispatchers.IO).launch {
try {
courseListUp = TCoRAPIController.getCourseListNEW()
} catch (ex: Exception) {
@ -133,7 +133,7 @@ class CacheController(private val context: Context) {
fun updateMensaMenu(context: Context): Job {
val file = File(context.filesDir, "mensa.json")
return GlobalScope.launch(Dispatchers.IO) {
return CoroutineScope(Dispatchers.IO).launch {
try {
mensaMenu = TCoRAPIController.getMensaMenu()
} catch (ex: Exception) {
@ -157,7 +157,7 @@ class CacheController(private val context: Context) {
var timetable = TimetableWeek()
// try to update timetable from tcor, async
return GlobalScope.launch(Dispatchers.IO) {
return CoroutineScope(Dispatchers.IO).launch {
try {
timetable = TCoRAPIController.getTimetable(courseName, week)
} catch (ex: Exception) {
@ -184,7 +184,7 @@ class CacheController(private val context: Context) {
fun updateAdditionalLessons(context: Context): Job {
val fileLessons = File(context.filesDir, "additional_lessons.json")
return GlobalScope.launch(Dispatchers.IO) {
return CoroutineScope(Dispatchers.IO).launch {
TimetableController.subjectMap.forEach { (courseName, subjects) ->
// update all subjects for a course
subjects.forEach {subject ->
@ -209,7 +209,7 @@ class CacheController(private val context: Context) {
val file = File(context.filesDir, "grades_encrypted")
val parser = QISPOSParser(context)
return GlobalScope.launch(Dispatchers.IO) {
return CoroutineScope(Dispatchers.IO).launch {
if (parser.checkQISPOSStatus() == 200) {
// save cache file and update time
saveEncrypted(context, file, Gson().toJson(parser.parseGrades()))

View File

@ -24,12 +24,14 @@ package org.mosad.seil0.projectlaogai.fragments
import android.graphics.Rect
import android.os.Bundle
import android.util.Log
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.lifecycle.lifecycleScope
import kotlinx.coroutines.*
import org.mosad.seil0.projectlaogai.R
import org.mosad.seil0.projectlaogai.controller.QISPOSParser
@ -62,16 +64,16 @@ class GradesFragment : Fragment() {
binding.refreshLayoutGrades.setProgressBackgroundColorSchemeColor(Preferences.themeSecondary)
initActions()
parser = QISPOSParser(context!!)// init the parser
parser = QISPOSParser(requireContext())// init the parser
if (checkCredentials()) {
GlobalScope.launch(Dispatchers.Default) {
lifecycleScope.launch(Dispatchers.Default) {
// if the cache is older than 24hr, update blocking
val currentTime = System.currentTimeMillis() / 1000
withContext(Dispatchers.Main) {
if ((currentTime - Preferences.gradesCacheTime) > 86400 && checkQisposStatus()) {
binding.refreshLayoutGrades.isRefreshing = true
CacheController.updateGrades(context!!).join()
CacheController.updateGrades(requireContext()).join()
}
}
@ -83,13 +85,13 @@ class GradesFragment : Fragment() {
/**
* initialize the actions
*/
private fun initActions() = GlobalScope.launch(Dispatchers.Default) {
private fun initActions() = lifecycleScope.launch(Dispatchers.Default) {
binding.refreshLayoutGrades.setOnRefreshListener {
binding.linLayoutGrades.removeAllViews() // clear layout
// TODO add loading textView
GlobalScope.launch(Dispatchers.Default) {
CacheController.updateGrades(context!!).join()
lifecycleScope.launch(Dispatchers.Default) {
CacheController.updateGrades(requireContext()).join()
addGrades()
}
}
@ -99,12 +101,12 @@ class GradesFragment : Fragment() {
* check if the credentials are set, if not show a login dialog
*/
private fun checkCredentials(): Boolean {
val credentials = EncryptedPreferences.readCredentials(context!!)
val credentials = EncryptedPreferences.readCredentials(requireContext())
var credentialsPresent = false
// if there is no password set, show the login dialog
if (credentials.first.isEmpty() || credentials.second.isEmpty()) {
LoginDialog(this.context!!)
LoginDialog(this.requireContext())
.positiveButton {
EncryptedPreferences.saveCredentials(email, password, context)
addGrades()
@ -153,9 +155,9 @@ class GradesFragment : Fragment() {
* add the grades to the layout, async
* TODO this is slow as hell
*/
private fun addGrades() = GlobalScope.launch(Dispatchers.Default) {
private fun addGrades() = lifecycleScope.launch(Dispatchers.Default) {
val addGradesTime = measureTimeMillis {
val grades = CacheController(context!!).readGrades()
val grades = CacheController(requireContext()).readGrades()
withContext(Dispatchers.Main) {
binding.linLayoutGrades.removeAllViews() // clear layout
@ -165,7 +167,7 @@ class GradesFragment : Fragment() {
// for each semester add a new card
grades.forEach { semester ->
val usedSubjects = ArrayList<String>()
val semesterCard = DayCardView(context!!)
val semesterCard = DayCardView(requireContext())
semesterCard.setDayHeading(semester.key)
// for each subject add a new linLayout
@ -220,7 +222,7 @@ class GradesFragment : Fragment() {
}
}
println("added grades in $addGradesTime ms")
Log.i(javaClass.name, "added grades in $addGradesTime ms")
}
}

View File

@ -30,6 +30,7 @@ import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.*
import org.mosad.seil0.projectlaogai.R
import org.mosad.seil0.projectlaogai.controller.cache.CacheController.Companion.mensaMenu
@ -68,22 +69,22 @@ class HomeFragment : Fragment() {
/**
* add the current mensa meal to the home screens
*/
private fun addMensaMenu() = GlobalScope.launch(Dispatchers.Default) {
private fun addMensaMenu() = lifecycleScope.launch(Dispatchers.Default) {
var dayMeals: ArrayList<Meal>
val cal = Calendar.getInstance()
val mensaCardView = DayCardView(context!!)
val mensaCardView = DayCardView(requireContext())
withContext(Dispatchers.Main) {
if (isAdded) {
if (cal.get(Calendar.HOUR_OF_DAY) < 15) {
dayMeals = mensaMenu.currentWeek.days[NotRetardedCalendar.getDayOfWeekIndex()].meals
mensaCardView.setDayHeading(activity!!.resources.getString(R.string.today_date, formatter.format(cal.time)))
mensaCardView.setDayHeading(getString(R.string.today_date, formatter.format(cal.time)))
} else {
dayMeals = mensaMenu.currentWeek.days[NotRetardedCalendar.getTomorrowWeekIndex()].meals
cal.add(Calendar.DATE, 1)
mensaCardView.setDayHeading(activity!!.resources.getString(R.string.tomorrow_date, formatter.format(cal.time)))
mensaCardView.setDayHeading(getString(R.string.tomorrow_date, formatter.format(cal.time)))
}
if (dayMeals.size >= 2) {
@ -118,20 +119,15 @@ class HomeFragment : Fragment() {
/**
* add the current timetable to the home screen
*/
private fun addTimeTable() = GlobalScope.launch(Dispatchers.Default) {
withContext(Dispatchers.Main) {
if (isAdded && TimetableController.timetable.isNotEmpty()) {
try {
val dayCardView = findNextDay(NotRetardedCalendar.getDayOfWeekIndex())
binding.linLayoutHome.addView(dayCardView)
} catch (ex: Exception) {
Log.e(className, "could not load timetable", ex) // TODO send feedback
}
private fun addTimeTable() = lifecycleScope.launch(Dispatchers.Main) {
if (isAdded && TimetableController.timetable.isNotEmpty()) {
try {
val dayCardView = findNextDay(NotRetardedCalendar.getDayOfWeekIndex())
binding.linLayoutHome.addView(dayCardView)
} catch (ex: Exception) {
Log.e(className, "could not load timetable", ex) // TODO send feedback
}
}
}
/**
@ -142,7 +138,7 @@ class HomeFragment : Fragment() {
* @return a DayCardView with all lessons added
*/
private fun findNextDay(startDayIndex: Int): DayCardView {
val dayCardView = DayCardView(context!!)
val dayCardView = DayCardView(requireContext())
var dayTimetable: TimetableDay? = null
var dayIndexSearch = startDayIndex
var weekIndexSearch = 0

View File

@ -27,8 +27,8 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.mosad.seil0.projectlaogai.R
@ -62,7 +62,7 @@ class MensaFragment : Fragment() {
initActions() // init actions
GlobalScope.launch(Dispatchers.Default) {
lifecycleScope.launch(Dispatchers.Default) {
val dayCurrent = if(NotRetardedCalendar.getDayOfWeekIndex() == 6) 0 else NotRetardedCalendar.getDayOfWeekIndex()
// add the current and next week
@ -71,7 +71,7 @@ class MensaFragment : Fragment() {
// show a info if there are no more menus
if (binding.linLayoutMensa.childCount == 0) {
val txtViewInfo = TextViewInfo(context!!).set {
val txtViewInfo = TextViewInfo(requireContext()).set {
txt = resources.getString(R.string.no_more_meals)
}
withContext(Dispatchers.Main) { binding.linLayoutMensa.addView(txtViewInfo) }
@ -84,13 +84,13 @@ class MensaFragment : Fragment() {
* @param menusWeek menu of type MensaWeek you want to add
* @param dayStart the first day of the week to add
*/
private fun addWeek(menusWeek: MensaWeek, dayStart: Int) = GlobalScope.launch(Dispatchers.Default) {
private fun addWeek(menusWeek: MensaWeek, dayStart: Int) = lifecycleScope.launch(Dispatchers.Default) {
withContext(Dispatchers.Main) {
// only add the days dayStart to Fri since the mensa is closed on Sat/Sun
for (dayIndex in dayStart..4) {
var helpMeal = MealLinearLayout(context)
val dayCardView = DayCardView(context!!)
val dayCardView = DayCardView(requireContext())
if(menusWeek.days[dayIndex].meals.isNotEmpty())
dayCardView.setDayHeading(menusWeek.days[dayIndex].meals[0].day)
@ -127,8 +127,8 @@ class MensaFragment : Fragment() {
/**
* refresh the mensa cache and update the mensa screen
*/
private fun updateMensaScreen() = GlobalScope.launch(Dispatchers.Default) {
CacheController.updateMensaMenu(context!!).join() // blocking since we want the new data
private fun updateMensaScreen() = lifecycleScope.launch(Dispatchers.Default) {
CacheController.updateMensaMenu(requireContext()).join() // blocking since we want the new data
withContext(Dispatchers.Main) {
// remove all menus from the layout
@ -145,7 +145,7 @@ class MensaFragment : Fragment() {
// show a info if there are no more menus
if (binding.linLayoutMensa.childCount == 0) {
val txtViewInfo = TextViewInfo(context!!).set {
val txtViewInfo = TextViewInfo(requireContext()).set {
txt = resources.getString(R.string.no_more_meals)
}
binding.linLayoutMensa.addView(txtViewInfo)

View File

@ -22,21 +22,24 @@
package org.mosad.seil0.projectlaogai.fragments
//import com.afollestad.aesthetic.Aesthetic
import android.os.Bundle
import android.util.TypedValue
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import com.afollestad.aesthetic.Aesthetic
import androidx.lifecycle.lifecycleScope
import com.afollestad.materialdialogs.MaterialDialog
import com.afollestad.materialdialogs.WhichButton
import com.afollestad.materialdialogs.actions.getActionButton
import com.afollestad.materialdialogs.color.colorChooser
import com.afollestad.materialdialogs.list.listItemsMultiChoice
import com.afollestad.materialdialogs.list.listItemsSingleChoice
import de.psdev.licensesdialog.LicensesDialog
import kotlinx.coroutines.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.joinAll
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.mosad.seil0.projectlaogai.BuildConfig
import org.mosad.seil0.projectlaogai.R
import org.mosad.seil0.projectlaogai.controller.GradesController
@ -50,7 +53,6 @@ import org.mosad.seil0.projectlaogai.uicomponents.dialogs.CourseSelectionDialog
import org.mosad.seil0.projectlaogai.uicomponents.dialogs.LoadingDialog
import org.mosad.seil0.projectlaogai.uicomponents.dialogs.LoginDialog
import org.mosad.seil0.projectlaogai.util.DataTypes
import java.util.*
/**
* The settings controller class
@ -86,20 +88,20 @@ class SettingsFragment : Fragment() {
binding.switchBuffet.isChecked = Preferences.showBuffet // init switch
val outValue = TypedValue()
activity!!.theme.resolveAttribute(R.attr.themeName, outValue, true)
requireActivity().theme.resolveAttribute(R.attr.themeName, outValue, true)
when(outValue.string) {
"light" -> {
binding.switchBuffet.setTextColor(activity!!.resources.getColor(R.color.textPrimaryLight, activity!!.theme))
binding.switchBuffet.setTextColor(requireActivity().resources.getColor(R.color.textPrimaryLight, requireActivity().theme))
selectedTheme = DataTypes.Theme.Light
selectedTheme.string = resources.getString(R.string.themeLight)
}
"dark" -> {
binding.switchBuffet.setTextColor(activity!!.resources.getColor(R.color.textPrimaryDark, activity!!.theme))
binding.switchBuffet.setTextColor(requireActivity().resources.getColor(R.color.textPrimaryDark, requireActivity().theme))
selectedTheme = DataTypes.Theme.Dark
selectedTheme.string = resources.getString(R.string.themeDark)
}
"black" -> {
binding.switchBuffet.setTextColor(activity!!.resources.getColor(R.color.textPrimaryDark, activity!!.theme))
binding.switchBuffet.setTextColor(requireActivity().resources.getColor(R.color.textPrimaryDark, requireActivity().theme))
selectedTheme = DataTypes.Theme.Black
selectedTheme.string = resources.getString(R.string.themeBlack)
}
@ -113,7 +115,7 @@ class SettingsFragment : Fragment() {
private fun initActions() {
binding.linLayoutUser.setOnClickListener {
// open a new dialog
LoginDialog(context!!)
LoginDialog(requireContext())
.positiveButton {
EncryptedPreferences.saveCredentials(email, password, context)
}
@ -129,13 +131,13 @@ class SettingsFragment : Fragment() {
}
binding.linLayoutCourse.setOnClickListener {
CourseSelectionDialog(context!!).show {
CourseSelectionDialog(requireContext()).show {
list = coursesList.map { it.courseName }
listItems {
val loadingDialog = LoadingDialog(context)
loadingDialog.show()
GlobalScope.launch(Dispatchers.Default) {
lifecycleScope.launch(Dispatchers.Default) {
Preferences.saveCourse(context, coursesList[selectedIndex]) // save the course
// update current & next weeks timetable
@ -164,7 +166,7 @@ class SettingsFragment : Fragment() {
}
}
MaterialDialog(context!!).show {
MaterialDialog(requireContext()).show {
title(R.string.manage_lessons)
positiveButton(R.string.delete)
negativeButton(R.string.cancel)
@ -182,7 +184,7 @@ class SettingsFragment : Fragment() {
binding.linLayoutAbout.setOnClickListener {
// open a new info dialog
MaterialDialog(context!!)
MaterialDialog(requireContext())
.title(R.string.about_dialog_heading)
.message(R.string.about_dialog_text)
.show()
@ -191,7 +193,7 @@ class SettingsFragment : Fragment() {
binding.linLayoutLicence.setOnClickListener {
// do the theme magic, as the lib's theme support is broken
val outValue = TypedValue()
context!!.theme.resolveAttribute(R.attr.themeName, outValue, true)
requireContext().theme.resolveAttribute(R.attr.themeName, outValue, true)
val dialogCss = when (outValue.string) {
"light" -> R.string.license_dialog_style_light
@ -204,7 +206,7 @@ class SettingsFragment : Fragment() {
}
// open a new license dialog
LicensesDialog.Builder(context!!)
LicensesDialog.Builder(requireContext())
.setNotices(R.raw.notices)
.setTitle(R.string.licenses)
.setIncludeOwnLicense(true)
@ -214,67 +216,67 @@ class SettingsFragment : Fragment() {
.show()
}
binding.linLayoutTheme.setOnClickListener {
val themes = listOf(
resources.getString(R.string.themeLight),
resources.getString(R.string.themeDark),
resources.getString(R.string.themeBlack)
)
// binding.linLayoutTheme.setOnClickListener {
// val themes = listOf(
// resources.getString(R.string.themeLight),
// resources.getString(R.string.themeDark),
// resources.getString(R.string.themeBlack)
// )
//
// MaterialDialog(requireContext()).show {
// title(R.string.theme)
// listItemsSingleChoice(items = themes, initialSelection = selectedTheme.ordinal) { _, index, _ ->
// Aesthetic.config {
// when (index) {
// 0 -> activityTheme(R.style.AppTheme_Light)
// 1 -> activityTheme(R.style.AppTheme_Dark)
// 2 -> activityTheme(R.style.AppTheme_Black)
// else -> activityTheme(R.style.AppTheme_Light)
// }
// apply()
// }
// }
// }
// }
MaterialDialog(context!!).show {
title(R.string.theme)
listItemsSingleChoice(items = themes, initialSelection = selectedTheme.ordinal) { _, index, _ ->
Aesthetic.config {
when (index) {
0 -> activityTheme(R.style.AppTheme_Light)
1 -> activityTheme(R.style.AppTheme_Dark)
2 -> activityTheme(R.style.AppTheme_Black)
else -> activityTheme(R.style.AppTheme_Light)
}
apply()
}
}
}
}
// binding.linLayoutPrimaryColor.setOnClickListener {
// // open a new color chooser dialog
// MaterialDialog(requireContext())
// .colorChooser(DataTypes().primaryColors, allowCustomArgb = true, initialSelection = Preferences.colorPrimary) { _, color ->
// binding.viewPrimaryColor.setBackgroundColor(color)
// Aesthetic.config {
// colorPrimary(color)
// colorPrimaryDark(color)
// apply()
// }
// Preferences.saveColorPrimary(requireContext(), color)
// }
// .show {
// title(R.string.primary_color)
// positiveButton(R.string.select)
// getActionButton(WhichButton.POSITIVE).updateTextColor(Preferences.colorAccent)
// }
//
// }
binding.linLayoutPrimaryColor.setOnClickListener {
// open a new color chooser dialog
MaterialDialog(context!!)
.colorChooser(DataTypes().primaryColors, allowCustomArgb = true, initialSelection = Preferences.colorPrimary) { _, color ->
binding.viewPrimaryColor.setBackgroundColor(color)
Aesthetic.config {
colorPrimary(color)
colorPrimaryDark(color)
apply()
}
Preferences.saveColorPrimary(context!!, color)
}
.show {
title(R.string.primary_color)
positiveButton(R.string.select)
getActionButton(WhichButton.POSITIVE).updateTextColor(Preferences.colorAccent)
}
}
binding.linLayoutAccentColor.setOnClickListener {
// open a new color chooser dialog
MaterialDialog(context!!)
.colorChooser(DataTypes().accentColors, allowCustomArgb = true, initialSelection = Preferences.colorAccent) { _, color ->
binding.viewAccentColor.setBackgroundColor(color)
Aesthetic.config {
colorAccent(color)
apply()
}
Preferences.saveColorAccent(context!!, color)
}
.show{
title(R.string.accent_color)
positiveButton(R.string.select)
getActionButton(WhichButton.POSITIVE).updateTextColor(Preferences.colorAccent)
}
}
// binding.linLayoutAccentColor.setOnClickListener {
// // open a new color chooser dialog
// MaterialDialog(requireContext())
// .colorChooser(DataTypes().accentColors, allowCustomArgb = true, initialSelection = Preferences.colorAccent) { _, color ->
// binding.viewAccentColor.setBackgroundColor(color)
// Aesthetic.config {
// colorAccent(color)
// apply()
// }
//
// Preferences.saveColorAccent(requireContext(), color)
// }
// .show{
// title(R.string.accent_color)
// positiveButton(R.string.select)
// getActionButton(WhichButton.POSITIVE).updateTextColor(Preferences.colorAccent)
// }
// }
binding.linLayoutGradesSync.setOnClickListener {
val items = resources.getStringArray(R.array.syncInterval).toList()
@ -286,7 +288,7 @@ class SettingsFragment : Fragment() {
else -> 0
}
MaterialDialog(context!!)
MaterialDialog(requireContext())
.title(R.string.grades_sync)
.listItemsSingleChoice(items = items, initialSelection = initial) { _, index, _ ->
val interval = when (index) {
@ -297,8 +299,8 @@ class SettingsFragment : Fragment() {
else -> 0
}
Preferences.saveGradesSync(context!!, interval)
GradesController.updateBackgroundSync(context!!)
Preferences.saveGradesSync(requireContext(), interval)
GradesController.updateBackgroundSync(requireContext())
binding.textGradesSyncDesc.text = if (Preferences.gradesSyncInterval == 0) {
resources.getString(R.string.grades_sync_desc_never)
@ -309,7 +311,7 @@ class SettingsFragment : Fragment() {
}
binding.switchBuffet.setOnClickListener {
Preferences.saveShowBuffet(context!!, binding.switchBuffet.isChecked)
Preferences.saveShowBuffet(requireContext(), binding.switchBuffet.isChecked)
}
}

View File

@ -27,6 +27,7 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.*
import org.mosad.seil0.projectlaogai.R
import org.mosad.seil0.projectlaogai.controller.cache.TimetableController
@ -61,7 +62,7 @@ class TimetableFragment : Fragment() {
if (timetable.size > 1 && timetable[0].days.isNotEmpty() && timetable[1].days.isNotEmpty()) {
initTimetable()
} else {
val txtViewInfo = TextViewInfo(context!!).set {
val txtViewInfo = TextViewInfo(requireContext()).set {
txt = resources.getString(R.string.timetable_generic_error)
}.showImage()
binding.linLayoutTimetable.addView(txtViewInfo)
@ -74,13 +75,13 @@ class TimetableFragment : Fragment() {
private fun initActions() {
binding.refreshLayoutTimetable.setOnRefreshListener {
runBlocking { TimetableController.update(context!!).joinAll() }
runBlocking { TimetableController.update(requireContext()).joinAll() }
reloadTimetableUI()
}
// show the AddLessonDialog if the ftaBtn is clicked
binding.faBtnAddSubject.setOnClickListener {
AddSubjectDialog(context!!)
AddSubjectDialog(requireContext())
.positiveButton {
TimetableController.addSubject(selectedCourse, selectedSubject, context)
runBlocking { reloadTimetableUI() }
@ -101,16 +102,16 @@ class TimetableFragment : Fragment() {
/**
* add the current and next weeks lessons
*/
private fun initTimetable() = GlobalScope.launch(Dispatchers.Default) {
private fun initTimetable() = lifecycleScope.launch(Dispatchers.Default) {
val currentDayIndex = NotRetardedCalendar.getDayOfWeekIndex()
addTimetableWeek(currentDayIndex, 5, 0).join() // add current week
addTimetableWeek(0, currentDayIndex - 1, 1) // add next week
}
private fun addTimetableWeek(dayBegin: Int, dayEnd: Int, week: Int) = GlobalScope.launch(Dispatchers.Main) {
private fun addTimetableWeek(dayBegin: Int, dayEnd: Int, week: Int) = lifecycleScope.launch(Dispatchers.Main) {
for (dayIndex in dayBegin..dayEnd) {
val dayCardView = DayCardView(context!!)
val dayCardView = DayCardView(requireContext())
// some wired calendar magic, calculate the correct date to be shown
// ((timetable week - current week * 7) + (dayIndex - dayIndex of current week)
@ -128,7 +129,7 @@ class TimetableFragment : Fragment() {
/**
* clear linLayout_Timetable, add the updated timetable
*/
private fun reloadTimetableUI() = GlobalScope.launch(Dispatchers.Default) {
private fun reloadTimetableUI() = lifecycleScope.launch(Dispatchers.Default) {
withContext(Dispatchers.Main) {
// remove all lessons from the layout
binding.linLayoutTimetable.removeAllViews()

View File

@ -41,7 +41,6 @@ class TextViewInfo(context: Context?): AppCompatTextView(context!!) {
init {
params.setMargins(0,200,0,0)
}
fun set(func: TextViewInfo.() -> Unit): TextViewInfo = apply {

View File

@ -1,13 +1,13 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
ext.kotlin_version = '1.4.20'
ext.kotlin_version = '1.7.20'
repositories {
google()
jcenter()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:4.1.1'
classpath 'com.android.tools.build:gradle:7.3.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong
@ -18,7 +18,7 @@ buildscript {
allprojects {
repositories {
google()
jcenter()
mavenCentral()
}
}