diff --git a/app/build.gradle b/app/build.gradle index 5d88468..666963f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,7 +1,5 @@ apply plugin: 'com.android.application' - apply plugin: 'kotlin-android' - apply plugin: 'kotlin-android-extensions' android { @@ -12,8 +10,8 @@ android { applicationId "org.mosad.seil0.projectlaogai" minSdkVersion 23 targetSdkVersion 29 - versionCode 14 - versionName "0.5.0" + versionCode 15 + versionName "0.5.190" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" resValue "string", "build_time", buildTime() setProperty("archivesBaseName", "projectlaogai-$versionName") @@ -49,12 +47,12 @@ android { dependencies { implementation fileTree(include: ['*.jar'], dir: 'libs') implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" - implementation 'org.jetbrains.anko:anko-commons:0.10.8' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.3' implementation 'androidx.appcompat:appcompat:1.1.0' implementation 'androidx.legacy:legacy-support-v4:1.0.0' - implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta3' + implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta4' implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.0.0' - implementation 'com.google.android.material:material:1.0.0' + implementation 'com.google.android.material:material:1.1.0' implementation 'com.google.code.gson:gson:2.8.6' implementation 'com.afollestad:aesthetic:1.0.0-beta05' implementation 'com.afollestad.material-dialogs:core:3.1.1' diff --git a/app/src/main/java/org/mosad/seil0/projectlaogai/MainActivity.kt b/app/src/main/java/org/mosad/seil0/projectlaogai/MainActivity.kt index af33d57..c8a3b83 100644 --- a/app/src/main/java/org/mosad/seil0/projectlaogai/MainActivity.kt +++ b/app/src/main/java/org/mosad/seil0/projectlaogai/MainActivity.kt @@ -52,7 +52,6 @@ import kotlin.system.measureTimeMillis /** * TODO save the current fragment to show it when the app is restarted - * TODO since anko is dead, we should use coroutines */ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener { diff --git a/app/src/main/java/org/mosad/seil0/projectlaogai/controller/CacheController.kt b/app/src/main/java/org/mosad/seil0/projectlaogai/controller/CacheController.kt index 7367a4b..3c97140 100644 --- a/app/src/main/java/org/mosad/seil0/projectlaogai/controller/CacheController.kt +++ b/app/src/main/java/org/mosad/seil0/projectlaogai/controller/CacheController.kt @@ -27,6 +27,10 @@ import com.google.gson.Gson import com.google.gson.GsonBuilder import com.google.gson.JsonParser import com.google.gson.reflect.TypeToken +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.joinAll +import kotlinx.coroutines.launch import org.mosad.seil0.projectlaogai.controller.PreferencesController.Companion.cCourse import org.mosad.seil0.projectlaogai.hsoparser.Course import org.mosad.seil0.projectlaogai.hsoparser.MensaMenu @@ -53,7 +57,7 @@ class CacheController(cont: 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 - mensaMenu.meta.updateTime) > 86400) { println("update mensa blocking") - TCoRAPIController.getMensa(context).get() + GlobalScope.launch(Dispatchers.Default) { TCoRAPIController.getMensa(context).join() } } // check if we need to update the timetables before displaying them @@ -61,23 +65,29 @@ class CacheController(cont: Context) { cal.time = Date(timetables[0].meta.updateTime * 1000) // if a) it`s monday and the last cache update was not on a sunday or b) the cache is older than 24hr, update blocking - if((currentDay == Calendar.MONDAY && cal.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) || (currentTime - timetables[0].meta.updateTime) > 86400) { + if ((currentDay == Calendar.MONDAY && cal.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) || (currentTime - timetables[0].meta.updateTime) > 86400) { println("updating timetable after sunday!") - val jobA = TCoRAPIController.getTimetable(cCourse.courseName, 0, context) - val jobB = TCoRAPIController.getTimetable(cCourse.courseName, 1, context) - jobA.get() - jobB.get() + GlobalScope.launch(Dispatchers.Default) { + val threads = listOf( + TCoRAPIController.getTimetable(cCourse.courseName, 0, context), + TCoRAPIController.getTimetable(cCourse.courseName, 1, context) + ) + threads.joinAll() + } + + TCoRAPIController.getTimetable(cCourse.courseName, 0, context) + TCoRAPIController.getTimetable(cCourse.courseName, 1, context) } // check if an update is necessary, not blocking - if(currentTime - PreferencesController.coursesCacheTime > 86400) + if (currentTime - PreferencesController.coursesCacheTime > 86400) TCoRAPIController.getCoursesList(context) - if(currentTime - PreferencesController.mensaCacheTime > 10800) + if (currentTime - PreferencesController.mensaCacheTime > 10800) TCoRAPIController.getMensa(context) - if(currentTime - PreferencesController.timetableCacheTime > 10800) { + if (currentTime - PreferencesController.timetableCacheTime > 10800) { TCoRAPIController.getTimetable(cCourse.courseName, 0, context) TCoRAPIController.getTimetable(cCourse.courseName, 1, context) } @@ -99,13 +109,16 @@ class CacheController(cont: Context) { // make sure the file exists if (!file.exists()) - TCoRAPIController.getCoursesList(context).get() + GlobalScope.launch(Dispatchers.Default) { TCoRAPIController.getCoursesList(context).join() } val fileReader = FileReader(file) val bufferedReader = BufferedReader(fileReader) val coursesObject = JsonParser.parseString(bufferedReader.readLine()).asJsonObject - coursesList = Gson().fromJson(coursesObject.getAsJsonArray("courses"), object : TypeToken>() {}.type) + coursesList = Gson().fromJson( + coursesObject.getAsJsonArray("courses"), + object : TypeToken>() {}.type + ) } /** @@ -116,9 +129,8 @@ class CacheController(cont: Context) { val file = File(context.filesDir, "mensa.json") // make sure the file exists - if (!file.exists()) { - TCoRAPIController.getMensa(context).get() - } + if (!file.exists()) + GlobalScope.launch(Dispatchers.Default) { TCoRAPIController.getMensa(context).join() } val fileReader = FileReader(file) val bufferedReader = BufferedReader(fileReader) @@ -136,8 +148,11 @@ class CacheController(cont: Context) { val file = File(context.filesDir, "timetable-$courseName-$week.json") // make sure the file exists - if (!file.exists()) - TCoRAPIController.getTimetable(courseName, week, context).get() + if (!file.exists()) { + GlobalScope.launch(Dispatchers.Default) { + TCoRAPIController.getTimetable(courseName, week, context).join() + } + } val fileReader = FileReader(file) val bufferedReader = BufferedReader(fileReader) diff --git a/app/src/main/java/org/mosad/seil0/projectlaogai/controller/TCoRAPIController.kt b/app/src/main/java/org/mosad/seil0/projectlaogai/controller/TCoRAPIController.kt index 250ee49..9d90148 100644 --- a/app/src/main/java/org/mosad/seil0/projectlaogai/controller/TCoRAPIController.kt +++ b/app/src/main/java/org/mosad/seil0/projectlaogai/controller/TCoRAPIController.kt @@ -24,7 +24,7 @@ package org.mosad.seil0.projectlaogai.controller import android.content.Context import android.util.Log -import org.jetbrains.anko.doAsync +import kotlinx.coroutines.* import org.json.JSONObject import org.mosad.seil0.projectlaogai.controller.PreferencesController.Companion.coursesCacheTime import org.mosad.seil0.projectlaogai.controller.PreferencesController.Companion.mensaCacheTime @@ -44,7 +44,7 @@ class TCoRAPIController { /** * get the json object from tcor api and write it as file (cache) */ - fun getCoursesList(context: Context) = doAsync { + fun getCoursesList(context: Context) = GlobalScope.launch { try { val url = URL("$tcorBaseURL/courseList") val file = File(context.filesDir, "courses.json") @@ -53,9 +53,11 @@ class TCoRAPIController { val coursesObject = JSONObject(url.readText()) //JSONObject(inReader.readLine()) // write the json object to a file - val writer = BufferedWriter(FileWriter(file)) - writer.write(coursesObject.toString()) - writer.close() + withContext(Dispatchers.IO) { + val writer = BufferedWriter(FileWriter(file)) + writer.write(coursesObject.toString()) + writer.close() + } // update cache time coursesCacheTime = System.currentTimeMillis() / 1000 @@ -69,7 +71,7 @@ class TCoRAPIController { /** * get the json object from tcor api and write it as file (cache) */ - fun getMensa(context: Context) = doAsync { + fun getMensa(context: Context) = GlobalScope.launch { try { val url = URL("$tcorBaseURL/mensamenu") val file = File(context.filesDir, "mensa.json") @@ -78,9 +80,11 @@ class TCoRAPIController { val mensaObject = JSONObject(url.readText()) //JSONObject(inReader.readLine()) // write the json object to a file - val writer = BufferedWriter(FileWriter(file)) - writer.write(mensaObject.toString()) - writer.close() + withContext(Dispatchers.IO) { + val writer = BufferedWriter(FileWriter(file)) + writer.write(mensaObject.toString()) + writer.close() + } // update cache time mensaCacheTime = System.currentTimeMillis() / 1000 @@ -94,18 +98,20 @@ class TCoRAPIController { /** * get the json object from tcor api and write it as file (cache) */ - fun getTimetable(courseName: String, week: Int, context: Context) = doAsync { + fun getTimetable(courseName: String, week: Int, context: Context) = GlobalScope.launch { try { val url = URL("$tcorBaseURL/timetable?courseName=$courseName&week=$week") val file = File(context.filesDir, "timetable-$courseName-$week.json") // read data from the API - val mensaObject = JSONObject(url.readText()) //JSONObject(inReader.readLine()) + val timetableObject = JSONObject(url.readText()) //JSONObject(inReader.readLine()) // write the json object to a file - val writer = BufferedWriter(FileWriter(file)) - writer.write(mensaObject.toString()) - writer.close() + withContext(Dispatchers.IO) { + val writer = BufferedWriter(FileWriter(file)) + writer.write(timetableObject.toString()) + writer.close() + } // update cache time timetableCacheTime = System.currentTimeMillis() / 1000 diff --git a/app/src/main/java/org/mosad/seil0/projectlaogai/fragments/HomeFragment.kt b/app/src/main/java/org/mosad/seil0/projectlaogai/fragments/HomeFragment.kt index 40f4b5a..e58b8de 100644 --- a/app/src/main/java/org/mosad/seil0/projectlaogai/fragments/HomeFragment.kt +++ b/app/src/main/java/org/mosad/seil0/projectlaogai/fragments/HomeFragment.kt @@ -31,8 +31,10 @@ import android.view.ViewGroup import android.widget.TextView import androidx.fragment.app.Fragment import kotlinx.android.synthetic.main.fragment_home.* -import org.jetbrains.anko.doAsync -import org.jetbrains.anko.uiThread +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import org.mosad.seil0.projectlaogai.R import org.mosad.seil0.projectlaogai.controller.CacheController.Companion.mensaMenu import org.mosad.seil0.projectlaogai.controller.CacheController.Companion.timetables @@ -54,11 +56,10 @@ class HomeFragment : Fragment() { private val formatter = SimpleDateFormat("E dd.MM", Locale.getDefault()) override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { - val view: View = inflater.inflate(R.layout.fragment_home, container, false) - addMensaMenu().get() - addTimeTable().get() + addMensaMenu() + addTimeTable() // Inflate the layout for this fragment return view @@ -67,13 +68,13 @@ class HomeFragment : Fragment() { /** * add the current mensa meal to the home screens */ - private fun addMensaMenu() = doAsync { + private fun addMensaMenu() = GlobalScope.launch(Dispatchers.Default) { var dayMeals: ArrayList val cal = Calendar.getInstance() val mensaCardView = DayCardView(context!!) - uiThread { + withContext(Dispatchers.Main) { if (isAdded) { if (cal.get(Calendar.HOUR_OF_DAY) < 15) { @@ -117,9 +118,9 @@ class HomeFragment : Fragment() { /** * add the current timetable to the home screen */ - private fun addTimeTable() = doAsync { + private fun addTimeTable() = GlobalScope.launch(Dispatchers.Default) { - uiThread { + withContext(Dispatchers.Main) { if (isAdded && timetables.isNotEmpty()) { try { @@ -140,7 +141,7 @@ class HomeFragment : Fragment() { * @param startDayIndex the day index you want to start searching * @return a DayCardView with all lessons added */ - private fun findNextDay(startDayIndex: Int) : DayCardView { + private fun findNextDay(startDayIndex: Int): DayCardView { val dayCardView = DayCardView(context!!) var dayTimetable: TimetableDay? = null var dayIndexSearch = startDayIndex @@ -151,7 +152,7 @@ class HomeFragment : Fragment() { dayTimetable = timetables[weekIndexSearch].timetable.days[dayIndex] // some wired calendar magic, calculate the correct date to be shown ((timetable week - current week * 7) + (dayIndex - dayIndex of current week) - val daysToAdd =(timetables[weekIndexSearch].meta.weekNumberYear - NotRetardedCalendar.getWeekOfYear()) * 7 + (dayIndex - NotRetardedCalendar.getDayOfWeekIndex()) + val daysToAdd = (timetables[weekIndexSearch].meta.weekNumberYear - NotRetardedCalendar.getWeekOfYear()) * 7 + (dayIndex - NotRetardedCalendar.getDayOfWeekIndex()) dayCardView.addTimetableDay(dayTimetable, daysToAdd) // if there are no lessons don't show the dayCardView @@ -179,7 +180,7 @@ class HomeFragment : Fragment() { noLesson.textSize = 18.0F noLesson.setTypeface(null, Typeface.BOLD) noLesson.textAlignment = View.TEXT_ALIGNMENT_CENTER - noLesson.setPadding(7,7,7,7) + noLesson.setPadding(7, 7, 7, 7) return noLesson } diff --git a/app/src/main/java/org/mosad/seil0/projectlaogai/fragments/MensaFragment.kt b/app/src/main/java/org/mosad/seil0/projectlaogai/fragments/MensaFragment.kt index 25a9680..7bbc9d9 100644 --- a/app/src/main/java/org/mosad/seil0/projectlaogai/fragments/MensaFragment.kt +++ b/app/src/main/java/org/mosad/seil0/projectlaogai/fragments/MensaFragment.kt @@ -28,8 +28,10 @@ import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment import kotlinx.android.synthetic.main.fragment_mensa.* -import org.jetbrains.anko.doAsync -import org.jetbrains.anko.uiThread +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import org.mosad.seil0.projectlaogai.R import org.mosad.seil0.projectlaogai.controller.CacheController import org.mosad.seil0.projectlaogai.controller.CacheController.Companion.mensaMenu @@ -53,12 +55,14 @@ class MensaFragment : Fragment() { // init actions refreshAction() - // add the current week (week starts on sunday) - val dayCurrent = if(NotRetardedCalendar.getDayOfWeekIndex() == 6) 0 else NotRetardedCalendar.getDayOfWeekIndex() - addWeek(mensaMenu.currentWeek, dayCurrent).get() + GlobalScope.launch(Dispatchers.Default) { + val dayCurrent = if(NotRetardedCalendar.getDayOfWeekIndex() == 6) 0 else NotRetardedCalendar.getDayOfWeekIndex() + addWeek(mensaMenu.currentWeek, dayCurrent).join() + + // add the next week + addWeek(mensaMenu.nextWeek, 0) + } - // add the next week - addWeek(mensaMenu.nextWeek, 0) // TODO should we show a info if there is no more food this & next week? @@ -70,9 +74,9 @@ 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) = doAsync { + private fun addWeek(menusWeek: MensaWeek, dayStart: Int) = GlobalScope.launch(Dispatchers.Default) { - uiThread { + withContext(Dispatchers.Main) { // only add the days dayStart to Fri since the mensa is closed on Sat/Sun for (dayIndex in dayStart..4) { @@ -105,8 +109,8 @@ class MensaFragment : Fragment() { /** * initialize the refresh action */ - private fun refreshAction() = doAsync { - uiThread { + private fun refreshAction() = GlobalScope.launch(Dispatchers.Default) { + withContext(Dispatchers.Main) { // set the refresh listener refreshLayout_Mensa.setOnRefreshListener { updateMensaScreen() @@ -118,18 +122,18 @@ class MensaFragment : Fragment() { /** * refresh the mensa cache and update the mensa screen */ - private fun updateMensaScreen() = doAsync { + private fun updateMensaScreen() = GlobalScope.launch(Dispatchers.Default) { // update the cache - TCoRAPIController.getMensa(context!!).get() // blocking since we want the new data + TCoRAPIController.getMensa(context!!).join() // blocking since we want the new data CacheController.readMensa(context!!) - uiThread { + withContext(Dispatchers.Main) { // remove all menus from the layout linLayout_Mensa.removeAllViews() // add the refreshed menus val dayCurrent = if (NotRetardedCalendar.getDayOfWeekIndex() == 6) 0 else NotRetardedCalendar.getDayOfWeekIndex() - addWeek(mensaMenu.currentWeek, dayCurrent).get() + addWeek(mensaMenu.currentWeek, dayCurrent).join() // add the next week addWeek(mensaMenu.nextWeek, 0) diff --git a/app/src/main/java/org/mosad/seil0/projectlaogai/fragments/SettingsFragment.kt b/app/src/main/java/org/mosad/seil0/projectlaogai/fragments/SettingsFragment.kt index 96f160a..059f5e9 100644 --- a/app/src/main/java/org/mosad/seil0/projectlaogai/fragments/SettingsFragment.kt +++ b/app/src/main/java/org/mosad/seil0/projectlaogai/fragments/SettingsFragment.kt @@ -39,8 +39,7 @@ import com.afollestad.materialdialogs.list.listItems import com.afollestad.materialdialogs.list.listItemsSingleChoice import de.psdev.licensesdialog.LicensesDialog import kotlinx.android.synthetic.main.fragment_settings.* -import org.jetbrains.anko.doAsync -import org.jetbrains.anko.uiThread +import kotlinx.coroutines.* import org.mosad.seil0.projectlaogai.BuildConfig import org.mosad.seil0.projectlaogai.R import org.mosad.seil0.projectlaogai.controller.CacheController @@ -54,7 +53,6 @@ import org.mosad.seil0.projectlaogai.controller.TCoRAPIController import org.mosad.seil0.projectlaogai.hsoparser.DataTypes import java.util.* - /** * The settings controller class * contains all needed parts to display and the settings screen @@ -245,17 +243,20 @@ class SettingsFragment : Fragment() { .customView(R.layout.dialog_loading) dialog.show() - doAsync { + GlobalScope.launch(Dispatchers.Default) { PreferencesController.saveCourse(context, coursesList[index]) // save the course // update current & next weeks timetable - TCoRAPIController.getTimetable(cCourse.courseName, 0, context).get() // blocking since we want the new data - TCoRAPIController.getTimetable(cCourse.courseName, 1, context).get() // blocking since we want the new data + val threads = listOf( + TCoRAPIController.getTimetable(cCourse.courseName, 0, context), + TCoRAPIController.getTimetable(cCourse.courseName, 1, context) + ) + threads.joinAll() // blocking since we want the new data CacheController.readTimetable(cCourse.courseName, 0, context) CacheController.readTimetable(cCourse.courseName, 1, context) - uiThread { + withContext(Dispatchers.Main) { dialog.dismiss() txtView_Course.text = cCourse.courseName // update txtView } diff --git a/app/src/main/java/org/mosad/seil0/projectlaogai/fragments/TimeTableFragment.kt b/app/src/main/java/org/mosad/seil0/projectlaogai/fragments/TimeTableFragment.kt index be3d017..fc1fb75 100644 --- a/app/src/main/java/org/mosad/seil0/projectlaogai/fragments/TimeTableFragment.kt +++ b/app/src/main/java/org/mosad/seil0/projectlaogai/fragments/TimeTableFragment.kt @@ -31,8 +31,7 @@ import androidx.fragment.app.Fragment import com.afollestad.materialdialogs.MaterialDialog import com.google.android.material.floatingactionbutton.FloatingActionButton import kotlinx.android.synthetic.main.fragment_timetable.* -import org.jetbrains.anko.doAsync -import org.jetbrains.anko.uiThread +import kotlinx.coroutines.* import org.mosad.seil0.projectlaogai.R import org.mosad.seil0.projectlaogai.controller.CacheController import org.mosad.seil0.projectlaogai.controller.CacheController.Companion.timetables @@ -74,9 +73,9 @@ class TimeTableFragment : Fragment() { /** * initialize the actions */ - private fun initActions() = doAsync { + private fun initActions() = GlobalScope.launch(Dispatchers.Default) { - uiThread { + withContext(Dispatchers.Main) { refreshLayout_Timetable.setOnRefreshListener { updateTimetableScreen() } @@ -104,18 +103,18 @@ class TimeTableFragment : Fragment() { /** * add the current and next weeks lessons */ - private fun addInitWeeks() = doAsync { + private fun addInitWeeks() = GlobalScope.launch(Dispatchers.Default) { val currentDayIndex = NotRetardedCalendar.getDayOfWeekIndex() - addWeek(currentDayIndex, 5, 0).get() // add current week + addWeek(currentDayIndex, 5, 0).join() // add current week addWeek(0, currentDayIndex - 1, 1) // add next week } - private fun addWeek(startDayIndex: Int, dayEndIndex: Int, weekIndex: Int) = doAsync { + private fun addWeek(startDayIndex: Int, dayEndIndex: Int, weekIndex: Int) = GlobalScope.launch(Dispatchers.Default) { val timetable = timetables[weekIndex].timetable val timetableMeta = timetables[weekIndex].meta - uiThread { + withContext(Dispatchers.Main) { for (dayIndex in startDayIndex..dayEndIndex) { val dayCardView = DayCardView(context!!) @@ -132,15 +131,18 @@ class TimeTableFragment : Fragment() { } } - private fun updateTimetableScreen() = doAsync { + private fun updateTimetableScreen() = GlobalScope.launch(Dispatchers.Default) { // update the cache - TCoRAPIController.getTimetable(cCourse.courseName, 0, context!!).get() // blocking since we want the new data - TCoRAPIController.getTimetable(cCourse.courseName, 1, context!!).get() // blocking since we want the new data + val threads = listOf( + TCoRAPIController.getTimetable(cCourse.courseName, 0, context!!), + TCoRAPIController.getTimetable(cCourse.courseName, 1, context!!) + ) + threads.joinAll() // blocking since we want the new data CacheController.readTimetable(cCourse.courseName, 0, context!!) CacheController.readTimetable(cCourse.courseName, 1, context!!) - uiThread { + withContext(Dispatchers.Main) { // remove all menus from the layout linLayout_Timetable.removeAllViews() @@ -148,7 +150,7 @@ class TimeTableFragment : Fragment() { val dayIndex = NotRetardedCalendar.getDayOfWeekIndex() // add current week - addWeek(dayIndex, 5, 0).get() + addWeek(dayIndex, 5, 0).join() // add next week addWeek(0, dayIndex - 1, 1) diff --git a/app/src/main/res/raw/notices.xml b/app/src/main/res/raw/notices.xml index 99c8b86..e05c044 100644 --- a/app/src/main/res/raw/notices.xml +++ b/app/src/main/res/raw/notices.xml @@ -19,8 +19,8 @@ Apache Software License 2.0 - anko - https://github.com/Kotlin/anko + kotlinx.coroutines + https://github.com/Kotlin/kotlinx.coroutines Copyright JetBrains Apache Software License 2.0 diff --git a/fastlane/metadata/android/en-US/changelogs/15.txt b/fastlane/metadata/android/en-US/changelogs/15.txt new file mode 100644 index 0000000..375d883 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/15.txt @@ -0,0 +1,5 @@ +This release 0.5.1 is called "artistical Apollon". + +* new: it's now possible to use App shortcuts for the timetable, mensa and moodle screen +* change: updated some libs, updated kotlin to 1.3.61 +* change: the app was updated to use kotlin coroutines instead of anko for asynchronous work loads