14 Commits

Author SHA1 Message Date
6e9c63d3d4 Merge branch 'develop' of Seil0/ProjectLaogai into master [Hotfix] 2020-02-18 15:24:08 +01:00
c343735b57 fix crash on first startup 2020-02-18 15:18:36 +01:00
9c5274dc06 Merge branch 'develop' of Seil0/ProjectLaogai into master
release version 0.5.1
2020-02-05 14:15:04 +01:00
b186a2e96e release version 0.5.1 2020-02-05 14:10:45 +01:00
2cb4b72369 anko code removed, coroutines are now used for asynchronous functions
* constraintlayout 2.0.0-beta3 -> 2.0.0-beta4
* material-components-android 1.0.0 -> 1.1.0
* this is the first release candidate for version 0.5.1
2020-02-04 19:58:07 +01:00
2d497d1a96 update gradle wrapper to version 6.0.1 2020-01-15 15:28:07 +01:00
9d2de3fcb3 don't use deprecated Gson methods 2020-01-15 15:08:05 +01:00
bed3f5d978 added Timetable and Moodle shortcut, cleaned up activity init 2020-01-15 15:00:05 +01:00
8f5a4dd1b3 reworked preference saving 2019-12-13 14:54:51 +01:00
9907d083e9 added a Mensa shortcut
* added a Mensa shortcut, to directly display the Mensa-Screen
* kotlin 1.3.60 -> 1.3.61
2019-11-28 16:38:25 +01:00
d4860b2a32 updated some libs
* kotlin 1.3.50 -> 1.3.60
* androidx.constraintlayout 2.0.0-beta2 -> 2.0.0-beta3
2019-11-14 23:11:49 +01:00
5ec2b53bce added "Get it on Google Play" badge 2019-10-24 22:22:17 +02:00
701a351e6e update .drone.yml
Some checks reported errors
continuous-integration/drone/push Build encountered an error
2019-10-17 19:21:15 +02:00
5cad924b26 removed anko dependency from PreferenceController
Some checks reported errors
continuous-integration/drone/push Build encountered an error
2019-10-17 19:19:47 +02:00
26 changed files with 315 additions and 154 deletions

View File

@ -3,7 +3,7 @@ name: default
steps: steps:
- name: assembleRelease - name: assembleRelease
image: gradle:jdk8 image: nextcloudci/android:android-51
commands: commands:
- gradle assembleRelease - gradle assembleRelease

View File

@ -5,6 +5,7 @@
ProjectLaogai is a app to access the timetable and the mensa menu of Hochschule Offenburg. ProjectLaogai is a app to access the timetable and the mensa menu of Hochschule Offenburg.
[<img src="https://fdroid.gitlab.io/artwork/badge/get-it-on.png" height="75">](https://f-droid.org/packages/org.mosad.seil0.projectlaogai/) [<img src="https://fdroid.gitlab.io/artwork/badge/get-it-on.png" height="75">](https://f-droid.org/packages/org.mosad.seil0.projectlaogai/)
[<img src="https://play.google.com/intl/en_us/badges/static/images/badges/en_badge_web_generic.png" height="75">](https://play.google.com/store/apps/details?id=org.mosad.seil0.projectlaogai)
## Features ## Features
* check out the mensa menu of this and next week * check out the mensa menu of this and next week
* access your timetable * access your timetable
@ -19,4 +20,4 @@ ProjectLaogai is a app to access the timetable and the mensa menu of Hochschule
[<img src="https://www.mosad.xyz/images/Project_Laogai/ProjectLaogai_Settings.png" width=180>](https://www.mosad.xyz/images/Project_Laogai/ProjectLaogai_Settings.png) [<img src="https://www.mosad.xyz/images/Project_Laogai/ProjectLaogai_Settings.png" width=180>](https://www.mosad.xyz/images/Project_Laogai/ProjectLaogai_Settings.png)
[<img src="https://www.mosad.xyz/images/Project_Laogai/ProjectLaogai_Mensa_dark.png" width=180>](https://www.mosad.xyz/images/Project_Laogai/ProjectLaogai_Mensa_dark.png) [<img src="https://www.mosad.xyz/images/Project_Laogai/ProjectLaogai_Mensa_dark.png" width=180>](https://www.mosad.xyz/images/Project_Laogai/ProjectLaogai_Mensa_dark.png)
ProjectLaogai © 2019 [@Seil0](https://git.mosad.xyz/Seil0), a [mosad](http://www.mosad.xyz) Project ProjectLaogai © 2019-2020 [@Seil0](https://git.mosad.xyz/Seil0), a [mosad](http://www.mosad.xyz) Project

View File

@ -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.1"
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,13 +47,13 @@ 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-beta2' 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.5' 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'
implementation 'com.afollestad.material-dialogs:color:3.1.1' implementation 'com.afollestad.material-dialogs:color:3.1.1'

View File

@ -23,6 +23,9 @@
<action android:name="android.intent.action.MAIN"/> <action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/> <category android:name="android.intent.category.LAUNCHER"/>
</intent-filter> </intent-filter>
<meta-data android:name="android.app.shortcuts"
android:resource="@xml/shortcuts" />
</activity> </activity>
<activity <activity

View File

@ -1,7 +1,7 @@
/** /**
* ProjectLaogai * ProjectLaogai
* *
* Copyright 2019 <seil0@mosad.xyz> * Copyright 2019-2020 <seil0@mosad.xyz>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -30,6 +30,7 @@ import android.nfc.NfcAdapter
import android.nfc.NfcManager import android.nfc.NfcManager
import android.nfc.tech.NfcA import android.nfc.tech.NfcA
import android.os.Bundle import android.os.Bundle
import android.util.Log
import android.view.Menu import android.view.Menu
import android.view.MenuItem import android.view.MenuItem
import androidx.appcompat.app.ActionBarDrawerToggle import androidx.appcompat.app.ActionBarDrawerToggle
@ -50,10 +51,13 @@ import org.mosad.seil0.projectlaogai.controller.PreferencesController.Companion.
import org.mosad.seil0.projectlaogai.fragments.* import org.mosad.seil0.projectlaogai.fragments.*
import kotlin.system.measureTimeMillis 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
*/
class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener { class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener {
private var activeFragment: Fragment = HomeFragment() // the currently active fragment, home at the start private var activeFragment: Fragment = HomeFragment() // the currently active fragment, home at the start
private val className = "MainActivity"
private lateinit var adapter: NfcAdapter private lateinit var adapter: NfcAdapter
private lateinit var pendingIntent: PendingIntent private lateinit var pendingIntent: PendingIntent
@ -62,6 +66,8 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
private var useNFC = false private var useNFC = false
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
val fragmentTransaction: FragmentTransaction = supportFragmentManager.beginTransaction()
Aesthetic.attach(this) Aesthetic.attach(this)
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main) setContentView(R.layout.activity_main)
@ -72,11 +78,6 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
initAesthetic() initAesthetic()
initForegroundDispatch() initForegroundDispatch()
//init home fragment
val fragmentTransaction: FragmentTransaction = supportFragmentManager.beginTransaction()
fragmentTransaction.replace(R.id.fragment_container, activeFragment)
fragmentTransaction.commit()
val toggle = ActionBarDrawerToggle( val toggle = ActionBarDrawerToggle(
this, drawer_layout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close this, drawer_layout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close
) )
@ -85,9 +86,17 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
nav_view.setNavigationItemSelectedListener(this) nav_view.setNavigationItemSelectedListener(this)
// if we get an NFC read intent while the app is closed call readBalance // based on the inent we get, call readBalance or open a Fragment
if (NfcAdapter.ACTION_TECH_DISCOVERED == intent.action) when (intent.action) {
NFCMensaCard.readBalance(intent, this) NfcAdapter.ACTION_TECH_DISCOVERED -> NFCMensaCard.readBalance(intent, this)
"org.mosad.seil0.projectlaogai.fragments.MensaFragment" -> activeFragment = MensaFragment()
"org.mosad.seil0.projectlaogai.fragments.TimeTableFragment" -> activeFragment = TimeTableFragment()
"org.mosad.seil0.projectlaogai.fragments.MoodleFragment" -> activeFragment = MoodleFragment()
}
// open the activeFragment, default is the HomeFragment
fragmentTransaction.replace(R.id.fragment_container, activeFragment)
fragmentTransaction.commit()
} }
override fun onNewIntent(intent: Intent) { override fun onNewIntent(intent: Intent) {
@ -166,7 +175,7 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
PreferencesController.load(this) // load the settings, must be finished before doing anything else PreferencesController.load(this) // load the settings, must be finished before doing anything else
CacheController(this) // load the cache CacheController(this) // load the cache
} }
println("startup completed in $startupTime ms") Log.i(className, "startup completed in $startupTime ms")
} }
private fun initAesthetic() { private fun initAesthetic() {

View File

@ -1,7 +1,7 @@
/** /**
* ProjectLaogai * ProjectLaogai
* *
* Copyright 2019 <seil0@mosad.xyz> * Copyright 2019-2020 <seil0@mosad.xyz>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -23,12 +23,16 @@
package org.mosad.seil0.projectlaogai.controller package org.mosad.seil0.projectlaogai.controller
import android.content.Context import android.content.Context
import android.util.Log
import com.google.gson.Gson 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.*
import org.mosad.seil0.projectlaogai.controller.PreferencesController.Companion.cCourse import org.mosad.seil0.projectlaogai.controller.PreferencesController.Companion.cCourse
import org.mosad.seil0.projectlaogai.hsoparser.* import org.mosad.seil0.projectlaogai.hsoparser.Course
import org.mosad.seil0.projectlaogai.hsoparser.MensaMenu
import org.mosad.seil0.projectlaogai.hsoparser.TimetableCourseWeek
import java.io.BufferedReader import java.io.BufferedReader
import java.io.File import java.io.File
import java.io.FileReader import java.io.FileReader
@ -37,6 +41,7 @@ import kotlin.collections.ArrayList
class CacheController(cont: Context) { class CacheController(cont: Context) {
private val className = "CacheController"
private val context = cont private val context = cont
init { init {
@ -50,8 +55,8 @@ 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") Log.i(className, "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
@ -59,23 +64,29 @@ class CacheController(cont: Context) {
cal.time = Date(timetables[0].meta.updateTime * 1000) 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 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!") Log.i(className, "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
if(currentTime - PreferencesController.coursesCacheTime > 86400) if (currentTime - PreferencesController.coursesCacheTime > 86400)
TCoRAPIController.getCoursesList(context) TCoRAPIController.getCoursesList(context)
if(currentTime - PreferencesController.mensaCacheTime > 10800) if (currentTime - PreferencesController.mensaCacheTime > 10800)
TCoRAPIController.getMensa(context) TCoRAPIController.getMensa(context)
if(currentTime - PreferencesController.timetableCacheTime > 10800) { if (currentTime - PreferencesController.timetableCacheTime > 10800) {
TCoRAPIController.getTimetable(cCourse.courseName, 0, context) TCoRAPIController.getTimetable(cCourse.courseName, 0, context)
TCoRAPIController.getTimetable(cCourse.courseName, 1, context) TCoRAPIController.getTimetable(cCourse.courseName, 1, context)
} }
@ -97,13 +108,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() runBlocking { TCoRAPIController.getCoursesList(context).join() }
val fileReader = FileReader(file) val fileReader = FileReader(file)
val bufferedReader = BufferedReader(fileReader) val bufferedReader = BufferedReader(fileReader)
val coursesObject = JsonParser().parse(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
)
} }
/** /**
@ -114,13 +128,12 @@ 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() runBlocking { TCoRAPIController.getMensa(context).join() }
}
val fileReader = FileReader(file) val fileReader = FileReader(file)
val bufferedReader = BufferedReader(fileReader) val bufferedReader = BufferedReader(fileReader)
val mensaObject = JsonParser().parse(bufferedReader.readLine()).asJsonObject val mensaObject = JsonParser.parseString(bufferedReader.readLine()).asJsonObject
mensaMenu = GsonBuilder().create().fromJson(mensaObject, MensaMenu().javaClass) mensaMenu = GsonBuilder().create().fromJson(mensaObject, MensaMenu().javaClass)
} }
@ -135,11 +148,11 @@ class CacheController(cont: Context) {
// make sure the file exists // make sure the file exists
if (!file.exists()) if (!file.exists())
TCoRAPIController.getTimetable(courseName, week, context).get() runBlocking { TCoRAPIController.getTimetable(courseName, week, context).join() }
val fileReader = FileReader(file) val fileReader = FileReader(file)
val bufferedReader = BufferedReader(fileReader) val bufferedReader = BufferedReader(fileReader)
val timetableObject = JsonParser().parse(bufferedReader.readLine()).asJsonObject val timetableObject = JsonParser.parseString(bufferedReader.readLine()).asJsonObject
// make sure you add the single weeks in the exact order! // make sure you add the single weeks in the exact order!
if (timetables.size > week) { if (timetables.size > week) {
@ -154,7 +167,7 @@ class CacheController(cont: Context) {
* read coursesList, mensa (current and next week), timetable (current and next week) * read coursesList, mensa (current and next week), timetable (current and next week)
* @param courseName the course name (e.g AI1) * @param courseName the course name (e.g AI1)
*/ */
fun readStartCache(courseName: String) { private fun readStartCache(courseName: String) {
readCoursesList(context) readCoursesList(context)
readMensa(context) readMensa(context)
readTimetable(courseName, 0, context) readTimetable(courseName, 0, context)

View File

@ -1,7 +1,7 @@
/** /**
* ProjectLaogai * ProjectLaogai
* *
* Copyright 2019 <seil0@mosad.xyz> * Copyright 2019-2020 <seil0@mosad.xyz>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -66,7 +66,7 @@ class NFCMensaCard {
lookAtMe(context, data, settings.value).show() lookAtMe(context, data, settings.value).show()
} }
} catch (ex: Exception) { } catch (ex: Exception) {
Log.i(className,"could not connect to tag", ex) Log.w(className,"could not connect to tag", ex)
} }
} }

View File

@ -1,7 +1,7 @@
/** /**
* ProjectLaogai * ProjectLaogai
* *
* Copyright 2019 <seil0@mosad.xyz> * Copyright 2019-2020 <seil0@mosad.xyz>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -24,7 +24,6 @@ package org.mosad.seil0.projectlaogai.controller
import android.content.Context import android.content.Context
import android.graphics.Color import android.graphics.Color
import org.jetbrains.anko.defaultSharedPreferences
import org.mosad.seil0.projectlaogai.R import org.mosad.seil0.projectlaogai.R
import org.mosad.seil0.projectlaogai.hsoparser.Course import org.mosad.seil0.projectlaogai.hsoparser.Course
@ -46,7 +45,10 @@ class PreferencesController {
// the save function // the save function
fun save(context: Context) { fun save(context: Context) {
val sharedPref = context.defaultSharedPreferences val sharedPref = context.getSharedPreferences(
context.getString(R.string.preference_file_key),
Context.MODE_PRIVATE
)
// save the update times (cache) // save the update times (cache)
with (sharedPref.edit()) { with (sharedPref.edit()) {
@ -62,42 +64,89 @@ class PreferencesController {
apply() apply()
} }
// save the course }
/**
* save the course locally
*/
fun saveCourse(context: Context, course: Course) {
val sharedPref = context.getSharedPreferences(
context.getString(R.string.preference_file_key),
Context.MODE_PRIVATE
)
with (sharedPref.edit()) { with (sharedPref.edit()) {
putString(context.getString(R.string.save_key_course), cCourse.courseName) putString(context.getString(R.string.save_key_course), course.courseName)
putString(context.getString(R.string.save_key_courseTTLink), cCourse.courseLink) putString(context.getString(R.string.save_key_courseTTLink), course.courseLink)
apply() apply()
} }
// save the primary color cCourse = course
}
/**
* save the primary color
*/
fun saveColorPrimary(context: Context, colorPrimary: Int) {
val sharedPref = context.getSharedPreferences(
context.getString(R.string.preference_file_key),
Context.MODE_PRIVATE
)
with (sharedPref.edit()) { with (sharedPref.edit()) {
putInt(context.getString(R.string.save_key_colorPrimary), putInt(context.getString(R.string.save_key_colorPrimary),
cColorPrimary colorPrimary
) )
apply() apply()
} }
// save the accent color cColorPrimary = colorPrimary
}
/**
* save the accent color
*/
fun saveColorAccent(context: Context, colorAccent: Int) {
val sharedPref = context.getSharedPreferences(
context.getString(R.string.preference_file_key),
Context.MODE_PRIVATE
)
with (sharedPref.edit()) { with (sharedPref.edit()) {
putInt(context.getString(R.string.save_key_colorAccent), putInt(context.getString(R.string.save_key_colorAccent),
cColorAccent colorAccent
) )
apply() apply()
} }
// save showBuffet cColorAccent = colorAccent
}
/**
* save showBuffet
*/
fun saveShowBuffet(context: Context, showBuffet: Boolean) {
val sharedPref = context.getSharedPreferences(
context.getString(R.string.preference_file_key),
Context.MODE_PRIVATE
)
with (sharedPref.edit()) { with (sharedPref.edit()) {
putBoolean(context.getString(R.string.save_key_showBuffet), putBoolean(context.getString(R.string.save_key_showBuffet),
cShowBuffet showBuffet
) )
apply() apply()
} }
cShowBuffet = showBuffet
} }
// the load function // the load function
fun load(context: Context) { fun load(context: Context) {
val sharedPref = context.defaultSharedPreferences val sharedPref = context.getSharedPreferences(
context.getString(R.string.preference_file_key),
Context.MODE_PRIVATE
)
// load the update times (cache) // load the update times (cache)
coursesCacheTime = sharedPref.getLong(context.getString( coursesCacheTime = sharedPref.getLong(context.getString(

View File

@ -1,7 +1,7 @@
/** /**
* ProjectLaogai * ProjectLaogai
* *
* Copyright 2019 <seil0@mosad.xyz> * Copyright 2019-2020 <seil0@mosad.xyz>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -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
val writer = BufferedWriter(FileWriter(file)) withContext(Dispatchers.IO) {
writer.write(coursesObject.toString()) val writer = BufferedWriter(FileWriter(file))
writer.close() writer.write(coursesObject.toString())
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
val writer = BufferedWriter(FileWriter(file)) withContext(Dispatchers.IO) {
writer.write(mensaObject.toString()) val writer = BufferedWriter(FileWriter(file))
writer.close() writer.write(mensaObject.toString())
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
val writer = BufferedWriter(FileWriter(file)) withContext(Dispatchers.IO) {
writer.write(mensaObject.toString()) val writer = BufferedWriter(FileWriter(file))
writer.close() writer.write(timetableObject.toString())
writer.close()
}
// update cache time // update cache time
timetableCacheTime = System.currentTimeMillis() / 1000 timetableCacheTime = System.currentTimeMillis() / 1000

View File

@ -1,7 +1,7 @@
/** /**
* ProjectLaogai * ProjectLaogai
* *
* Copyright 2019 <seil0@mosad.xyz> * Copyright 2019-2020 <seil0@mosad.xyz>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -31,8 +31,7 @@ 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.*
import org.jetbrains.anko.uiThread
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 +53,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 +65,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 +115,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 {
@ -140,7 +138,7 @@ class HomeFragment : Fragment() {
* @param startDayIndex the day index you want to start searching * @param startDayIndex the day index you want to start searching
* @return a DayCardView with all lessons added * @return a DayCardView with all lessons added
*/ */
private fun findNextDay(startDayIndex: Int) : DayCardView { private fun findNextDay(startDayIndex: Int): DayCardView {
val dayCardView = DayCardView(context!!) val dayCardView = DayCardView(context!!)
var dayTimetable: TimetableDay? = null var dayTimetable: TimetableDay? = null
var dayIndexSearch = startDayIndex var dayIndexSearch = startDayIndex
@ -151,7 +149,7 @@ class HomeFragment : Fragment() {
dayTimetable = timetables[weekIndexSearch].timetable.days[dayIndex] 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) // 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) dayCardView.addTimetableDay(dayTimetable, daysToAdd)
// if there are no lessons don't show the dayCardView // if there are no lessons don't show the dayCardView
@ -179,7 +177,7 @@ class HomeFragment : Fragment() {
noLesson.textSize = 18.0F noLesson.textSize = 18.0F
noLesson.setTypeface(null, Typeface.BOLD) noLesson.setTypeface(null, Typeface.BOLD)
noLesson.textAlignment = View.TEXT_ALIGNMENT_CENTER noLesson.textAlignment = View.TEXT_ALIGNMENT_CENTER
noLesson.setPadding(7,7,7,7) noLesson.setPadding(7, 7, 7, 7)
return noLesson return noLesson
} }

View File

@ -1,7 +1,7 @@
/** /**
* ProjectLaogai * ProjectLaogai
* *
* Copyright 2019 <seil0@mosad.xyz> * Copyright 2019-2020 <seil0@mosad.xyz>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -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
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? // 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)

View File

@ -1,7 +1,7 @@
/** /**
* ProjectLaogai * ProjectLaogai
* *
* Copyright 2019 <seil0@mosad.xyz> * Copyright 2019-2020 <seil0@mosad.xyz>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by

View File

@ -1,7 +1,7 @@
/** /**
* ProjectLaogai * ProjectLaogai
* *
* Copyright 2019 <seil0@mosad.xyz> * Copyright 2019-2020 <seil0@mosad.xyz>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -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
@ -182,6 +180,7 @@ class SettingsFragment : Fragment() {
2 -> activityTheme(R.style.AppTheme_Black) 2 -> activityTheme(R.style.AppTheme_Black)
else -> activityTheme(R.style.AppTheme_Light) else -> activityTheme(R.style.AppTheme_Light)
} }
apply()
} }
} }
} }
@ -199,8 +198,7 @@ class SettingsFragment : Fragment() {
apply() apply()
} }
cColorPrimary = color PreferencesController.saveColorPrimary(context!!, color)
PreferencesController.save(context!!)
} }
.positiveButton(R.string.select) .positiveButton(R.string.select)
.show() .show()
@ -217,17 +215,14 @@ class SettingsFragment : Fragment() {
apply() apply()
} }
cColorAccent = color PreferencesController.saveColorAccent(context!!, color)
PreferencesController.save(context!!)
} }
.positiveButton(R.string.select) .positiveButton(R.string.select)
.show() .show()
} }
switchBuffet.setOnClickListener { switchBuffet.setOnClickListener {
cShowBuffet = switchBuffet.isChecked PreferencesController.saveShowBuffet(context!!, switchBuffet.isChecked)
PreferencesController.save(context!!)
println(switchBuffet.isChecked)
} }
} }
@ -248,18 +243,20 @@ class SettingsFragment : Fragment() {
.customView(R.layout.dialog_loading) .customView(R.layout.dialog_loading)
dialog.show() dialog.show()
doAsync { GlobalScope.launch(Dispatchers.Default) {
cCourse = coursesList[index] // set the course PreferencesController.saveCourse(context, coursesList[index]) // save the course
PreferencesController.save(context)
// 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
} }

View File

@ -1,7 +1,7 @@
/** /**
* ProjectLaogai * ProjectLaogai
* *
* Copyright 2019 <seil0@mosad.xyz> * Copyright 2019-2020 <seil0@mosad.xyz>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -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,16 +73,16 @@ 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()
} }
faBtnAddLesson.setOnClickListener { faBtnAddLesson.setOnClickListener {
MaterialDialog(context!!) MaterialDialog(context!!)
.title(text = "Vorlesung hinzufügen") .title(text = resources.getString(R.string.add_lesson))
.message(text = "wähle einen Studiengang aus:\n\nWähle eine Vorlesung aus: \n\n Diese Funktion ist noch nicht verfügbar") .message(text = "wähle einen Studiengang aus:\n\nWähle eine Vorlesung aus: \n\n Diese Funktion ist noch nicht verfügbar")
.show() .show()
} }
@ -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)

View File

@ -1,7 +1,7 @@
/** /**
* ProjectLaogai * ProjectLaogai
* *
* Copyright 2019 <seil0@mosad.xyz> * Copyright 2019-2020 <seil0@mosad.xyz>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by

View File

@ -1,7 +1,7 @@
/** /**
* ProjectLaogai * ProjectLaogai
* *
* Copyright 2019 <seil0@mosad.xyz> * Copyright 2019-2020 <seil0@mosad.xyz>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by

View File

@ -1,7 +1,7 @@
/** /**
* ProjectLaogai * ProjectLaogai
* *
* Copyright 2019 <seil0@mosad.xyz> * Copyright 2019-2020 <seil0@mosad.xyz>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by

View File

@ -1,7 +1,7 @@
/** /**
* ProjectLaogai * ProjectLaogai
* *
* Copyright 2019 <seil0@mosad.xyz> * Copyright 2019-2020 <seil0@mosad.xyz>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by

View File

@ -0,0 +1,43 @@
<shortcuts xmlns:android="http://schemas.android.com/apk/res/android">
<shortcut
android:shortcutId="mensa"
android:enabled="true"
android:icon="@drawable/ic_local_dining_black_24dp"
android:shortcutShortLabel="@string/shortcut_mensa_short"
android:shortcutLongLabel="@string/shortcut_mensa_long"
android:shortcutDisabledMessage="@string/shortcut_mensa_disabled">
<intent
android:action="org.mosad.seil0.projectlaogai.fragments.MensaFragment"
android:targetPackage="org.mosad.seil0.projectlaogai"
android:targetClass="org.mosad.seil0.projectlaogai.MainActivity" />
<categories android:name="android.shortcut.conversation" />
</shortcut>
<shortcut
android:shortcutId="timetable"
android:enabled="true"
android:icon="@drawable/ic_baseline_calendar_today_24dp"
android:shortcutShortLabel="@string/shortcut_timetable_short"
android:shortcutLongLabel="@string/shortcut_timetable_long"
android:shortcutDisabledMessage="@string/shortcut_timetable_disabled">
<intent
android:action="org.mosad.seil0.projectlaogai.fragments.TimeTableFragment"
android:targetPackage="org.mosad.seil0.projectlaogai"
android:targetClass="org.mosad.seil0.projectlaogai.MainActivity" />
<categories android:name="android.shortcut.conversation" />
</shortcut>
<shortcut
android:shortcutId="moodle"
android:enabled="true"
android:icon="@drawable/ic_school_black_24dp"
android:shortcutShortLabel="@string/shortcut_moodle_short"
android:shortcutLongLabel="@string/shortcut_moodle_long"
android:shortcutDisabledMessage="@string/shortcut_moodle_disabled">
<intent
android:action="org.mosad.seil0.projectlaogai.fragments.MoodleFragment"
android:targetPackage="org.mosad.seil0.projectlaogai"
android:targetClass="org.mosad.seil0.projectlaogai.MainActivity" />
<categories android:name="android.shortcut.conversation" />
</shortcut>
</shortcuts>

View File

@ -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>

View File

@ -18,20 +18,23 @@
<string name="no_more_food">Diese Woche keine weitere Essensausgabe</string> <string name="no_more_food">Diese Woche keine weitere Essensausgabe</string>
<string name="no_lesson_today">heute keine Vorlesung!</string> <string name="no_lesson_today">heute keine Vorlesung!</string>
<!-- fragment_timetable -->
<string name="add_lesson">Eine Vorlesung hinzufügen</string>
<!-- fragment_settings --> <!-- fragment_settings -->
<string name="info">Info</string> <string name="info">Info</string>
<string name="user">Benutzer</string> <string name="user">Benutzer</string>
<string name="course_desc">Tippen, um den Kurs zu ändern</string> <string name="course_desc">Tippe um den Kurs zu ändern</string>
<string name="about_dialog_heading">Über</string> <string name="about_dialog_heading">Über</string>
<string name="licenses">Lizenzen</string> <string name="licenses">Lizenzen</string>
<string name="theme">Design</string> <string name="theme">Design</string>
<string name="themeLight">Hell</string> <string name="themeLight">Hell</string>
<string name="themeDark">Dunkel</string> <string name="themeDark">Dunkel</string>
<string name="themeBlack">Schwarz</string> <string name="themeBlack">Schwarz</string>
<string name="primary_color">Hauptfarbe</string> <string name="primary_color">Primärfarbe</string>
<string name="primary_color_desc">Die Primärfarbe, Standard ist Schwarz.</string> <string name="primary_color_desc">Zum Ändern tippen, Standard ist Schwarz.</string>
<string name="accent_color">Akzentfarbe</string> <string name="accent_color">Akzentfarbe</string>
<string name="accent_color_desc">Die Akzentfarbe, Standard ist indigo</string> <string name="accent_color_desc">Zum Ändern tippen, Standard ist Indigo.</string>
<string name="show_buffet">Buffet immer anzeigen</string> <string name="show_buffet">Buffet immer anzeigen</string>
<!-- dialogs --> <!-- dialogs -->
@ -47,4 +50,17 @@
<string name="error">Fehler</string> <string name="error">Fehler</string>
<string name="timetable_error">Stundenplan konnte nicht geladen werden!</string> <string name="timetable_error">Stundenplan konnte nicht geladen werden!</string>
<!-- shortcuts -->
<string name="shortcut_mensa_short">Mensa</string>
<string name="shortcut_mensa_long">Mensa</string>
<string name="shortcut_mensa_disabled">Mensa deaktiviert</string>
<string name="shortcut_timetable_short">Stundenplan</string>
<string name="shortcut_timetable_long">Stundenplan</string>
<string name="shortcut_timetable_disabled">Stundenplan deaktiviert</string>
<string name="shortcut_moodle_short">Moodle</string>
<string name="shortcut_moodle_long">Moodle</string>
<string name="shortcut_moodle_disabled">Moodle deaktiviert</string>
</resources> </resources>

View File

@ -20,12 +20,15 @@
<string name="no_more_food">No more Food this week</string> <string name="no_more_food">No more Food this week</string>
<string name="no_lesson_today">"No lecture today!"</string> <string name="no_lesson_today">"No lecture today!"</string>
<!-- fragment_timetable -->
<string name="add_lesson">Add a lesson</string>
<!-- fragment_settings --> <!-- fragment_settings -->
<string name="info">Info</string> <string name="info">Info</string>
<string name="user">User</string> <string name="user">User</string>
<string name="course_desc">Tap to change course</string> <string name="course_desc">Tap to change course</string>
<string name="about_dialog_heading">About</string> <string name="about_dialog_heading">About</string>
<string name="about_dialog_text" translatable="false">"This software is made by @Seil0 and is published under the terms and conditions of GPL 3. For further information visit \ngit.mosad.xyz/Seil0/ProjectLaogai \n\n© 2018-2019 seil0@mosad.xyz "</string> <string name="about_dialog_text" translatable="false">"This software is made by @Seil0 and is published under the terms and conditions of GPL 3. For further information visit \ngit.mosad.xyz/Seil0/ProjectLaogai \n\n© 2018-2020 seil0@mosad.xyz "</string>
<string name="about_txtView" translatable="false">hso App by @Seil0</string> <string name="about_txtView" translatable="false">hso App by @Seil0</string>
<string name="about_version" translatable="false">Version %1$s (%2$s)</string> <string name="about_version" translatable="false">Version %1$s (%2$s)</string>
<string name="licenses">Licenses</string> <string name="licenses">Licenses</string>
@ -34,9 +37,9 @@
<string name="themeDark">Dark</string> <string name="themeDark">Dark</string>
<string name="themeBlack">Black</string> <string name="themeBlack">Black</string>
<string name="primary_color">Primary color</string> <string name="primary_color">Primary color</string>
<string name="primary_color_desc">The primary color, default is black.</string> <string name="primary_color_desc">Tap to change, default is black.</string>
<string name="accent_color">Accent color</string> <string name="accent_color">Accent color</string>
<string name="accent_color_desc">The accent color, default is indigo.</string> <string name="accent_color_desc">Tap to change, default is indigo.</string>
<string name="show_buffet">Always show buffet</string> <string name="show_buffet">Always show buffet</string>
<!-- dialogs --> <!-- dialogs -->
@ -59,7 +62,21 @@
<string name="error">Error</string> <string name="error">Error</string>
<string name="timetable_error">Could not load timetable!"</string> <string name="timetable_error">Could not load timetable!"</string>
<!-- shortcuts -->
<string name="shortcut_mensa_short">Mensa</string>
<string name="shortcut_mensa_long">Mensa</string>
<string name="shortcut_mensa_disabled">Mensa disabled</string>
<string name="shortcut_timetable_short">Timetable</string>
<string name="shortcut_timetable_long">Timetable</string>
<string name="shortcut_timetable_disabled">Timetable disabled</string>
<string name="shortcut_moodle_short">Moodle</string>
<string name="shortcut_moodle_long">Moodle</string>
<string name="shortcut_moodle_disabled">Moodle disabled</string>
<!-- save keys --> <!-- save keys -->
<string name="preference_file_key" translatable="false">org.mosad.seil0.projectlaogai_preferences</string>
<string name="save_key_course" translatable="false">org.mosad.seil0.projectlaogai.course</string> <string name="save_key_course" translatable="false">org.mosad.seil0.projectlaogai.course</string>
<string name="save_key_courseTTLink" translatable="false">org.mosad.seil0.projectlaogai.courseTTLink</string> <string name="save_key_courseTTLink" translatable="false">org.mosad.seil0.projectlaogai.courseTTLink</string>
<string name="save_key_colorPrimary" translatable="false">org.mosad.seil0.projectlaogai.colorPrimary</string> <string name="save_key_colorPrimary" translatable="false">org.mosad.seil0.projectlaogai.colorPrimary</string>

View File

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

View 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 workloads

View File

@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-6.0.1-bin.zip
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists

4
gradlew vendored
View File

@ -125,8 +125,8 @@ if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi fi
# For Cygwin, switch paths to Windows format before running java # For Cygwin or MSYS, switch paths to Windows format before running java
if $cygwin ; then if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"` APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"` JAVACMD=`cygpath --unix "$JAVACMD"`