merge version 0.5.1 #38
@ -1,7 +1,5 @@
 | 
				
			|||||||
apply plugin: 'com.android.application'
 | 
					apply plugin: 'com.android.application'
 | 
				
			||||||
 | 
					 | 
				
			||||||
apply plugin: 'kotlin-android'
 | 
					apply plugin: 'kotlin-android'
 | 
				
			||||||
 | 
					 | 
				
			||||||
apply plugin: 'kotlin-android-extensions'
 | 
					apply plugin: 'kotlin-android-extensions'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
android {
 | 
					android {
 | 
				
			||||||
@ -12,8 +10,8 @@ android {
 | 
				
			|||||||
        applicationId "org.mosad.seil0.projectlaogai"
 | 
					        applicationId "org.mosad.seil0.projectlaogai"
 | 
				
			||||||
        minSdkVersion 23
 | 
					        minSdkVersion 23
 | 
				
			||||||
        targetSdkVersion 29
 | 
					        targetSdkVersion 29
 | 
				
			||||||
        versionCode 14
 | 
					        versionCode 15
 | 
				
			||||||
        versionName "0.5.0"
 | 
					        versionName "0.5.190"
 | 
				
			||||||
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
 | 
					        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
 | 
				
			||||||
        resValue "string", "build_time", buildTime()
 | 
					        resValue "string", "build_time", buildTime()
 | 
				
			||||||
        setProperty("archivesBaseName", "projectlaogai-$versionName")
 | 
					        setProperty("archivesBaseName", "projectlaogai-$versionName")
 | 
				
			||||||
@ -49,12 +47,12 @@ android {
 | 
				
			|||||||
dependencies {
 | 
					dependencies {
 | 
				
			||||||
    implementation fileTree(include: ['*.jar'], dir: 'libs')
 | 
					    implementation fileTree(include: ['*.jar'], dir: 'libs')
 | 
				
			||||||
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
 | 
					    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.appcompat:appcompat:1.1.0'
 | 
				
			||||||
    implementation 'androidx.legacy:legacy-support-v4:1.0.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 '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.google.code.gson:gson:2.8.6'
 | 
				
			||||||
    implementation 'com.afollestad:aesthetic:1.0.0-beta05'
 | 
					    implementation 'com.afollestad:aesthetic:1.0.0-beta05'
 | 
				
			||||||
    implementation 'com.afollestad.material-dialogs:core:3.1.1'
 | 
					    implementation 'com.afollestad.material-dialogs:core:3.1.1'
 | 
				
			||||||
 | 
				
			|||||||
@ -52,7 +52,6 @@ import kotlin.system.measureTimeMillis
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * TODO save the current fragment to show it when the app is restarted
 | 
					 * 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 {
 | 
					class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -27,6 +27,10 @@ import com.google.gson.Gson
 | 
				
			|||||||
import com.google.gson.GsonBuilder
 | 
					import com.google.gson.GsonBuilder
 | 
				
			||||||
import com.google.gson.JsonParser
 | 
					import com.google.gson.JsonParser
 | 
				
			||||||
import com.google.gson.reflect.TypeToken
 | 
					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.controller.PreferencesController.Companion.cCourse
 | 
				
			||||||
import org.mosad.seil0.projectlaogai.hsoparser.Course
 | 
					import org.mosad.seil0.projectlaogai.hsoparser.Course
 | 
				
			||||||
import org.mosad.seil0.projectlaogai.hsoparser.MensaMenu
 | 
					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 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) {
 | 
					        if ((currentDay == Calendar.MONDAY && cal.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) || (currentTime - mensaMenu.meta.updateTime) > 86400) {
 | 
				
			||||||
            println("update mensa blocking")
 | 
					            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
 | 
					        // check if we need to update the timetables before displaying them
 | 
				
			||||||
@ -63,11 +67,17 @@ class CacheController(cont: Context) {
 | 
				
			|||||||
        // 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 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!")
 | 
					            println("updating timetable after sunday!")
 | 
				
			||||||
            val jobA = TCoRAPIController.getTimetable(cCourse.courseName, 0, context)
 | 
					 | 
				
			||||||
            val jobB = TCoRAPIController.getTimetable(cCourse.courseName, 1, context)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            jobA.get()
 | 
					            GlobalScope.launch(Dispatchers.Default) {
 | 
				
			||||||
            jobB.get()
 | 
					                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
 | 
					        // check if an update is necessary, not blocking
 | 
				
			||||||
@ -99,13 +109,16 @@ class CacheController(cont: Context) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            // make sure the file exists
 | 
					            // make sure the file exists
 | 
				
			||||||
            if (!file.exists())
 | 
					            if (!file.exists())
 | 
				
			||||||
                TCoRAPIController.getCoursesList(context).get()
 | 
					                GlobalScope.launch(Dispatchers.Default) { TCoRAPIController.getCoursesList(context).join() }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            val fileReader = FileReader(file)
 | 
					            val fileReader = FileReader(file)
 | 
				
			||||||
            val bufferedReader = BufferedReader(fileReader)
 | 
					            val bufferedReader = BufferedReader(fileReader)
 | 
				
			||||||
            val coursesObject = JsonParser.parseString(bufferedReader.readLine()).asJsonObject
 | 
					            val coursesObject = JsonParser.parseString(bufferedReader.readLine()).asJsonObject
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            coursesList = Gson().fromJson(coursesObject.getAsJsonArray("courses"), object : TypeToken<List<Course>>() {}.type)
 | 
					            coursesList = Gson().fromJson(
 | 
				
			||||||
 | 
					                coursesObject.getAsJsonArray("courses"),
 | 
				
			||||||
 | 
					                object : TypeToken<List<Course>>() {}.type
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
@ -116,9 +129,8 @@ class CacheController(cont: Context) {
 | 
				
			|||||||
            val file = File(context.filesDir, "mensa.json")
 | 
					            val file = File(context.filesDir, "mensa.json")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // make sure the file exists
 | 
					            // make sure the file exists
 | 
				
			||||||
            if (!file.exists()) {
 | 
					            if (!file.exists())
 | 
				
			||||||
                TCoRAPIController.getMensa(context).get()
 | 
					                GlobalScope.launch(Dispatchers.Default) { TCoRAPIController.getMensa(context).join() }
 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            val fileReader = FileReader(file)
 | 
					            val fileReader = FileReader(file)
 | 
				
			||||||
            val bufferedReader = BufferedReader(fileReader)
 | 
					            val bufferedReader = BufferedReader(fileReader)
 | 
				
			||||||
@ -136,8 +148,11 @@ class CacheController(cont: Context) {
 | 
				
			|||||||
            val file = File(context.filesDir, "timetable-$courseName-$week.json")
 | 
					            val file = File(context.filesDir, "timetable-$courseName-$week.json")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // make sure the file exists
 | 
					            // make sure the file exists
 | 
				
			||||||
            if (!file.exists())
 | 
					            if (!file.exists()) {
 | 
				
			||||||
                TCoRAPIController.getTimetable(courseName, week, context).get()
 | 
					                GlobalScope.launch(Dispatchers.Default) {
 | 
				
			||||||
 | 
					                    TCoRAPIController.getTimetable(courseName, week, context).join()
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            val fileReader = FileReader(file)
 | 
					            val fileReader = FileReader(file)
 | 
				
			||||||
            val bufferedReader = BufferedReader(fileReader)
 | 
					            val bufferedReader = BufferedReader(fileReader)
 | 
				
			||||||
 | 
				
			|||||||
@ -24,7 +24,7 @@ package org.mosad.seil0.projectlaogai.controller
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import android.content.Context
 | 
					import android.content.Context
 | 
				
			||||||
import android.util.Log
 | 
					import android.util.Log
 | 
				
			||||||
import org.jetbrains.anko.doAsync
 | 
					import kotlinx.coroutines.*
 | 
				
			||||||
import org.json.JSONObject
 | 
					import org.json.JSONObject
 | 
				
			||||||
import org.mosad.seil0.projectlaogai.controller.PreferencesController.Companion.coursesCacheTime
 | 
					import org.mosad.seil0.projectlaogai.controller.PreferencesController.Companion.coursesCacheTime
 | 
				
			||||||
import org.mosad.seil0.projectlaogai.controller.PreferencesController.Companion.mensaCacheTime
 | 
					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)
 | 
					         * 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 {
 | 
					            try {
 | 
				
			||||||
                val url = URL("$tcorBaseURL/courseList")
 | 
					                val url = URL("$tcorBaseURL/courseList")
 | 
				
			||||||
                val file = File(context.filesDir, "courses.json")
 | 
					                val file = File(context.filesDir, "courses.json")
 | 
				
			||||||
@ -53,9 +53,11 @@ class TCoRAPIController {
 | 
				
			|||||||
                val coursesObject = JSONObject(url.readText()) //JSONObject(inReader.readLine())
 | 
					                val coursesObject = JSONObject(url.readText()) //JSONObject(inReader.readLine())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                // write the json object to a file
 | 
					                // write the json object to a file
 | 
				
			||||||
 | 
					                withContext(Dispatchers.IO) {
 | 
				
			||||||
                    val writer = BufferedWriter(FileWriter(file))
 | 
					                    val writer = BufferedWriter(FileWriter(file))
 | 
				
			||||||
                    writer.write(coursesObject.toString())
 | 
					                    writer.write(coursesObject.toString())
 | 
				
			||||||
                    writer.close()
 | 
					                    writer.close()
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                // update cache time
 | 
					                // update cache time
 | 
				
			||||||
                coursesCacheTime = System.currentTimeMillis() / 1000
 | 
					                coursesCacheTime = System.currentTimeMillis() / 1000
 | 
				
			||||||
@ -69,7 +71,7 @@ class TCoRAPIController {
 | 
				
			|||||||
        /**
 | 
					        /**
 | 
				
			||||||
         * get the json object from tcor api and write it as file (cache)
 | 
					         * 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 {
 | 
					            try {
 | 
				
			||||||
                val url = URL("$tcorBaseURL/mensamenu")
 | 
					                val url = URL("$tcorBaseURL/mensamenu")
 | 
				
			||||||
                val file = File(context.filesDir, "mensa.json")
 | 
					                val file = File(context.filesDir, "mensa.json")
 | 
				
			||||||
@ -78,9 +80,11 @@ class TCoRAPIController {
 | 
				
			|||||||
                val mensaObject = JSONObject(url.readText()) //JSONObject(inReader.readLine())
 | 
					                val mensaObject = JSONObject(url.readText()) //JSONObject(inReader.readLine())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                // write the json object to a file
 | 
					                // write the json object to a file
 | 
				
			||||||
 | 
					                withContext(Dispatchers.IO) {
 | 
				
			||||||
                    val writer = BufferedWriter(FileWriter(file))
 | 
					                    val writer = BufferedWriter(FileWriter(file))
 | 
				
			||||||
                    writer.write(mensaObject.toString())
 | 
					                    writer.write(mensaObject.toString())
 | 
				
			||||||
                    writer.close()
 | 
					                    writer.close()
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                // update cache time
 | 
					                // update cache time
 | 
				
			||||||
                mensaCacheTime = System.currentTimeMillis() / 1000
 | 
					                mensaCacheTime = System.currentTimeMillis() / 1000
 | 
				
			||||||
@ -94,18 +98,20 @@ class TCoRAPIController {
 | 
				
			|||||||
        /**
 | 
					        /**
 | 
				
			||||||
         * get the json object from tcor api and write it as file (cache)
 | 
					         * 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 {
 | 
					            try {
 | 
				
			||||||
                val url = URL("$tcorBaseURL/timetable?courseName=$courseName&week=$week")
 | 
					                val url = URL("$tcorBaseURL/timetable?courseName=$courseName&week=$week")
 | 
				
			||||||
                val file = File(context.filesDir, "timetable-$courseName-$week.json")
 | 
					                val file = File(context.filesDir, "timetable-$courseName-$week.json")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                // read data from the API
 | 
					                // 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
 | 
					                // write the json object to a file
 | 
				
			||||||
 | 
					                withContext(Dispatchers.IO) {
 | 
				
			||||||
                    val writer = BufferedWriter(FileWriter(file))
 | 
					                    val writer = BufferedWriter(FileWriter(file))
 | 
				
			||||||
                writer.write(mensaObject.toString())
 | 
					                    writer.write(timetableObject.toString())
 | 
				
			||||||
                    writer.close()
 | 
					                    writer.close()
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                // update cache time
 | 
					                // update cache time
 | 
				
			||||||
                timetableCacheTime = System.currentTimeMillis() / 1000
 | 
					                timetableCacheTime = System.currentTimeMillis() / 1000
 | 
				
			||||||
 | 
				
			|||||||
@ -31,8 +31,10 @@ import android.view.ViewGroup
 | 
				
			|||||||
import android.widget.TextView
 | 
					import android.widget.TextView
 | 
				
			||||||
import androidx.fragment.app.Fragment
 | 
					import androidx.fragment.app.Fragment
 | 
				
			||||||
import kotlinx.android.synthetic.main.fragment_home.*
 | 
					import kotlinx.android.synthetic.main.fragment_home.*
 | 
				
			||||||
import org.jetbrains.anko.doAsync
 | 
					import kotlinx.coroutines.Dispatchers
 | 
				
			||||||
import org.jetbrains.anko.uiThread
 | 
					import kotlinx.coroutines.GlobalScope
 | 
				
			||||||
 | 
					import kotlinx.coroutines.launch
 | 
				
			||||||
 | 
					import kotlinx.coroutines.withContext
 | 
				
			||||||
import org.mosad.seil0.projectlaogai.R
 | 
					import org.mosad.seil0.projectlaogai.R
 | 
				
			||||||
import org.mosad.seil0.projectlaogai.controller.CacheController.Companion.mensaMenu
 | 
					import org.mosad.seil0.projectlaogai.controller.CacheController.Companion.mensaMenu
 | 
				
			||||||
import org.mosad.seil0.projectlaogai.controller.CacheController.Companion.timetables
 | 
					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())
 | 
					    private val formatter = SimpleDateFormat("E dd.MM", Locale.getDefault())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
 | 
					    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
 | 
				
			||||||
 | 
					 | 
				
			||||||
        val view: View = inflater.inflate(R.layout.fragment_home, container, false)
 | 
					        val view: View = inflater.inflate(R.layout.fragment_home, container, false)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        addMensaMenu().get()
 | 
					        addMensaMenu()
 | 
				
			||||||
        addTimeTable().get()
 | 
					        addTimeTable()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Inflate the layout for this fragment
 | 
					        // Inflate the layout for this fragment
 | 
				
			||||||
        return view
 | 
					        return view
 | 
				
			||||||
@ -67,13 +68,13 @@ class HomeFragment : Fragment() {
 | 
				
			|||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * add the current mensa meal to the home screens
 | 
					     * add the current mensa meal to the home screens
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    private fun addMensaMenu() = doAsync {
 | 
					    private fun addMensaMenu() = GlobalScope.launch(Dispatchers.Default) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        var dayMeals: ArrayList<Meal>
 | 
					        var dayMeals: ArrayList<Meal>
 | 
				
			||||||
        val cal = Calendar.getInstance()
 | 
					        val cal = Calendar.getInstance()
 | 
				
			||||||
        val mensaCardView = DayCardView(context!!)
 | 
					        val mensaCardView = DayCardView(context!!)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        uiThread {
 | 
					        withContext(Dispatchers.Main) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (isAdded) {
 | 
					            if (isAdded) {
 | 
				
			||||||
                if (cal.get(Calendar.HOUR_OF_DAY) < 15) {
 | 
					                if (cal.get(Calendar.HOUR_OF_DAY) < 15) {
 | 
				
			||||||
@ -117,9 +118,9 @@ class HomeFragment : Fragment() {
 | 
				
			|||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * add the current timetable to the home screen
 | 
					     * 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()) {
 | 
					            if (isAdded && timetables.isNotEmpty()) {
 | 
				
			||||||
                try {
 | 
					                try {
 | 
				
			||||||
 | 
				
			|||||||
@ -28,8 +28,10 @@ import android.view.View
 | 
				
			|||||||
import android.view.ViewGroup
 | 
					import android.view.ViewGroup
 | 
				
			||||||
import androidx.fragment.app.Fragment
 | 
					import androidx.fragment.app.Fragment
 | 
				
			||||||
import kotlinx.android.synthetic.main.fragment_mensa.*
 | 
					import kotlinx.android.synthetic.main.fragment_mensa.*
 | 
				
			||||||
import org.jetbrains.anko.doAsync
 | 
					import kotlinx.coroutines.Dispatchers
 | 
				
			||||||
import org.jetbrains.anko.uiThread
 | 
					import kotlinx.coroutines.GlobalScope
 | 
				
			||||||
 | 
					import kotlinx.coroutines.launch
 | 
				
			||||||
 | 
					import kotlinx.coroutines.withContext
 | 
				
			||||||
import org.mosad.seil0.projectlaogai.R
 | 
					import org.mosad.seil0.projectlaogai.R
 | 
				
			||||||
import org.mosad.seil0.projectlaogai.controller.CacheController
 | 
					import org.mosad.seil0.projectlaogai.controller.CacheController
 | 
				
			||||||
import org.mosad.seil0.projectlaogai.controller.CacheController.Companion.mensaMenu
 | 
					import org.mosad.seil0.projectlaogai.controller.CacheController.Companion.mensaMenu
 | 
				
			||||||
@ -53,12 +55,14 @@ class MensaFragment : Fragment() {
 | 
				
			|||||||
        // init actions
 | 
					        // init actions
 | 
				
			||||||
        refreshAction()
 | 
					        refreshAction()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // add the current week (week starts on sunday)
 | 
					        GlobalScope.launch(Dispatchers.Default) {
 | 
				
			||||||
            val dayCurrent =  if(NotRetardedCalendar.getDayOfWeekIndex() == 6) 0 else NotRetardedCalendar.getDayOfWeekIndex()
 | 
					            val dayCurrent =  if(NotRetardedCalendar.getDayOfWeekIndex() == 6) 0 else NotRetardedCalendar.getDayOfWeekIndex()
 | 
				
			||||||
        addWeek(mensaMenu.currentWeek, dayCurrent).get()
 | 
					            addWeek(mensaMenu.currentWeek, dayCurrent).join()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // add the next week
 | 
					            // add the next week
 | 
				
			||||||
            addWeek(mensaMenu.nextWeek, 0)
 | 
					            addWeek(mensaMenu.nextWeek, 0)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // TODO should we show a info if there is no more food this & next week?
 | 
					        // 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 menusWeek menu of type MensaWeek you want to add
 | 
				
			||||||
     * @param dayStart the first day of the week 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
 | 
					            // only add the days dayStart to Fri since the mensa is closed on Sat/Sun
 | 
				
			||||||
            for (dayIndex in dayStart..4) {
 | 
					            for (dayIndex in dayStart..4) {
 | 
				
			||||||
@ -105,8 +109,8 @@ class MensaFragment : Fragment() {
 | 
				
			|||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * initialize the refresh action
 | 
					     * initialize the refresh action
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    private fun refreshAction() = doAsync {
 | 
					    private fun refreshAction() = GlobalScope.launch(Dispatchers.Default) {
 | 
				
			||||||
        uiThread {
 | 
					        withContext(Dispatchers.Main) {
 | 
				
			||||||
            // set the refresh listener
 | 
					            // set the refresh listener
 | 
				
			||||||
            refreshLayout_Mensa.setOnRefreshListener {
 | 
					            refreshLayout_Mensa.setOnRefreshListener {
 | 
				
			||||||
                updateMensaScreen()
 | 
					                updateMensaScreen()
 | 
				
			||||||
@ -118,18 +122,18 @@ class MensaFragment : Fragment() {
 | 
				
			|||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * refresh the mensa cache and update the mensa screen
 | 
					     * refresh the mensa cache and update the mensa screen
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    private fun updateMensaScreen() = doAsync {
 | 
					    private fun updateMensaScreen() = GlobalScope.launch(Dispatchers.Default) {
 | 
				
			||||||
        // update the cache
 | 
					        // 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!!)
 | 
					        CacheController.readMensa(context!!)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        uiThread {
 | 
					        withContext(Dispatchers.Main) {
 | 
				
			||||||
            // remove all menus from the layout
 | 
					            // remove all menus from the layout
 | 
				
			||||||
            linLayout_Mensa.removeAllViews()
 | 
					            linLayout_Mensa.removeAllViews()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // add the refreshed menus
 | 
					            // add the refreshed menus
 | 
				
			||||||
            val dayCurrent = if (NotRetardedCalendar.getDayOfWeekIndex() == 6) 0 else NotRetardedCalendar.getDayOfWeekIndex()
 | 
					            val dayCurrent = if (NotRetardedCalendar.getDayOfWeekIndex() == 6) 0 else NotRetardedCalendar.getDayOfWeekIndex()
 | 
				
			||||||
            addWeek(mensaMenu.currentWeek, dayCurrent).get()
 | 
					            addWeek(mensaMenu.currentWeek, dayCurrent).join()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // add the next week
 | 
					            // add the next week
 | 
				
			||||||
            addWeek(mensaMenu.nextWeek, 0)
 | 
					            addWeek(mensaMenu.nextWeek, 0)
 | 
				
			||||||
 | 
				
			|||||||
@ -39,8 +39,7 @@ import com.afollestad.materialdialogs.list.listItems
 | 
				
			|||||||
import com.afollestad.materialdialogs.list.listItemsSingleChoice
 | 
					import com.afollestad.materialdialogs.list.listItemsSingleChoice
 | 
				
			||||||
import de.psdev.licensesdialog.LicensesDialog
 | 
					import de.psdev.licensesdialog.LicensesDialog
 | 
				
			||||||
import kotlinx.android.synthetic.main.fragment_settings.*
 | 
					import kotlinx.android.synthetic.main.fragment_settings.*
 | 
				
			||||||
import org.jetbrains.anko.doAsync
 | 
					import kotlinx.coroutines.*
 | 
				
			||||||
import org.jetbrains.anko.uiThread
 | 
					 | 
				
			||||||
import org.mosad.seil0.projectlaogai.BuildConfig
 | 
					import org.mosad.seil0.projectlaogai.BuildConfig
 | 
				
			||||||
import org.mosad.seil0.projectlaogai.R
 | 
					import org.mosad.seil0.projectlaogai.R
 | 
				
			||||||
import org.mosad.seil0.projectlaogai.controller.CacheController
 | 
					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 org.mosad.seil0.projectlaogai.hsoparser.DataTypes
 | 
				
			||||||
import java.util.*
 | 
					import java.util.*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * The settings controller class
 | 
					 * The settings controller class
 | 
				
			||||||
 * contains all needed parts to display and the settings screen
 | 
					 * contains all needed parts to display and the settings screen
 | 
				
			||||||
@ -245,17 +243,20 @@ class SettingsFragment : Fragment() {
 | 
				
			|||||||
                    .customView(R.layout.dialog_loading)
 | 
					                    .customView(R.layout.dialog_loading)
 | 
				
			||||||
                dialog.show()
 | 
					                dialog.show()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                doAsync {
 | 
					                GlobalScope.launch(Dispatchers.Default) {
 | 
				
			||||||
                    PreferencesController.saveCourse(context, coursesList[index]) // save the course
 | 
					                    PreferencesController.saveCourse(context, coursesList[index]) // save the course
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    // update current & next weeks timetable
 | 
					                    // update current & next weeks timetable
 | 
				
			||||||
                    TCoRAPIController.getTimetable(cCourse.courseName, 0, context).get() // blocking since we want the new data
 | 
					                    val threads = listOf(
 | 
				
			||||||
                    TCoRAPIController.getTimetable(cCourse.courseName, 1, context).get() // blocking since we want the new data
 | 
					                        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, 0, context)
 | 
				
			||||||
                    CacheController.readTimetable(cCourse.courseName, 1, context)
 | 
					                    CacheController.readTimetable(cCourse.courseName, 1, context)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    uiThread {
 | 
					                    withContext(Dispatchers.Main) {
 | 
				
			||||||
                        dialog.dismiss()
 | 
					                        dialog.dismiss()
 | 
				
			||||||
                        txtView_Course.text = cCourse.courseName // update txtView
 | 
					                        txtView_Course.text = cCourse.courseName // update txtView
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
				
			|||||||
@ -31,8 +31,7 @@ import androidx.fragment.app.Fragment
 | 
				
			|||||||
import com.afollestad.materialdialogs.MaterialDialog
 | 
					import com.afollestad.materialdialogs.MaterialDialog
 | 
				
			||||||
import com.google.android.material.floatingactionbutton.FloatingActionButton
 | 
					import com.google.android.material.floatingactionbutton.FloatingActionButton
 | 
				
			||||||
import kotlinx.android.synthetic.main.fragment_timetable.*
 | 
					import kotlinx.android.synthetic.main.fragment_timetable.*
 | 
				
			||||||
import org.jetbrains.anko.doAsync
 | 
					import kotlinx.coroutines.*
 | 
				
			||||||
import org.jetbrains.anko.uiThread
 | 
					 | 
				
			||||||
import org.mosad.seil0.projectlaogai.R
 | 
					import org.mosad.seil0.projectlaogai.R
 | 
				
			||||||
import org.mosad.seil0.projectlaogai.controller.CacheController
 | 
					import org.mosad.seil0.projectlaogai.controller.CacheController
 | 
				
			||||||
import org.mosad.seil0.projectlaogai.controller.CacheController.Companion.timetables
 | 
					import org.mosad.seil0.projectlaogai.controller.CacheController.Companion.timetables
 | 
				
			||||||
@ -74,9 +73,9 @@ class TimeTableFragment : Fragment() {
 | 
				
			|||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * initialize the actions
 | 
					     * initialize the actions
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    private fun initActions() = doAsync {
 | 
					    private fun initActions() = GlobalScope.launch(Dispatchers.Default) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        uiThread {
 | 
					        withContext(Dispatchers.Main) {
 | 
				
			||||||
            refreshLayout_Timetable.setOnRefreshListener {
 | 
					            refreshLayout_Timetable.setOnRefreshListener {
 | 
				
			||||||
                updateTimetableScreen()
 | 
					                updateTimetableScreen()
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -104,18 +103,18 @@ class TimeTableFragment : Fragment() {
 | 
				
			|||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * add the current and next weeks lessons
 | 
					     * add the current and next weeks lessons
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    private fun addInitWeeks() = doAsync {
 | 
					    private fun addInitWeeks() = GlobalScope.launch(Dispatchers.Default) {
 | 
				
			||||||
        val currentDayIndex = NotRetardedCalendar.getDayOfWeekIndex()
 | 
					        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
 | 
					        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 timetable = timetables[weekIndex].timetable
 | 
				
			||||||
        val timetableMeta = timetables[weekIndex].meta
 | 
					        val timetableMeta = timetables[weekIndex].meta
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        uiThread {
 | 
					        withContext(Dispatchers.Main) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            for (dayIndex in startDayIndex..dayEndIndex) {
 | 
					            for (dayIndex in startDayIndex..dayEndIndex) {
 | 
				
			||||||
                val dayCardView = DayCardView(context!!)
 | 
					                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
 | 
					        // update the cache
 | 
				
			||||||
        TCoRAPIController.getTimetable(cCourse.courseName, 0, context!!).get() // blocking since we want the new data
 | 
					        val threads = listOf(
 | 
				
			||||||
        TCoRAPIController.getTimetable(cCourse.courseName, 1, context!!).get() // blocking since we want the new data
 | 
					            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, 0, context!!)
 | 
				
			||||||
        CacheController.readTimetable(cCourse.courseName, 1, context!!)
 | 
					        CacheController.readTimetable(cCourse.courseName, 1, context!!)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        uiThread {
 | 
					        withContext(Dispatchers.Main) {
 | 
				
			||||||
            // remove all menus from the layout
 | 
					            // remove all menus from the layout
 | 
				
			||||||
            linLayout_Timetable.removeAllViews()
 | 
					            linLayout_Timetable.removeAllViews()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -148,7 +150,7 @@ class TimeTableFragment : Fragment() {
 | 
				
			|||||||
            val dayIndex = NotRetardedCalendar.getDayOfWeekIndex()
 | 
					            val dayIndex = NotRetardedCalendar.getDayOfWeekIndex()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // add current week
 | 
					            // add current week
 | 
				
			||||||
            addWeek(dayIndex, 5, 0).get()
 | 
					            addWeek(dayIndex, 5, 0).join()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // add next week
 | 
					            // add next week
 | 
				
			||||||
            addWeek(0, dayIndex - 1, 1)
 | 
					            addWeek(0, dayIndex - 1, 1)
 | 
				
			||||||
 | 
				
			|||||||
@ -19,8 +19,8 @@
 | 
				
			|||||||
        <license>Apache Software License 2.0</license>
 | 
					        <license>Apache Software License 2.0</license>
 | 
				
			||||||
    </notice>
 | 
					    </notice>
 | 
				
			||||||
    <notice>
 | 
					    <notice>
 | 
				
			||||||
        <name>anko</name>
 | 
					        <name>kotlinx.coroutines</name>
 | 
				
			||||||
        <url>https://github.com/Kotlin/anko</url>
 | 
					        <url>https://github.com/Kotlin/kotlinx.coroutines</url>
 | 
				
			||||||
        <copyright>Copyright JetBrains</copyright>
 | 
					        <copyright>Copyright JetBrains</copyright>
 | 
				
			||||||
        <license>Apache Software License 2.0</license>
 | 
					        <license>Apache Software License 2.0</license>
 | 
				
			||||||
    </notice>
 | 
					    </notice>
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										5
									
								
								fastlane/metadata/android/en-US/changelogs/15.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								fastlane/metadata/android/en-US/changelogs/15.txt
									
									
									
									
									
										Normal file
									
								
							@ -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
 | 
				
			||||||
		Reference in New Issue
	
	Block a user