Compare commits
16 Commits
Author | SHA1 | Date | |
---|---|---|---|
ac37bce145 | |||
6fd82254e0
|
|||
0dd8ba9475
|
|||
770e9a255d | |||
4589badbfc
|
|||
74f75bfbde | |||
a00c651bfd | |||
77757ad9ca | |||
fe111ac56b | |||
2bd86ff6bb | |||
dbaf496a79 | |||
77326a8ed6 | |||
9fc897e194 | |||
f9ac219ec6 | |||
ff1d353cae | |||
6e5cf29eaa |
@ -1,5 +1,10 @@
|
|||||||
|

|
||||||
|
[](https://www.gnu.org/licenses/gpl-3.0)
|
||||||
|
|
||||||
# ProjectLaogai "hso App"
|
# ProjectLaogai "hso App"
|
||||||
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://f-droid.org/badge/get-it-on.png" height="75">](https://f-droid.org/packages/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
|
||||||
|
@ -12,8 +12,8 @@ android {
|
|||||||
applicationId "org.mosad.seil0.projectlaogai"
|
applicationId "org.mosad.seil0.projectlaogai"
|
||||||
minSdkVersion 21
|
minSdkVersion 21
|
||||||
targetSdkVersion 28
|
targetSdkVersion 28
|
||||||
versionCode 12
|
versionCode 13
|
||||||
versionName "0.4.0"
|
versionName "0.4.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")
|
||||||
@ -37,12 +37,13 @@ dependencies {
|
|||||||
implementation 'org.jetbrains.anko:anko-commons:0.10.8'
|
implementation 'org.jetbrains.anko:anko-commons:0.10.8'
|
||||||
implementation 'androidx.appcompat:appcompat:1.0.2'
|
implementation 'androidx.appcompat:appcompat:1.0.2'
|
||||||
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-alpha3'
|
implementation 'androidx.constraintlayout:constraintlayout:2.0.0-alpha5'
|
||||||
|
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.0.0'
|
||||||
implementation 'com.google.android.material:material:1.0.0'
|
implementation 'com.google.android.material:material:1.0.0'
|
||||||
implementation 'com.google.code.gson:gson:2.8.5'
|
implementation 'com.google.code.gson:gson:2.8.5'
|
||||||
implementation 'com.afollestad:aesthetic:1.0.0-beta05'
|
implementation 'com.afollestad:aesthetic:1.0.0-beta05'
|
||||||
implementation 'com.afollestad.material-dialogs:core:2.6.0'
|
implementation 'com.afollestad.material-dialogs:core:2.8.1'
|
||||||
implementation 'com.afollestad.material-dialogs:color:2.6.0'
|
implementation 'com.afollestad.material-dialogs:color:2.8.1'
|
||||||
|
|
||||||
|
|
||||||
testImplementation 'junit:junit:4.12'
|
testImplementation 'junit:junit:4.12'
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
<application
|
<application
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
|
android:fullBackupContent="@xml/backup_descriptor"
|
||||||
android:icon="@mipmap/ic_laogai_icon"
|
android:icon="@mipmap/ic_laogai_icon"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:roundIcon="@mipmap/ic_laogai_icon"
|
android:roundIcon="@mipmap/ic_laogai_icon"
|
||||||
|
@ -68,7 +68,7 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
|
|||||||
Aesthetic.config {
|
Aesthetic.config {
|
||||||
colorPrimary(Color.BLACK)
|
colorPrimary(Color.BLACK)
|
||||||
colorPrimaryDark(Color.BLACK)
|
colorPrimaryDark(Color.BLACK)
|
||||||
colorAccent(Color.parseColor("#FF1744"))
|
colorAccent(Color.parseColor("#3F51B5"))
|
||||||
apply()
|
apply()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -162,10 +162,10 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
|
|||||||
* load the mensa menus of the current week
|
* load the mensa menus of the current week
|
||||||
*/
|
*/
|
||||||
private fun load() {
|
private fun load() {
|
||||||
// load the settings
|
|
||||||
PreferencesController.load(this) // this must be finished before doing anything else
|
|
||||||
|
|
||||||
val startupTime = measureTimeMillis {
|
val startupTime = measureTimeMillis {
|
||||||
|
// load the settings
|
||||||
|
PreferencesController.load(this) // this must be finished before doing anything else
|
||||||
|
|
||||||
val tcor = TCoRAPIController(this)
|
val tcor = TCoRAPIController(this)
|
||||||
val currentTime = System.currentTimeMillis() / 1000
|
val currentTime = System.currentTimeMillis() / 1000
|
||||||
val currentDay = Calendar.getInstance().get(Calendar.DAY_OF_WEEK)
|
val currentDay = Calendar.getInstance().get(Calendar.DAY_OF_WEEK)
|
||||||
@ -179,8 +179,8 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
|
|||||||
// update blocking if a) it`s monday and the last cache was not on a monday or b) the cache is older than 6 days
|
// update blocking if a) it`s monday and the last cache was not on a monday or b) the cache is older than 6 days
|
||||||
if((currentDay == Calendar.MONDAY && timetableCacheDay != Calendar.MONDAY) || (System.currentTimeMillis() / 1000) - timetableCacheTime > 518400) {
|
if((currentDay == Calendar.MONDAY && timetableCacheDay != Calendar.MONDAY) || (System.currentTimeMillis() / 1000) - timetableCacheTime > 518400) {
|
||||||
println("updating timetable after sunday!")
|
println("updating timetable after sunday!")
|
||||||
val jobA = tcor.getTimetable(cCourse.courseName, 0)
|
val jobA = TCoRAPIController.getTimetable(cCourse.courseName, 0, this)
|
||||||
val jobB = tcor.getTimetable(cCourse.courseName, 1)
|
val jobB = TCoRAPIController.getTimetable(cCourse.courseName, 1, this)
|
||||||
|
|
||||||
jobA.get()
|
jobA.get()
|
||||||
jobB.get()
|
jobB.get()
|
||||||
@ -192,7 +192,7 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
|
|||||||
// update blocking if it's sunday after 1500
|
// update blocking if it's sunday after 1500
|
||||||
// TODO and the last update was before 1500
|
// TODO and the last update was before 1500
|
||||||
if(currentDay == Calendar.SUNDAY && cal.get(Calendar.HOUR_OF_DAY) >= 15) {
|
if(currentDay == Calendar.SUNDAY && cal.get(Calendar.HOUR_OF_DAY) >= 15) {
|
||||||
val jobA = tcor.getMensa()
|
val jobA = TCoRAPIController.getMensa(this)
|
||||||
jobA.get()
|
jobA.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -205,14 +205,14 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
|
|||||||
tcor.getCoursesList()
|
tcor.getCoursesList()
|
||||||
|
|
||||||
if(currentTime - mensaCacheTime > 10800)
|
if(currentTime - mensaCacheTime > 10800)
|
||||||
tcor.getMensa()
|
TCoRAPIController.getMensa(this)
|
||||||
|
|
||||||
if(currentTime - timetableCacheTime > 10800) {
|
if(currentTime - timetableCacheTime > 10800) {
|
||||||
tcor.getTimetable(cCourse.courseName, 0)
|
TCoRAPIController.getTimetable(cCourse.courseName, 0, this)
|
||||||
tcor.getTimetable(cCourse.courseName, 1)
|
TCoRAPIController.getTimetable(cCourse.courseName, 1, this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
println("Completed in $startupTime ms")
|
println("startup completed in $startupTime ms")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -42,6 +42,53 @@ class CacheController(cont: Context) {
|
|||||||
var mensaCurrentWeek = MensaWeek()
|
var mensaCurrentWeek = MensaWeek()
|
||||||
var mensaNextWeek = MensaWeek()
|
var mensaNextWeek = MensaWeek()
|
||||||
var timetables = ArrayList<TimetableWeek>()
|
var timetables = ArrayList<TimetableWeek>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* read current and next weeks mensa menus from the cached file
|
||||||
|
*/
|
||||||
|
fun readMensa(context: Context) {
|
||||||
|
val file = File(context.filesDir, "mensa.json")
|
||||||
|
|
||||||
|
// make sure the file exists
|
||||||
|
if (!file.exists()) {
|
||||||
|
TCoRAPIController.getMensa(context).get()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
val fileReader = FileReader(file)
|
||||||
|
val bufferedReader = BufferedReader(fileReader)
|
||||||
|
val mensaObject = JsonParser().parse(bufferedReader.readLine()).asJsonObject
|
||||||
|
|
||||||
|
val currentWeek = mensaObject.getAsJsonObject("currentWeek")
|
||||||
|
val nextWeek = mensaObject.getAsJsonObject("nextWeek")
|
||||||
|
|
||||||
|
mensaCurrentWeek = Gson().fromJson(currentWeek, MensaWeek().javaClass)
|
||||||
|
mensaNextWeek = Gson().fromJson(nextWeek, MensaWeek().javaClass)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* read the weeks timetable from the cached file
|
||||||
|
* @param courseName the course name (e.g AI1)
|
||||||
|
* @param week the week to read (0 for the current and so on)
|
||||||
|
*/
|
||||||
|
fun readTimetable(courseName: String, week: Int, context: Context) {
|
||||||
|
val file = File(context.filesDir, "timetable-$courseName-$week.json")
|
||||||
|
|
||||||
|
// make sure the file exists
|
||||||
|
if (!file.exists())
|
||||||
|
TCoRAPIController.getTimetable(courseName, week, context).get()
|
||||||
|
|
||||||
|
val fileReader = FileReader(file)
|
||||||
|
val bufferedReader = BufferedReader(fileReader)
|
||||||
|
val timetableObject = JsonParser().parse(bufferedReader.readLine()).asJsonObject
|
||||||
|
|
||||||
|
// make sure you add the single weeks in the exact order!
|
||||||
|
if (timetables.size == week) {
|
||||||
|
timetables.add(Gson().fromJson(timetableObject.getAsJsonObject("timetable"), TimetableWeek().javaClass))
|
||||||
|
} else if (timetables.size >= week) {
|
||||||
|
timetables[week] = Gson().fromJson(timetableObject.getAsJsonObject("timetable"), TimetableWeek().javaClass)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -50,16 +97,16 @@ class CacheController(cont: Context) {
|
|||||||
*/
|
*/
|
||||||
fun readStartCache(courseName: String) {
|
fun readStartCache(courseName: String) {
|
||||||
readCoursesList()
|
readCoursesList()
|
||||||
readMensa()
|
readMensa(context)
|
||||||
readTimetable(courseName, 0)
|
readTimetable(courseName, 0, context)
|
||||||
readTimetable(courseName, 1)
|
readTimetable(courseName, 1, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* read the courses list from the cached file
|
* read the courses list from the cached file
|
||||||
* add them to the coursesList object
|
* add them to the coursesList object
|
||||||
*/
|
*/
|
||||||
fun readCoursesList() {
|
private fun readCoursesList() {
|
||||||
val file = File(context.filesDir, "courses.json")
|
val file = File(context.filesDir, "courses.json")
|
||||||
|
|
||||||
// make sure the file exists
|
// make sure the file exists
|
||||||
@ -73,50 +120,4 @@ class CacheController(cont: Context) {
|
|||||||
coursesList = Gson().fromJson(coursesObject.getAsJsonArray("courses"), object : TypeToken<List<Course>>() {}.type)
|
coursesList = Gson().fromJson(coursesObject.getAsJsonArray("courses"), object : TypeToken<List<Course>>() {}.type)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* read current and next weeks mensa menus from the cached file
|
|
||||||
*/
|
|
||||||
fun readMensa() {
|
|
||||||
val file = File(context.filesDir, "mensa.json")
|
|
||||||
|
|
||||||
// make sure the file exists
|
|
||||||
if (!file.exists()) {
|
|
||||||
TCoRAPIController(context).getMensa().get()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
val fileReader = FileReader(file)
|
|
||||||
val bufferedReader = BufferedReader(fileReader)
|
|
||||||
val mensaObject = JsonParser().parse(bufferedReader.readLine()).asJsonObject
|
|
||||||
|
|
||||||
val currentWeek = mensaObject.getAsJsonObject("currentWeek")
|
|
||||||
val nextWeek = mensaObject.getAsJsonObject("nextWeek")
|
|
||||||
|
|
||||||
mensaCurrentWeek = Gson().fromJson(currentWeek, MensaWeek().javaClass)
|
|
||||||
mensaNextWeek = Gson().fromJson(nextWeek, MensaWeek().javaClass)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* read the weeks timetable from the cached file
|
|
||||||
* @param courseName the course name (e.g AI1)
|
|
||||||
* @param week the week to read (0 for the current and so on)
|
|
||||||
*/
|
|
||||||
fun readTimetable(courseName: String, week: Int) {
|
|
||||||
val file = File(context.filesDir, "timetable-$courseName-$week.json")
|
|
||||||
|
|
||||||
// make sure the file exists
|
|
||||||
if (!file.exists())
|
|
||||||
TCoRAPIController(context).getTimetable(courseName, week).get()
|
|
||||||
|
|
||||||
val fileReader = FileReader(file)
|
|
||||||
val bufferedReader = BufferedReader(fileReader)
|
|
||||||
val timetableObject = JsonParser().parse(bufferedReader.readLine()).asJsonObject
|
|
||||||
|
|
||||||
// make sure you add the single weeks in the exact order!
|
|
||||||
if (timetables.size == week) {
|
|
||||||
timetables.add(Gson().fromJson(timetableObject.getAsJsonObject("timetable"), TimetableWeek().javaClass))
|
|
||||||
} else if (timetables.size >= week) {
|
|
||||||
timetables[week] = Gson().fromJson(timetableObject.getAsJsonObject("timetable"), TimetableWeek().javaClass)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -34,6 +34,48 @@ import java.net.URL
|
|||||||
class TCoRAPIController(cont: Context) {
|
class TCoRAPIController(cont: Context) {
|
||||||
private val context = cont
|
private val context = cont
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
/**
|
||||||
|
* get the json object from tcor api and write it as file (cache)
|
||||||
|
*/
|
||||||
|
fun getMensa(context: Context) = doAsync {
|
||||||
|
val url = URL("https://tcor.mosad.xyz/mensamenu")
|
||||||
|
val file = File(context.filesDir, "mensa.json")
|
||||||
|
|
||||||
|
// read data from the API
|
||||||
|
val mensaObject = JSONObject(url.readText()) //JSONObject(inReader.readLine())
|
||||||
|
|
||||||
|
// write the json object to a file
|
||||||
|
val writer = BufferedWriter(FileWriter(file))
|
||||||
|
writer.write(mensaObject.toString())
|
||||||
|
writer.close()
|
||||||
|
|
||||||
|
// update cache time
|
||||||
|
mensaCacheTime = System.currentTimeMillis() / 1000
|
||||||
|
PreferencesController.save(context)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get the json object from tcor api and write it as file (cache)
|
||||||
|
*/
|
||||||
|
fun getTimetable(courseName: String, week: Int, context: Context) = doAsync {
|
||||||
|
val url = URL("https://tcor.mosad.xyz/timetable?courseName=$courseName&week=$week")
|
||||||
|
val file = File(context.filesDir, "timetable-$courseName-$week.json")
|
||||||
|
|
||||||
|
// read data from the API
|
||||||
|
val mensaObject = JSONObject(url.readText()) //JSONObject(inReader.readLine())
|
||||||
|
|
||||||
|
// write the json object to a file
|
||||||
|
val writer = BufferedWriter(FileWriter(file))
|
||||||
|
writer.write(mensaObject.toString())
|
||||||
|
writer.close()
|
||||||
|
|
||||||
|
// update cache time
|
||||||
|
timetableCacheTime = System.currentTimeMillis() / 1000
|
||||||
|
PreferencesController.save(context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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)
|
||||||
*/
|
*/
|
||||||
@ -53,44 +95,4 @@ class TCoRAPIController(cont: Context) {
|
|||||||
coursesCacheTime = System.currentTimeMillis() / 1000
|
coursesCacheTime = System.currentTimeMillis() / 1000
|
||||||
PreferencesController.save(context)
|
PreferencesController.save(context)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* get the json object from tcor api and write it as file (cache)
|
|
||||||
*/
|
|
||||||
fun getMensa() = doAsync {
|
|
||||||
val url = URL("https://tcor.mosad.xyz/mensamenu")
|
|
||||||
val file = File(context.filesDir, "mensa.json")
|
|
||||||
|
|
||||||
// read data from the API
|
|
||||||
val mensaObject = JSONObject(url.readText()) //JSONObject(inReader.readLine())
|
|
||||||
|
|
||||||
// write the json object to a file
|
|
||||||
val writer = BufferedWriter(FileWriter(file))
|
|
||||||
writer.write(mensaObject.toString())
|
|
||||||
writer.close()
|
|
||||||
|
|
||||||
// update cache time
|
|
||||||
mensaCacheTime = System.currentTimeMillis() / 1000
|
|
||||||
PreferencesController.save(context)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* get the json object from tcor api and write it as file (cache)
|
|
||||||
*/
|
|
||||||
fun getTimetable(courseName: String, week: Int) = doAsync {
|
|
||||||
val url = URL("https://tcor.mosad.xyz/timetable?courseName=$courseName&week=$week")
|
|
||||||
val file = File(context.filesDir, "timetable-$courseName-$week.json")
|
|
||||||
|
|
||||||
// read data from the API
|
|
||||||
val mensaObject = JSONObject(url.readText()) //JSONObject(inReader.readLine())
|
|
||||||
|
|
||||||
// write the json object to a file
|
|
||||||
val writer = BufferedWriter(FileWriter(file))
|
|
||||||
writer.write(mensaObject.toString())
|
|
||||||
writer.close()
|
|
||||||
|
|
||||||
// update cache time
|
|
||||||
timetableCacheTime = System.currentTimeMillis() / 1000
|
|
||||||
PreferencesController.save(context)
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -141,7 +141,7 @@ class HomeFragment : Fragment() {
|
|||||||
} else {
|
} else {
|
||||||
MaterialDialog(context!!)
|
MaterialDialog(context!!)
|
||||||
.title(R.string.error)
|
.title(R.string.error)
|
||||||
.message(R.string.gen_tt_error)
|
.message(R.string.timetable_error)
|
||||||
.show()
|
.show()
|
||||||
// TODO log the error and send feedback
|
// TODO log the error and send feedback
|
||||||
}
|
}
|
||||||
|
@ -26,15 +26,15 @@ import android.os.Bundle
|
|||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.LinearLayout
|
|
||||||
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 org.jetbrains.anko.doAsync
|
||||||
import org.jetbrains.anko.uiThread
|
import org.jetbrains.anko.uiThread
|
||||||
import org.mosad.seil0.projectlaogai.R
|
import org.mosad.seil0.projectlaogai.controller.CacheController
|
||||||
import org.mosad.seil0.projectlaogai.controller.CacheController.Companion.mensaCurrentWeek
|
import org.mosad.seil0.projectlaogai.controller.CacheController.Companion.mensaCurrentWeek
|
||||||
import org.mosad.seil0.projectlaogai.controller.CacheController.Companion.mensaNextWeek
|
import org.mosad.seil0.projectlaogai.controller.CacheController.Companion.mensaNextWeek
|
||||||
import org.mosad.seil0.projectlaogai.controller.PreferencesController.Companion.cShowBuffet
|
import org.mosad.seil0.projectlaogai.controller.PreferencesController.Companion.cShowBuffet
|
||||||
|
import org.mosad.seil0.projectlaogai.controller.TCoRAPIController
|
||||||
import org.mosad.seil0.projectlaogai.hsoparser.MensaWeek
|
import org.mosad.seil0.projectlaogai.hsoparser.MensaWeek
|
||||||
import org.mosad.seil0.projectlaogai.hsoparser.NotRetardedCalendar
|
import org.mosad.seil0.projectlaogai.hsoparser.NotRetardedCalendar
|
||||||
import org.mosad.seil0.projectlaogai.uicomponents.DayCardView
|
import org.mosad.seil0.projectlaogai.uicomponents.DayCardView
|
||||||
@ -46,26 +46,29 @@ import org.mosad.seil0.projectlaogai.uicomponents.MealLinearLayout
|
|||||||
*/
|
*/
|
||||||
class MensaFragment : Fragment() {
|
class MensaFragment : Fragment() {
|
||||||
|
|
||||||
private lateinit var linLayoutMensaFragment: LinearLayout
|
|
||||||
|
|
||||||
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_mensa, container, false)
|
val view: View = inflater.inflate(org.mosad.seil0.projectlaogai.R.layout.fragment_mensa, container, false)
|
||||||
|
|
||||||
linLayoutMensaFragment = view.findViewById(R.id.linLayout_Mensa)
|
// init actions
|
||||||
|
refreshAction()
|
||||||
|
|
||||||
// add the current week (week starts on sunday)
|
// add the current week (week starts on sunday)
|
||||||
val dayCurrent = if(NotRetardedCalendar().getDayOfWeekIndex() == 6) 0 else NotRetardedCalendar().getDayOfWeekIndex()
|
val dayCurrent = if(NotRetardedCalendar().getDayOfWeekIndex() == 6) 0 else NotRetardedCalendar().getDayOfWeekIndex()
|
||||||
addWeek(mensaCurrentWeek, dayCurrent).get()
|
addWeek(mensaCurrentWeek, dayCurrent).get()
|
||||||
|
|
||||||
// add the next week
|
// add the next week
|
||||||
addWeek(mensaNextWeek, 0).get()
|
addWeek(mensaNextWeek, 0)
|
||||||
|
|
||||||
|
// TODO should we show a info if there is no more food this & next week?
|
||||||
|
|
||||||
return view
|
return view
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* add all menus from dayStart to Friday for a given week
|
* add all menus from dayStart to Friday for a given week
|
||||||
|
* @param menusWeek menu of type MensaWeek you want to add
|
||||||
|
* @param dayStart the first day of the week to add
|
||||||
*/
|
*/
|
||||||
private fun addWeek(menusWeek: MensaWeek, dayStart: Int) = doAsync {
|
private fun addWeek(menusWeek: MensaWeek, dayStart: Int) = doAsync {
|
||||||
|
|
||||||
@ -75,7 +78,9 @@ class MensaFragment : Fragment() {
|
|||||||
for (dayIndex in dayStart..4) {
|
for (dayIndex in dayStart..4) {
|
||||||
var helpMeal = MealLinearLayout(context)
|
var helpMeal = MealLinearLayout(context)
|
||||||
val dayCardView = DayCardView(context!!)
|
val dayCardView = DayCardView(context!!)
|
||||||
dayCardView.setDayHeading(menusWeek.days[dayIndex].meals[0].day)
|
|
||||||
|
if(menusWeek.days[dayIndex].meals.isNotEmpty())
|
||||||
|
dayCardView.setDayHeading(menusWeek.days[dayIndex].meals[0].day)
|
||||||
|
|
||||||
for (meal in menusWeek.days[dayIndex].meals) {
|
for (meal in menusWeek.days[dayIndex].meals) {
|
||||||
val mealLayout = MealLinearLayout(context)
|
val mealLayout = MealLinearLayout(context)
|
||||||
@ -97,4 +102,40 @@ class MensaFragment : Fragment() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* initialize the refresh action
|
||||||
|
*/
|
||||||
|
private fun refreshAction() = doAsync {
|
||||||
|
uiThread {
|
||||||
|
// set the refresh listener
|
||||||
|
refreshLayout_Mensa.setOnRefreshListener {
|
||||||
|
updateMensaScreen()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* refresh the mensa cache and update the mensa screen
|
||||||
|
*/
|
||||||
|
private fun updateMensaScreen() = doAsync {
|
||||||
|
// update the cache
|
||||||
|
TCoRAPIController.getMensa(context!!).get() // blocking since we want the new data
|
||||||
|
CacheController.readMensa(context!!)
|
||||||
|
|
||||||
|
uiThread {
|
||||||
|
// remove all menus from the layout
|
||||||
|
linLayout_Mensa.removeAllViews()
|
||||||
|
|
||||||
|
// add the refreshed menus
|
||||||
|
val dayCurrent = if (NotRetardedCalendar().getDayOfWeekIndex() == 6) 0 else NotRetardedCalendar().getDayOfWeekIndex()
|
||||||
|
addWeek(mensaCurrentWeek, dayCurrent).get()
|
||||||
|
|
||||||
|
// add the next week
|
||||||
|
addWeek(mensaNextWeek, 0)
|
||||||
|
|
||||||
|
refreshLayout_Mensa.isRefreshing = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -176,11 +176,11 @@ class SettingsFragment : Fragment() {
|
|||||||
PreferencesController.save(context)
|
PreferencesController.save(context)
|
||||||
|
|
||||||
// update current & next weeks timetable
|
// update current & next weeks timetable
|
||||||
TCoRAPIController(context).getTimetable(cCourse.courseName, 0)
|
TCoRAPIController.getTimetable(cCourse.courseName, 0, context).get() // blocking since we want the new data
|
||||||
TCoRAPIController(context).getTimetable(cCourse.courseName, 1)
|
TCoRAPIController.getTimetable(cCourse.courseName, 1, context).get() // blocking since we want the new data
|
||||||
|
|
||||||
CacheController(context).readTimetable(cCourse.courseName, 0)
|
CacheController.readTimetable(cCourse.courseName, 0, context)
|
||||||
CacheController(context).readTimetable(cCourse.courseName, 1)
|
CacheController.readTimetable(cCourse.courseName, 1, context)
|
||||||
|
|
||||||
uiThread {
|
uiThread {
|
||||||
dialog.dismiss()
|
dialog.dismiss()
|
||||||
|
@ -27,13 +27,18 @@ import android.view.LayoutInflater
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
|
import com.afollestad.materialdialogs.MaterialDialog
|
||||||
import kotlinx.android.synthetic.main.fragment_timetable.*
|
import kotlinx.android.synthetic.main.fragment_timetable.*
|
||||||
import org.jetbrains.anko.doAsync
|
import org.jetbrains.anko.doAsync
|
||||||
import org.jetbrains.anko.uiThread
|
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.Companion.timetables
|
import org.mosad.seil0.projectlaogai.controller.CacheController.Companion.timetables
|
||||||
|
import org.mosad.seil0.projectlaogai.controller.PreferencesController.Companion.cCourse
|
||||||
|
import org.mosad.seil0.projectlaogai.controller.TCoRAPIController
|
||||||
import org.mosad.seil0.projectlaogai.hsoparser.DataTypes
|
import org.mosad.seil0.projectlaogai.hsoparser.DataTypes
|
||||||
import org.mosad.seil0.projectlaogai.hsoparser.NotRetardedCalendar
|
import org.mosad.seil0.projectlaogai.hsoparser.NotRetardedCalendar
|
||||||
|
import org.mosad.seil0.projectlaogai.hsoparser.TimetableWeek
|
||||||
import org.mosad.seil0.projectlaogai.uicomponents.*
|
import org.mosad.seil0.projectlaogai.uicomponents.*
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.*
|
import java.util.*
|
||||||
@ -44,37 +49,51 @@ import java.util.*
|
|||||||
*/
|
*/
|
||||||
class TimeTableFragment : Fragment() {
|
class TimeTableFragment : Fragment() {
|
||||||
|
|
||||||
|
private val formatter = SimpleDateFormat("E dd.MM", Locale.getDefault()) // TODO change to android call when min api is 24
|
||||||
|
|
||||||
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_timetable, container, false)
|
val view: View = inflater.inflate(R.layout.fragment_timetable, container, false)
|
||||||
|
|
||||||
|
// init actions
|
||||||
|
refreshAction()
|
||||||
|
|
||||||
if (timetables[0].days.isNotEmpty() && timetables[1].days.isNotEmpty()) {
|
if (timetables[0].days.isNotEmpty() && timetables[1].days.isNotEmpty()) {
|
||||||
addWeeks()
|
addInitWeeks()
|
||||||
} else {
|
} else {
|
||||||
// TODO show card with error msg
|
MaterialDialog(context!!)
|
||||||
|
.title(R.string.error)
|
||||||
|
.message(R.string.timetable_error)
|
||||||
|
.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
return view
|
return view
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* add the all days with at least one lesson to the timetable screen
|
* add the current and next weeks lessons
|
||||||
*/
|
*/
|
||||||
private fun addWeeks() = doAsync {
|
private fun addInitWeeks() = doAsync {
|
||||||
val dayIndex = NotRetardedCalendar().getDayOfWeekIndex()
|
val dayIndex = NotRetardedCalendar().getDayOfWeekIndex()
|
||||||
val formatter = SimpleDateFormat("E dd.MM", Locale.getDefault()) // TODO change to android call when min api is 24
|
|
||||||
val calendar = Calendar.getInstance()
|
val calendar = Calendar.getInstance()
|
||||||
|
|
||||||
|
// add current week
|
||||||
|
addWeek(dayIndex, 5, timetables[0], calendar).get()
|
||||||
|
|
||||||
|
// add next week
|
||||||
|
addWeek(0, dayIndex - 1, timetables[1], calendar)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addWeek(dayStart: Int, dayEnd: Int, timetable: TimetableWeek, calendar: Calendar) = doAsync {
|
||||||
uiThread {
|
uiThread {
|
||||||
|
|
||||||
// add the current week
|
for (day in dayStart..dayEnd) {
|
||||||
for (day in dayIndex..5) {
|
|
||||||
var helpLesson = LessonLinearLayout(context)
|
var helpLesson = LessonLinearLayout(context)
|
||||||
val dayCardView = DayCardView(context!!)
|
val dayCardView = DayCardView(context!!)
|
||||||
dayCardView.setDayHeading(formatter.format(calendar.time))
|
dayCardView.setDayHeading(formatter.format(calendar.time))
|
||||||
|
|
||||||
// for each timeslot of the day
|
// for each timeslot of the day
|
||||||
for ((tsIndex, timeslot) in timetables[0].days[day].timeslots.withIndex()) {
|
for ((tsIndex, timeslot) in timetable.days[day].timeslots.withIndex()) {
|
||||||
|
|
||||||
for(lesson in timeslot) {
|
for(lesson in timeslot) {
|
||||||
|
|
||||||
@ -102,43 +121,46 @@ class TimeTableFragment : Fragment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
calendar.add(Calendar.DATE, 1) // before this we are at a sunday (no lecture on sundays!)
|
calendar.add(Calendar.DATE, 1) // before this we are at a sunday (no lecture on sundays!)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// add the next week
|
/**
|
||||||
for (day in 0..(dayIndex - 1)) {
|
* initialize the refresh action
|
||||||
var helpLesson = LessonLinearLayout(context!!)
|
*/
|
||||||
val dayCardView = DayCardView(context!!)
|
private fun refreshAction() = doAsync {
|
||||||
dayCardView.setDayHeading(formatter.format(calendar.time))
|
uiThread {
|
||||||
|
// set the refresh listener
|
||||||
// for each timeslot of the day
|
refreshLayout_Timetable.setOnRefreshListener {
|
||||||
for ((tsIndex, timeslot) in timetables[1].days[day].timeslots.withIndex()) {
|
updateTimetableScreen()
|
||||||
|
|
||||||
for(lesson in timeslot) {
|
|
||||||
|
|
||||||
if(lesson.lessonSubject.isNotEmpty()) {
|
|
||||||
|
|
||||||
val lessonLayout = LessonLinearLayout(context!!)
|
|
||||||
lessonLayout.setLesson(lesson, DataTypes().getTime()[tsIndex])
|
|
||||||
dayCardView.getLinLayoutDay().addView(lessonLayout)
|
|
||||||
|
|
||||||
if (lesson != timeslot.last())
|
|
||||||
lessonLayout.disableDivider()
|
|
||||||
|
|
||||||
helpLesson = lessonLayout
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
helpLesson.disableDivider()
|
|
||||||
calendar.add(Calendar.DATE, 1)
|
|
||||||
|
|
||||||
// if there are no lessons don't show the dayCardView
|
|
||||||
if (dayCardView.getLinLayoutDay().childCount > 1)
|
|
||||||
linLayout_Timetable.addView(dayCardView)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun updateTimetableScreen() = doAsync {
|
||||||
|
// update the cache
|
||||||
|
TCoRAPIController.getTimetable(cCourse.courseName, 0, context!!).get() // blocking since we want the new data
|
||||||
|
TCoRAPIController.getTimetable(cCourse.courseName, 1, context!!).get() // blocking since we want the new data
|
||||||
|
|
||||||
|
CacheController.readTimetable(cCourse.courseName, 0, context!!)
|
||||||
|
CacheController.readTimetable(cCourse.courseName, 1, context!!)
|
||||||
|
|
||||||
|
uiThread {
|
||||||
|
// remove all menus from the layout
|
||||||
|
linLayout_Timetable.removeAllViews()
|
||||||
|
|
||||||
|
// add the refreshed timetables
|
||||||
|
val dayIndex = NotRetardedCalendar().getDayOfWeekIndex()
|
||||||
|
val calendar = Calendar.getInstance()
|
||||||
|
|
||||||
|
// add current week
|
||||||
|
addWeek(dayIndex, 5, timetables[0], calendar).get()
|
||||||
|
|
||||||
|
// add next week
|
||||||
|
addWeek(0, dayIndex - 1, timetables[1], calendar)
|
||||||
|
|
||||||
|
refreshLayout_Timetable.isRefreshing = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,8 @@
|
|||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content" android:id="@+id/linLayout_Home">
|
android:layout_height="wrap_content"
|
||||||
|
android:id="@+id/linLayout_Home">
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
|
||||||
|
@ -5,9 +5,10 @@
|
|||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
tools:context=".fragments.MensaFragment">
|
tools:context=".fragments.MensaFragment">
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent"
|
||||||
|
android:id="@+id/refreshLayout_Mensa">
|
||||||
|
|
||||||
<ScrollView
|
<ScrollView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@ -15,10 +16,12 @@
|
|||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content" android:id="@+id/linLayout_Mensa"
|
android:layout_height="wrap_content"
|
||||||
android:background="@color/themePrimary">
|
android:animateLayoutChanges="false"
|
||||||
</LinearLayout>
|
android:background="@color/themePrimary"
|
||||||
|
android:id="@+id/linLayout_Mensa"/>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||||
|
|
||||||
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
@ -8,6 +8,7 @@
|
|||||||
<!-- TODO: Update blank fragment layout -->
|
<!-- TODO: Update blank fragment layout -->
|
||||||
<WebView
|
<WebView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent" android:id="@+id/webView"/>
|
android:layout_height="match_parent"
|
||||||
|
android:id="@+id/webView"/>
|
||||||
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
@ -5,9 +5,10 @@
|
|||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
tools:context=".fragments.TimeTableFragment">
|
tools:context=".fragments.TimeTableFragment">
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent"
|
||||||
|
android:id="@+id/refreshLayout_Timetable">
|
||||||
|
|
||||||
<ScrollView
|
<ScrollView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@ -15,10 +16,10 @@
|
|||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content" android:id="@+id/linLayout_Timetable"
|
android:layout_height="wrap_content"
|
||||||
android:background="@color/themePrimary">
|
android:animateLayoutChanges="false"
|
||||||
</LinearLayout>
|
android:background="@color/themePrimary"
|
||||||
|
android:id="@+id/linLayout_Timetable"/>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||||
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
@ -12,8 +12,7 @@
|
|||||||
<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>
|
||||||
<string name="error">Fehler</string>
|
<string name="error">Fehler</string>
|
||||||
<string name="no_tt_error">Stundenplan konnte nicht geladen werden!</string>
|
<string name="timetable_error">Stundenplan konnte nicht geladen werden!</string>
|
||||||
<string name="gen_tt_error">Allgemeiner Stundenplan Fehler!"</string>
|
|
||||||
<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">Tippen, um den Kurs zu ändern</string>
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
<color name="colorPrimary">#000000</color>
|
<color name="colorPrimary">#000000</color>
|
||||||
<color name="colorPrimaryDark">#000000</color>
|
<color name="colorPrimaryDark">#000000</color>
|
||||||
<color name="colorAccent">#3F51B5</color>
|
<color name="colorAccent">#3F51B5</color>
|
||||||
<color name="colorMensaDay">#EBE8E9</color>
|
|
||||||
<color name="ic_launcher_background">#FFFFFF</color>
|
<color name="ic_launcher_background">#FFFFFF</color>
|
||||||
|
|
||||||
<color name="themePrimary">#FFFFFF</color>
|
<color name="themePrimary">#FFFFFF</color>
|
||||||
@ -27,6 +26,4 @@
|
|||||||
<color name="themeSecondaryLight">#FFFFFF</color>
|
<color name="themeSecondaryLight">#FFFFFF</color>
|
||||||
<color name="themeTertiaryLight">#424242</color> <!-- TODO find a better color -->
|
<color name="themeTertiaryLight">#424242</color> <!-- TODO find a better color -->
|
||||||
|
|
||||||
<color name="test">#424242</color>
|
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -20,8 +20,7 @@
|
|||||||
|
|
||||||
<string name="no_lesson_today">"No lecture today!"</string>
|
<string name="no_lesson_today">"No lecture today!"</string>
|
||||||
<string name="error">Error</string>
|
<string name="error">Error</string>
|
||||||
<string name="no_tt_error">Could not load timetable!"</string>
|
<string name="timetable_error">Could not load timetable!"</string>
|
||||||
<string name="gen_tt_error">There was an error with the timetable!"</string>
|
|
||||||
|
|
||||||
<string name="sample_user" translatable="false">SampleUser@stud.hs-offenburg.de</string>
|
<string name="sample_user" translatable="false">SampleUser@stud.hs-offenburg.de</string>
|
||||||
<string name="sample_course" translatable="false">SampleCourse 3</string>
|
<string name="sample_course" translatable="false">SampleCourse 3</string>
|
||||||
|
5
app/src/main/res/xml/backup_descriptor.xml
Normal file
5
app/src/main/res/xml/backup_descriptor.xml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<full-backup-content>
|
||||||
|
<exclude domain="file" path="mensa.json"/>
|
||||||
|
<exclude domain="file" path="courses.json"/>
|
||||||
|
</full-backup-content>
|
@ -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.21'
|
ext.kotlin_version = '1.3.31'
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
jcenter()
|
jcenter()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:3.3.2'
|
classpath 'com.android.tools.build:gradle:3.4.0'
|
||||||
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
|
||||||
|
7
fastlane/metadata/android/de/full_description.txt
Normal file
7
fastlane/metadata/android/de/full_description.txt
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
ProjectLaogai ist eine App um den Stundenplan und das Mensa-Essen der Hochschule Offenburg anzuzeigen.
|
||||||
|
|
||||||
|
Features:
|
||||||
|
* schaue was es diese und nächste WOche in der Mensa zu Essen gibt
|
||||||
|
* schaue dir deinen Stundenplan an
|
||||||
|
* öffne moodle direkt in der App
|
||||||
|
* viele lustige Bugs
|
1
fastlane/metadata/android/de/short_description.txt
Normal file
1
fastlane/metadata/android/de/short_description.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
eine App für die Hochschule Offenburg
|
@ -1,5 +1,4 @@
|
|||||||
ProjectLaogai is a app to access the timetable and the mensa menu
|
ProjectLaogai is an app to access the timetable and the mensa menu of Hochschule Offenburg.
|
||||||
of Hochschule Offenburg.
|
|
||||||
|
|
||||||
Features:
|
Features:
|
||||||
* check out the mensa menu of this and next week
|
* check out the mensa menu of this and next week
|
||||||
|
@ -1 +1 @@
|
|||||||
access the timetable and mensa menu at Hochschule Offenburg
|
an app for the Hochschule Offenburg
|
||||||
|
3
gradle/wrapper/gradle-wrapper.properties
vendored
3
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,5 +1,6 @@
|
|||||||
|
#Thu Apr 25 17:58:09 WEST 2019
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip
|
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip
|
||||||
|
Reference in New Issue
Block a user