23 Commits
0.3.3 ... 0.4.0

Author SHA1 Message Date
4971d0b1b8 added fastlane metadata 2019-04-05 15:05:29 +02:00
a87e57c80e removed versionNameSuffix 2019-04-01 18:03:26 +02:00
ee388bf5a5 removed maven repo 2019-04-01 17:55:14 +02:00
8aaf8e3647 release 0.4.0
* use Locale.getDefault() for the timetable screen
2019-04-01 10:14:00 +02:00
d645d75bbf fixed showing wrong meal of tomorrow on Wednesday 2019-03-27 19:29:54 +01:00
f97491addd added mensa sunday workaround
* update mensa blocking un sundays between 1500 and 2359
* updated material-dialogs 2.2.0 -> 2.6.0
2019-03-27 13:29:36 +01:00
e08790aaa4 show the next day with a lecture on Sundays too 2019-03-24 17:23:10 +01:00
750a808fbe the homescreen now shows the next day with a lecture
* fixed getTomorrowWeekIndex() since it would return 7 which is out of the arrays bounds
* minor clean up
2019-03-23 21:07:33 +01:00
e51a80b78d home screen redesign 2019-03-22 21:59:32 +01:00
a4eaea2918 timetable and mensa gui redesign
* the timetable and mensa screen are now the same design as the settings, much cleaner and ready for themes
2019-03-20 21:33:55 +01:00
cd3136715f spelling 2019-03-20 17:55:30 +01:00
15f1386b6e some minor gui fixes
* why was minifyEnabled = false ??????????
2019-03-19 19:51:58 +01:00
3bace6c155 Update 'README.md' 2019-03-19 19:18:34 +01:00
61716f8eb4 Update 'README.md' 2019-03-19 19:13:47 +01:00
a1410f7b80 sort of worked around the Sunday problem 2019-03-18 19:09:03 +01:00
953185425b fixed menu formatting 2019-03-17 20:52:34 +01:00
a6d14044c2 added initial course selection
* some minor gui fixes
2019-03-17 18:38:31 +01:00
f3b7ff066d added the tcor api
* drastically improved loading times, closes #14
2019-03-17 18:12:36 +01:00
040eb26dcf update app version to 0.3.90 2019-03-14 22:57:41 +01:00
1a5d2b6561 fix homescreen 2019-03-14 08:04:09 +01:00
92b60d660c updated gradle build tool to 3.3.2 2019-03-14 08:03:39 +01:00
a4eceeddc9 added 2nd week menus & option to disable buffet in the mensa tab
* the GUI now shows a second week for Mensa menus
* you can disable the buffet in the Mensa tab now
2019-03-10 13:37:13 +01:00
3e3a80442e next weeks menu & accent color
* the MensaParser can now get the next weeks menus
* it's now possible to select a accent color
2019-03-09 22:15:53 +01:00
45 changed files with 1061 additions and 954 deletions

View File

@ -1,13 +1,16 @@
# ProjectLaogai "hso App" # ProjectLaogai "hso App"
ProjectLaogai is a app to access the timetable for any course of the Hochschule Offenburg. You can also check the current weeks mensa menus. ProjectLaogai is a app to access the timetable and the mensa menu of Hochschule Offenburg.
## Features ## Features
* look up what you can eat in the mensa * check out the mensa menu of this and next week
* check your timetable * access your timetable
* open moodle
* probably some funny bugs * probably some funny bugs
## Screenshots ## Screenshots
[<img src="https://raw.githubusercontent.com/Seil0/Seil0.github.io/master/images/ProjectLaogai_HomeScreen.png" width=180>](https://github.com/Seil0/Seil0.github.io/blob/master/images/ProjectLaogai_HomeScreen.png) [<img src="https://raw.githubusercontent.com/Seil0/Seil0.github.io/master/images/Project_Laogai/ProjectLaogai_HomeScreen.png" width=180>](https://github.com/Seil0/Seil0.github.io/blob/master/images/Project_Laogai/ProjectLaogai_HomeScreen.png)
[<img src="https://raw.githubusercontent.com/Seil0/Seil0.github.io/master/images/ProjectLaogai_Mensa.png" width=180>](https://github.com/Seil0/Seil0.github.io/blob/master/images/ProjectLaogai_Mensa.png) [<img src="https://raw.githubusercontent.com/Seil0/Seil0.github.io/master/images/Project_Laogai/ProjectLaogai_Mensa.png" width=180>](https://github.com/Seil0/Seil0.github.io/blob/master/images/Project_Laogai/ProjectLaogai_Mensa.png)
[<img src="https://raw.githubusercontent.com/Seil0/Seil0.github.io/master/images/ProjectLaogai_NavDrawer.png" width=180>](https://github.com/Seil0/Seil0.github.io/blob/master/images/ProjectLaogai_NavDrawer.png) [<img src="https://raw.githubusercontent.com/Seil0/Seil0.github.io/master/images/Project_Laogai/ProjectLaogai_Timetable.png" width=180>](https://github.com/Seil0/Seil0.github.io/blob/master/images/Project_Laogai/ProjectLaogai_Timetable.png)
[<img src="https://raw.githubusercontent.com/Seil0/Seil0.github.io/master/images/Project_Laogai/ProjectLaogai_Settings.png" width=180>](https://github.com/Seil0/Seil0.github.io/blob/master/images/Project_Laogai/ProjectLaogai_Settings.png)
[<img src="https://raw.githubusercontent.com/Seil0/Seil0.github.io/master/images/Project_Laogai/ProjectLaogai_NavDrawer.png" width=180>](https://github.com/Seil0/Seil0.github.io/blob/master/images/Project_Laogai/ProjectLaogai_NavDrawer.png)
ProjectLaogai © 2019 mosad [www.mosad.xyz](http://www.mosad.xyz), Project by [@Seil0](https://git.mosad.xyz/Seil0) ProjectLaogai © 2019 mosad [www.mosad.xyz](http://www.mosad.xyz), Project by [@Seil0](https://git.mosad.xyz/Seil0)

View File

@ -12,15 +12,20 @@ android {
applicationId "org.mosad.seil0.projectlaogai" applicationId "org.mosad.seil0.projectlaogai"
minSdkVersion 21 minSdkVersion 21
targetSdkVersion 28 targetSdkVersion 28
versionCode 11 versionCode 12
versionName "0.3.3" versionName "0.4.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
resValue "string", "build_time", buildTime()
setProperty("archivesBaseName", "projectlaogai-$versionName")
} }
buildTypes { buildTypes {
release { release {
minifyEnabled false minifyEnabled false
shrinkResources false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
} }
} }
compileOptions { compileOptions {
} }
@ -29,17 +34,22 @@ 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 '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 'com.google.android.material:material:1.0.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.0-alpha3' implementation 'androidx.constraintlayout:constraintlayout:2.0.0-alpha3'
implementation 'org.jsoup:jsoup:1.11.3' implementation 'com.google.android.material:material:1.0.0'
implementation 'org.jetbrains.anko:anko-commons:0.10.8' 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.0.3' implementation 'com.afollestad.material-dialogs:core:2.6.0'
implementation 'com.afollestad.material-dialogs:color:2.0.3' implementation 'com.afollestad.material-dialogs:color:2.6.0'
testImplementation 'junit:junit:4.12' testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.1.1' androidTestImplementation 'androidx.test:runner:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
} }
static def buildTime() {
return new Date().format("yyyy-MM-dd", TimeZone.getTimeZone("UTC"))
}

View File

@ -32,27 +32,25 @@ import androidx.core.view.GravityCompat
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentTransaction import androidx.fragment.app.FragmentTransaction
import com.afollestad.aesthetic.Aesthetic import com.afollestad.aesthetic.Aesthetic
import com.afollestad.materialdialogs.MaterialDialog
import com.google.android.material.navigation.NavigationView import com.google.android.material.navigation.NavigationView
import kotlinx.android.synthetic.main.activity_main.* import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.app_bar_main.* import kotlinx.android.synthetic.main.app_bar_main.*
import org.jetbrains.anko.doAsync import org.mosad.seil0.projectlaogai.controller.CacheController
import org.jetbrains.anko.uiThread import org.mosad.seil0.projectlaogai.controller.PreferencesController
import org.mosad.seil0.projectlaogai.PreferencesController.Companion.cColor import org.mosad.seil0.projectlaogai.controller.PreferencesController.Companion.cColorAccent
import org.mosad.seil0.projectlaogai.PreferencesController.Companion.cCourse import org.mosad.seil0.projectlaogai.controller.PreferencesController.Companion.cColorPrimary
import org.mosad.seil0.projectlaogai.PreferencesController.Companion.cCourseTTLinkList import org.mosad.seil0.projectlaogai.controller.PreferencesController.Companion.cCourse
import org.mosad.seil0.projectlaogai.PreferencesController.Companion.cTimeTableCurrentWeek import org.mosad.seil0.projectlaogai.controller.PreferencesController.Companion.coursesCacheTime
import org.mosad.seil0.projectlaogai.PreferencesController.Companion.cTimeTableNextWeek import org.mosad.seil0.projectlaogai.controller.PreferencesController.Companion.mensaCacheTime
import org.mosad.seil0.projectlaogai.PreferencesController.Companion.cWeekMenus import org.mosad.seil0.projectlaogai.controller.PreferencesController.Companion.timetableCacheTime
import org.mosad.seil0.projectlaogai.controller.TCoRAPIController
import org.mosad.seil0.projectlaogai.fragments.* import org.mosad.seil0.projectlaogai.fragments.*
import org.mosad.seil0.projectlaogai.hsoparser.MensaParser import java.sql.Date
import org.mosad.seil0.projectlaogai.hsoparser.TimeTableParser import java.util.*
import kotlin.system.measureTimeMillis import kotlin.system.measureTimeMillis
class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener { class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener {
private val mensaParser = MensaParser()
private val timeTableParser = TimeTableParser()
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
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
@ -70,12 +68,16 @@ 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"))
apply() apply()
} }
SettingsFragment().selectCourse(this)
} else { } else {
Aesthetic.config { Aesthetic.config {
colorPrimary(cColor) colorPrimary(cColorPrimary)
colorPrimaryDark(cColor) colorPrimaryDark(cColorPrimary)
colorAccent(cColorAccent)
apply() apply()
} }
} }
@ -163,53 +165,54 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
// load the settings // load the settings
PreferencesController.load(this) // this must be finished before doing anything else PreferencesController.load(this) // this must be finished before doing anything else
/** val startupTime = measureTimeMillis {
* load mensa, course timetable and courselist from the swfr/hso website val tcor = TCoRAPIController(this)
* TODO make an API see https://git.mosad.xyz/Seil0/TheCitadelofRicks val currentTime = System.currentTimeMillis() / 1000
*/ val currentDay = Calendar.getInstance().get(Calendar.DAY_OF_WEEK)
val time = measureTimeMillis { val cal = Calendar.getInstance()
/* getting the course list should be faster than the timetable, // timetable sunday workaround
* we need have time until the user opens the dialog cal.time = Date(timetableCacheTime * 1000)
*/ val timetableCacheDay = cal.get(Calendar.DAY_OF_WEEK)
doAsync {
cCourseTTLinkList = timeTableParser.getCourseTTLinks() // TODO this sill backfire if someone has to update before the server finished updating the timetable at 0001/0101
// 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) {
println("updating timetable after sunday!")
val jobA = tcor.getTimetable(cCourse.courseName, 0)
val jobB = tcor.getTimetable(cCourse.courseName, 1)
jobA.get()
jobB.get()
} }
val jobMenus = doAsync { // mensa sunday workaround
cWeekMenus = mensaParser.getMensaMenu() cal.time = Date(System.currentTimeMillis()) // reset to current time
// update blocking if it's sunday after 1500
// TODO and the last update was before 1500
if(currentDay == Calendar.SUNDAY && cal.get(Calendar.HOUR_OF_DAY) >= 15) {
val jobA = tcor.getMensa()
jobA.get()
} }
val jobTTCurrentWeek = doAsync { // get the cached files
try { val cache = CacheController(this)
cTimeTableCurrentWeek = timeTableParser.getTimeTable(cCourse.courseLink) cache.readStartCache(cCourse.courseName)
timeTableParser.printTimeTableWeek(cTimeTableCurrentWeek)
} catch (e: Exception) {
uiThread { // check if an update is necessary
MaterialDialog(this@MainActivity) if(currentTime - coursesCacheTime > 86400)
.title(R.string.error) tcor.getCoursesList()
.message(R.string.no_tt_error)
.show()
}
e.stackTrace if(currentTime - mensaCacheTime > 10800)
} tcor.getMensa()
if(currentTime - timetableCacheTime > 10800) {
tcor.getTimetable(cCourse.courseName, 0)
tcor.getTimetable(cCourse.courseName, 1)
} }
val jobTTNextWeek = doAsync {
try {
cTimeTableNextWeek = timeTableParser.getTimeTable(cCourse.courseLink.replace("week=0","week=1"))
} catch (e: Exception) {
e.stackTrace
}
}
jobMenus.get()
jobTTCurrentWeek.get()
jobTTNextWeek.get()
} }
println("Completed in $time ms") println("Completed in $startupTime ms")
} }
} }

View File

@ -0,0 +1,122 @@
/**
* ProjectLaogai
*
* Copyright 2019 <seil0@mosad.xyz>
*
* 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
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
*/
package org.mosad.seil0.projectlaogai.controller
import android.content.Context
import com.google.gson.Gson
import com.google.gson.JsonParser
import org.mosad.seil0.projectlaogai.hsoparser.Course
import org.mosad.seil0.projectlaogai.hsoparser.MensaWeek
import org.mosad.seil0.projectlaogai.hsoparser.TimetableWeek
import java.io.BufferedReader
import java.io.File
import java.io.FileReader
import com.google.gson.reflect.TypeToken
class CacheController(cont: Context) {
private val context = cont
companion object {
var coursesList = ArrayList<Course>()
var mensaCurrentWeek = MensaWeek()
var mensaNextWeek = MensaWeek()
var timetables = ArrayList<TimetableWeek>()
}
/**
* read coursesList, mensa (current and next week), timetable (current and next week)
* @param courseName the course name (e.g AI1)
*/
fun readStartCache(courseName: String) {
readCoursesList()
readMensa()
readTimetable(courseName, 0)
readTimetable(courseName, 1)
}
/**
* read the courses list from the cached file
* add them to the coursesList object
*/
fun readCoursesList() {
val file = File(context.filesDir, "courses.json")
// make sure the file exists
if (!file.exists())
TCoRAPIController(context).getCoursesList().get()
val fileReader = FileReader(file)
val bufferedReader = BufferedReader(fileReader)
val coursesObject = JsonParser().parse(bufferedReader.readLine()).asJsonObject
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)
}
}
}

View File

@ -20,14 +20,13 @@
* *
*/ */
package org.mosad.seil0.projectlaogai 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.jetbrains.anko.defaultSharedPreferences
import org.mosad.seil0.projectlaogai.R
import org.mosad.seil0.projectlaogai.hsoparser.Course import org.mosad.seil0.projectlaogai.hsoparser.Course
import org.mosad.seil0.projectlaogai.hsoparser.Meal
import org.mosad.seil0.projectlaogai.hsoparser.TimeTable
/** /**
* The PreferencesController class * The PreferencesController class
@ -36,18 +35,33 @@ import org.mosad.seil0.projectlaogai.hsoparser.TimeTable
class PreferencesController { class PreferencesController {
companion object { companion object {
var cCourseTTLinkList = ArrayList<Course>() var coursesCacheTime: Long = 0
var cWeekMenus = ArrayList<Meal>() var mensaCacheTime: Long = 0
var cTimeTableCurrentWeek = TimeTable() var timetableCacheTime: Long = 0
var cTimeTableNextWeek = TimeTable() var cColorPrimary: Int = Color.BLACK
var cColor: Int = Color.BLACK var cColorAccent: Int = Color.parseColor("#3F51B5")
var cCourse = Course("https://www.hs-offenburg.de/index.php?id=6627&class=class&iddV=DA64F6FE-9DDB-429E-A677-05D0D40CB636&week=0", "AI3") var cCourse = Course("https://www.hs-offenburg.de/index.php?id=6627&class=class&iddV=DA64F6FE-9DDB-429E-A677-05D0D40CB636&week=0", "AI3")
var cShowBuffet = true
// the save function // the save function
fun save(context: Context) { fun save(context: Context) {
println(cCourse.courseLink)
// save the course
val sharedPref = context.defaultSharedPreferences val sharedPref = context.defaultSharedPreferences
// save the update times (cache)
with (sharedPref.edit()) {
putLong(context.getString(R.string.save_key_coursesCacheTime),
coursesCacheTime
)
putLong(context.getString(R.string.save_key_mensaCacheTime),
mensaCacheTime
)
putLong(context.getString(R.string.save_key_timetableCacheTime),
timetableCacheTime
)
apply()
}
// save the course
with (sharedPref.edit()) { with (sharedPref.edit()) {
putString(context.getString(R.string.save_key_course), cCourse.courseName) putString(context.getString(R.string.save_key_course), cCourse.courseName)
putString(context.getString(R.string.save_key_courseTTLink), cCourse.courseLink) putString(context.getString(R.string.save_key_courseTTLink), cCourse.courseLink)
@ -56,7 +70,25 @@ class PreferencesController {
// save the primary color // save the primary color
with (sharedPref.edit()) { with (sharedPref.edit()) {
putInt(context.getString(R.string.save_key_colorPrimary), cColor) putInt(context.getString(R.string.save_key_colorPrimary),
cColorPrimary
)
apply()
}
// save the accent color
with (sharedPref.edit()) {
putInt(context.getString(R.string.save_key_colorAccent),
cColorAccent
)
apply()
}
// save showBuffet
with (sharedPref.edit()) {
putBoolean(context.getString(R.string.save_key_showBuffet),
cShowBuffet
)
apply() apply()
} }
@ -64,15 +96,37 @@ class PreferencesController {
// the load function // the load function
fun load(context: Context) { fun load(context: Context) {
// load saved course
val sharedPref = context.defaultSharedPreferences val sharedPref = context.defaultSharedPreferences
// load the update times (cache)
coursesCacheTime = sharedPref.getLong(context.getString(
R.string.save_key_coursesCacheTime
), 0)
mensaCacheTime = sharedPref.getLong(context.getString(
R.string.save_key_mensaCacheTime
), 0)
timetableCacheTime = sharedPref.getLong(context.getString(
R.string.save_key_timetableCacheTime
), 0)
// load saved course
cCourse = Course( cCourse = Course(
sharedPref.getString(context.getString(R.string.save_key_courseTTLink), "https://www.hs-offenburg.de/index.php?id=6627&class=class&iddV=DA64F6FE-9DDB-429E-A677-05D0D40CB636&week=0")!!, sharedPref.getString(context.getString(R.string.save_key_courseTTLink), "https://www.hs-offenburg.de/index.php?id=6627&class=class&iddV=DA64F6FE-9DDB-429E-A677-05D0D40CB636&week=0")!!,
sharedPref.getString(context.getString(R.string.save_key_course), "AI3")!! sharedPref.getString(context.getString(R.string.save_key_course), "AI3")!!
) )
// load saved color // load saved colors
cColor = sharedPref.getInt(context.getString(R.string.save_key_colorPrimary), Color.BLACK) cColorPrimary = sharedPref.getInt(context.getString(
R.string.save_key_colorPrimary
), Color.BLACK)
cColorAccent = sharedPref.getInt(context.getString(
R.string.save_key_colorAccent
), Color.parseColor("#3F51B5"))
// load showBuffet
cShowBuffet = sharedPref.getBoolean(context.getString(
R.string.save_key_showBuffet
), true)
} }
} }

View File

@ -0,0 +1,96 @@
/**
* ProjectLaogai
*
* Copyright 2019 <seil0@mosad.xyz>
*
* 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
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
*/
package org.mosad.seil0.projectlaogai.controller
import android.content.Context
import org.jetbrains.anko.doAsync
import org.json.JSONObject
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.timetableCacheTime
import java.io.*
import java.net.URL
class TCoRAPIController(cont: Context) {
private val context = cont
/**
* get the json object from tcor api and write it as file (cache)
*/
fun getCoursesList() = doAsync {
val url = URL("https://tcor.mosad.xyz/courses")
val file = File(context.filesDir, "courses.json")
// read data from the API
val coursesObject = JSONObject(url.readText()) //JSONObject(inReader.readLine())
// write the json object to a file
val writer = BufferedWriter(FileWriter(file))
writer.write(coursesObject.toString())
writer.close()
// update cache time
coursesCacheTime = System.currentTimeMillis() / 1000
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)
}
}

View File

@ -22,22 +22,29 @@
package org.mosad.seil0.projectlaogai.fragments package org.mosad.seil0.projectlaogai.fragments
import android.graphics.Typeface
import android.os.Bundle 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 android.widget.TextView
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import com.afollestad.materialdialogs.MaterialDialog import com.afollestad.materialdialogs.MaterialDialog
import kotlinx.android.synthetic.main.fragment_home.* import kotlinx.android.synthetic.main.fragment_home.*
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.PreferencesController.Companion.cTimeTableCurrentWeek
import org.mosad.seil0.projectlaogai.PreferencesController.Companion.cWeekMenus
import org.mosad.seil0.projectlaogai.R import org.mosad.seil0.projectlaogai.R
import org.mosad.seil0.projectlaogai.hsoparser.* import org.mosad.seil0.projectlaogai.controller.CacheController.Companion.mensaCurrentWeek
import org.mosad.seil0.projectlaogai.uicomponents.LessonCardView import org.mosad.seil0.projectlaogai.controller.CacheController.Companion.timetables
import org.mosad.seil0.projectlaogai.uicomponents.LessonTextView import org.mosad.seil0.projectlaogai.hsoparser.DataTypes
import org.mosad.seil0.projectlaogai.hsoparser.Meal
import org.mosad.seil0.projectlaogai.hsoparser.NotRetardedCalendar
import org.mosad.seil0.projectlaogai.hsoparser.TimetableDay
import org.mosad.seil0.projectlaogai.uicomponents.DayCardView
import org.mosad.seil0.projectlaogai.uicomponents.LessonLinearLayout
import org.mosad.seil0.projectlaogai.uicomponents.MealLinearLayout
import java.text.SimpleDateFormat
import java.util.* import java.util.*
/** /**
@ -46,18 +53,14 @@ import java.util.*
*/ */
class HomeFragment : Fragment() { class HomeFragment : Fragment() {
private lateinit var linLayoutTimeTable: LinearLayout 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)
// init UI elements addMensaMenu().get()
linLayoutTimeTable = view.findViewById(R.id.linLayoutTimeTable) addTimeTable()
//setText()
addCurrentMensaMenu()
addCurrentTimeTable()
// Inflate the layout for this fragment // Inflate the layout for this fragment
return view return view
@ -66,53 +69,46 @@ class HomeFragment : Fragment() {
/** /**
* add the current mensa meal to the home screens * add the current mensa meal to the home screens
*/ */
private fun addCurrentMensaMenu() { private fun addMensaMenu() = doAsync {
doAsync {
val dayMenus: ArrayList<Meal> var dayMeals: ArrayList<Meal>
val cal = Calendar.getInstance() val cal = Calendar.getInstance()
val mensaCardView = DayCardView(context!!)
uiThread {
if (cal.get(Calendar.HOUR_OF_DAY) < 15) { if (cal.get(Calendar.HOUR_OF_DAY) < 15) {
dayMenus = MensaParser().getMensaMenuDay(cWeekMenus, cal.get(Calendar.DAY_OF_WEEK)) dayMeals = mensaCurrentWeek.days[NotRetardedCalendar().getDayOfWeekIndex()].meals
mensaCardView.setDayHeading(resources.getString(R.string.today_date, formatter.format(cal.time)))
} else { } else {
dayMenus = MensaParser().getMensaMenuDay(cWeekMenus, cal.get(Calendar.DAY_OF_WEEK) + 1) dayMeals = mensaCurrentWeek.days[NotRetardedCalendar().getTomorrowWeekIndex()].meals
uiThread { cal.add(Calendar.DATE, 1)
txtView_Menu1Heading.text = resources.getString(R.string.meal_1_tomorrow) mensaCardView.setDayHeading(resources.getString(R.string.tomorrow_date, formatter.format(cal.time)))
txtView_Menu2Heading.text = resources.getString(R.string.meal_2_tomorrow)
}
} }
uiThread { if (dayMeals.size >= 2) {
// get the index of the first meal, not a "Schneller Teller"
loop@ for ((i, meal) in dayMeals.withIndex()) {
if (meal.heading.contains("Essen")) {
if (dayMenus.size >= 2) { val meal1Layout = MealLinearLayout(context)
// get the index of the first meal, not a "Schneller Teller" meal1Layout.setMeal(dayMeals[i])
loop@ for ((i, meal) in dayMenus.withIndex()) { mensaCardView.getLinLayoutDay().addView(meal1Layout)
if (meal.heading.contains("Essen")) {
for ((j, part) in dayMenus[i].parts.withIndex()) {
txtViewMenu1.append(part)
if (j < (dayMenus[i].parts.size - 2))
txtViewMenu1.append("\n")
}
for ((j, part) in dayMenus[i + 1].parts.withIndex()) { val meal2Layout = MealLinearLayout(context)
txtViewMenu2.append(part) meal2Layout.setMeal(dayMeals[i + 1])
if (j < (dayMenus[i + 1].parts.size - 2)) meal2Layout.disableDivider()
txtViewMenu2.append("\n") mensaCardView.getLinLayoutDay().addView(meal2Layout)
}
break@loop break@loop
}
}
} else {
if (txtView_Menu1Heading.text == resources.getString(R.string.meal_1_tomorrow)) {
txtViewMenu1.text = resources.getString(R.string.no_meal_tomorrow)
txtViewMenu2.text = resources.getString(R.string.no_meal_tomorrow)
} else {
txtViewMenu1.text = resources.getString(R.string.no_meal_today)
txtViewMenu2.text = resources.getString(R.string.no_meal_today)
} }
} }
} else {
mensaCardView.getLinLayoutDay().addView(getNoCard(resources.getString(R.string.mensa_closed)))
} }
linLayout_Home.addView(mensaCardView)
} }
} }
@ -120,52 +116,28 @@ class HomeFragment : Fragment() {
/** /**
* add the current timetable to the home screen * add the current timetable to the home screen
*/ */
private fun addCurrentTimeTable() { private fun addTimeTable() = doAsync {
val dayIndex = NotRetardedCalendar().getDayOfWeekIndex() val dayIndex = NotRetardedCalendar().getDayOfWeekIndex()
val cal = Calendar.getInstance()
var dayCardView: DayCardView
if (cTimeTableCurrentWeek.days.isNotEmpty() && dayIndex < 6) { uiThread {
val timeTableDay = cTimeTableCurrentWeek.days[dayIndex] if (timetables.isNotEmpty() && dayIndex < 6) {
// for all timeslots of the day // first check the current day
for ((i, timeslot) in timeTableDay.timeslots.withIndex()) { dayCardView = addDayTimetable(timetables[0].days[dayIndex])
val lessonCardView = LessonCardView(context!!, null) dayCardView.setDayHeading(resources.getString(R.string.today_date, formatter.format(cal.time)))
lessonCardView.getTxtViewTime().text = DataTypes().getTime()[i]
for (lesson in timeslot) { // if there are no lessons try to find the next day with a lesson
val lessonTxtView = LessonTextView(context!!) if (dayCardView.getLinLayoutDay().childCount <= 1)
lessonTxtView.setLesson(lesson) dayCardView = findNextDay(0, dayIndex + 1)
// TODO why does this exist linLayout_Home.addView(dayCardView)
if (lessonTxtView.text.length > 3) } else if (dayIndex == 6) {
lessonCardView.getLinLayoutLesson().addView(lessonTxtView)
}
if (lessonCardView.getLinLayoutLesson().childCount > 2)
linLayoutTimeTable.addView(lessonCardView)
}
// add a card if there is no lesson today
if (linLayoutTimeTable.childCount == 0) {
// TODO we could display the next day with a lecture
val lessonTxtView = LessonTextView(context!!)
lessonTxtView.setText(resources.getString(R.string.no_lesson_today))
val noLessonCardView = LessonCardView(context!!, null)
noLessonCardView.getLinLayoutLesson().addView(lessonTxtView)
linLayoutTimeTable.addView(noLessonCardView)
}
} else {
if (dayIndex == 6) {
// if that's the case it's sunday // if that's the case it's sunday
val lessonTxtView = LessonTextView(context!!) dayCardView = findNextDay(1, 0)
lessonTxtView.setText(resources.getString(R.string.no_lesson_today)) linLayout_Home.addView(dayCardView)
val noLessonCardView = LessonCardView(context!!, null)
noLessonCardView.getLinLayoutLesson().addView(lessonTxtView)
linLayoutTimeTable.addView(noLessonCardView)
} else { } else {
MaterialDialog(context!!) MaterialDialog(context!!)
.title(R.string.error) .title(R.string.error)
@ -175,6 +147,88 @@ class HomeFragment : Fragment() {
} }
} }
}
/**
* add the timetable of one day to the home-screen
* @param dayTimetable the day you wish to add
*/
private fun addDayTimetable(dayTimetable: TimetableDay) : DayCardView{
var helpLesson = LessonLinearLayout(context)
val dayCardView = DayCardView(context!!)
for ((tsIndex, timeslot) in dayTimetable.timeslots.withIndex()) {
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()
return dayCardView
}
/**
* find the next day with a lesson
* @param startWeekIndex the week you want to start searching
* @param startDayIndex the day index you want to start searching
* @return a DayCardView with all lessons added
*/
private fun findNextDay(startWeekIndex: Int, startDayIndex: Int) : DayCardView{
val cal = Calendar.getInstance()
var dayCardView = DayCardView(context!!)
var dayTimetable: TimetableDay? = null
var dayIndexSearch = startDayIndex
var weekIndexSearch = startWeekIndex
loop@ while (dayTimetable == null && weekIndexSearch <= timetables.size) {
for (i in (dayIndexSearch) ..5) {
dayTimetable = timetables[weekIndexSearch].days[i]
cal.add(Calendar.DATE, 1)
// add the timetable to the card, if it contains at least one lesson break!
dayCardView = addDayTimetable(dayTimetable)
dayCardView.setDayHeading(formatter.format(cal.time))
if (dayCardView.getLinLayoutDay().childCount > 1)
return dayCardView
}
dayIndexSearch = 0
weekIndexSearch++
cal.add(Calendar.DATE, 1)
}
dayCardView.setDayHeading(formatter.format(Calendar.getInstance().time))
dayCardView.getLinLayoutDay().addView(getNoCard(resources.getString(R.string.no_lesson_today))) // if there is no lecture at all show the no lesson card
return dayCardView
}
/**
* @param text the text to show on the card
* @return a TextView with the text and all needed parameters
*/
private fun getNoCard(text: String): TextView {
val noLesson = TextView(context)
noLesson.text = text
noLesson.setTextColor(ContextCompat.getColor(context!!, R.color.textPrimary))
noLesson.textSize = 18.0F
noLesson.setTypeface(null, Typeface.BOLD)
noLesson.textAlignment = View.TEXT_ALIGNMENT_CENTER
noLesson.setPadding(7,7,7,7)
return noLesson
} }
} }

View File

@ -23,18 +23,22 @@
package org.mosad.seil0.projectlaogai.fragments package org.mosad.seil0.projectlaogai.fragments
import android.os.Bundle import android.os.Bundle
import androidx.fragment.app.Fragment
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 android.widget.LinearLayout
import androidx.fragment.app.Fragment
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.PreferencesController.Companion.cWeekMenus
import org.mosad.seil0.projectlaogai.R import org.mosad.seil0.projectlaogai.R
import org.mosad.seil0.projectlaogai.uicomponents.MensaDayCardView import org.mosad.seil0.projectlaogai.controller.CacheController.Companion.mensaCurrentWeek
import org.mosad.seil0.projectlaogai.uicomponents.MenuCardView import org.mosad.seil0.projectlaogai.controller.CacheController.Companion.mensaNextWeek
import java.util.* import org.mosad.seil0.projectlaogai.controller.PreferencesController.Companion.cShowBuffet
import org.mosad.seil0.projectlaogai.hsoparser.MensaWeek
import org.mosad.seil0.projectlaogai.hsoparser.NotRetardedCalendar
import org.mosad.seil0.projectlaogai.uicomponents.DayCardView
import org.mosad.seil0.projectlaogai.uicomponents.MealLinearLayout
/** /**
* The mensa controller class * The mensa controller class
@ -48,67 +52,49 @@ class MensaFragment : Fragment() {
val view: View = inflater.inflate(R.layout.fragment_mensa, container, false) val view: View = inflater.inflate(R.layout.fragment_mensa, container, false)
linLayoutMensaFragment = view.findViewById(R.id.linLayout_MensaFragment) linLayoutMensaFragment = view.findViewById(R.id.linLayout_Mensa)
addCurrentWeek() // add the current week (week starts on sunday)
val dayCurrent = if(NotRetardedCalendar().getDayOfWeekIndex() == 6) 0 else NotRetardedCalendar().getDayOfWeekIndex()
addWeek(mensaCurrentWeek, dayCurrent).get()
// add the next week
addWeek(mensaNextWeek, 0).get()
return view return view
} }
private fun addCurrentWeek() { /**
* add all menus from dayStart to Friday for a given week
*/
private fun addWeek(menusWeek: MensaWeek, dayStart: Int) = doAsync {
doAsync { uiThread {
uiThread { // only add the days dayStart to Fri since the mensa is closed on Sat/Sun
for (dayIndex in dayStart..4) {
var helpMeal = MealLinearLayout(context)
val dayCardView = DayCardView(context!!)
dayCardView.setDayHeading(menusWeek.days[dayIndex].meals[0].day)
for(day in Calendar.getInstance().get(Calendar.DAY_OF_WEEK)..7) { for (meal in menusWeek.days[dayIndex].meals) {
val mealLayout = MealLinearLayout(context)
mealLayout.setMeal(meal)
val strDay: String = when(day) { if(meal.heading != "Buffet" || cShowBuffet) {
Calendar.MONDAY -> "Mon" dayCardView.getLinLayoutDay().addView(mealLayout)
Calendar.TUESDAY -> "Die" helpMeal = mealLayout
Calendar.WEDNESDAY -> "Mit"
Calendar.THURSDAY -> "Don"
Calendar.FRIDAY -> "Fre"
Calendar.SATURDAY -> "Sam"
else -> "TODAY" // the app will likely crash here
} }
val cardViewMensaDay = MensaDayCardView(context!!, null)
var add = false
for (meal in cWeekMenus) {
//println("Day: " + meal.day)
if (meal.day.contains(strDay)) {
val menuViewMenu = MenuCardView(context!!, null)
menuViewMenu.setMenuHeading(meal.heading)
for ((i, part) in meal.parts.withIndex()) {
menuViewMenu.getTxtViewMenu().append(part)
if(i < (meal.parts.size - 2))
menuViewMenu.getTxtViewMenu().append("\n")
}
cardViewMensaDay.setDayHeading(meal.day)
cardViewMensaDay.getLinLayoutMensaDay().addView(menuViewMenu)
add = true
}
}
if(add)
linLayoutMensaFragment.addView(cardViewMensaDay)
} }
// add a card if there are no more meals in this week helpMeal.disableDivider()
if(linLayoutMensaFragment.childCount == 0) {
val cardViewNoMoreFood = MensaDayCardView(context!!, null) if(dayCardView.getLinLayoutDay().childCount > 1)
cardViewNoMoreFood.setDayHeading(resources.getString(R.string.no_more_food)) linLayout_Mensa.addView(dayCardView)
linLayoutMensaFragment.addView(cardViewNoMoreFood)
}
} }
} }
} }
} }

View File

@ -48,10 +48,10 @@ class MoodleFragment : Fragment() {
webView = view.findViewById(R.id.webView) webView = view.findViewById(R.id.webView)
webView.loadUrl("https://elearning.hs-offenburg.de/moodle/") webView.loadUrl("https://elearning.hs-offenburg.de/moodle/")
webSettings = webView.getSettings() webSettings = webView.settings
//webSettings.setJavaScriptEnabled(true) // Enable Javascript //webSettings.setJavaScriptEnabled(true) // Enable Javascript
webView.setWebViewClient(WebViewClient()) // Force links and redirects to open in the WebView instead of in a browser webView.webViewClient = WebViewClient() // Force links and redirects to open in the WebView instead of in a browser
return view return view
} }

View File

@ -22,12 +22,13 @@
package org.mosad.seil0.projectlaogai.fragments package org.mosad.seil0.projectlaogai.fragments
import android.graphics.Color import android.content.Context
import android.os.Bundle 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 android.widget.LinearLayout
import android.widget.Switch
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import com.afollestad.aesthetic.Aesthetic import com.afollestad.aesthetic.Aesthetic
import com.afollestad.materialdialogs.MaterialDialog import com.afollestad.materialdialogs.MaterialDialog
@ -37,14 +38,17 @@ import com.afollestad.materialdialogs.list.listItems
import kotlinx.android.synthetic.main.fragment_settings.* import kotlinx.android.synthetic.main.fragment_settings.*
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.PreferencesController import org.mosad.seil0.projectlaogai.BuildConfig
import org.mosad.seil0.projectlaogai.PreferencesController.Companion.cColor import org.mosad.seil0.projectlaogai.controller.PreferencesController
import org.mosad.seil0.projectlaogai.PreferencesController.Companion.cCourse import org.mosad.seil0.projectlaogai.controller.PreferencesController.Companion.cColorAccent
import org.mosad.seil0.projectlaogai.PreferencesController.Companion.cCourseTTLinkList import org.mosad.seil0.projectlaogai.controller.PreferencesController.Companion.cColorPrimary
import org.mosad.seil0.projectlaogai.PreferencesController.Companion.cTimeTableCurrentWeek import org.mosad.seil0.projectlaogai.controller.PreferencesController.Companion.cCourse
import org.mosad.seil0.projectlaogai.PreferencesController.Companion.cTimeTableNextWeek import org.mosad.seil0.projectlaogai.controller.PreferencesController.Companion.cShowBuffet
import org.mosad.seil0.projectlaogai.R import org.mosad.seil0.projectlaogai.R
import org.mosad.seil0.projectlaogai.hsoparser.TimeTableParser import org.mosad.seil0.projectlaogai.controller.CacheController
import org.mosad.seil0.projectlaogai.controller.CacheController.Companion.coursesList
import org.mosad.seil0.projectlaogai.controller.TCoRAPIController
import org.mosad.seil0.projectlaogai.hsoparser.DataTypes
import java.util.* import java.util.*
/** /**
@ -55,9 +59,10 @@ class SettingsFragment : Fragment() {
private lateinit var linLayoutUser: LinearLayout private lateinit var linLayoutUser: LinearLayout
private lateinit var linLayoutCourse: LinearLayout private lateinit var linLayoutCourse: LinearLayout
private lateinit var linLayoutInfo: LinearLayout private lateinit var linLayoutAbout: LinearLayout
private lateinit var linLayoutMainColor: LinearLayout private lateinit var linLayoutPrimaryColor: LinearLayout
private lateinit var viewPrimaryColor: View private lateinit var linLayoutAccentColor: LinearLayout
private lateinit var switchBuffet: Switch
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
@ -65,9 +70,10 @@ class SettingsFragment : Fragment() {
linLayoutUser = view.findViewById(R.id.linLayout_User) linLayoutUser = view.findViewById(R.id.linLayout_User)
linLayoutCourse = view.findViewById(R.id.linLayout_Course) linLayoutCourse = view.findViewById(R.id.linLayout_Course)
linLayoutInfo = view.findViewById(R.id.linLayout_Info) linLayoutAbout = view.findViewById(R.id.linLayout_About)
linLayoutMainColor = view.findViewById(R.id.linLayout_MainColor) linLayoutPrimaryColor = view.findViewById(R.id.linLayout_PrimaryColor)
viewPrimaryColor = view.findViewById(R.id.view_PrimaryColor) linLayoutAccentColor = view.findViewById(R.id.linLayout_AccentColor)
switchBuffet = view.findViewById(R.id.switch_buffet)
initActions() initActions()
@ -79,6 +85,8 @@ class SettingsFragment : Fragment() {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
txtView_Course.text = cCourse.courseName txtView_Course.text = cCourse.courseName
txtView_AboutDesc.text = resources.getString(R.string.about_version, BuildConfig.VERSION_NAME, getString(R.string.build_time))
switch_buffet.isChecked = cShowBuffet // init switch
} }
/** /**
@ -90,28 +98,89 @@ class SettingsFragment : Fragment() {
} }
linLayoutCourse.setOnClickListener { linLayoutCourse.setOnClickListener {
// open a new dialog selectCourse(context!!)
val courseList = ArrayList<String>() txtView_Course.text = cCourse.courseName // update txtView
}
cCourseTTLinkList.forEach { (_, course) -> linLayoutAbout.setOnClickListener {
courseList.add(course) // open a new info dialog
} MaterialDialog(context!!)
.title(R.string.about_dialog_heading)
.message(R.string.about_dialog_text)
.show()
}
MaterialDialog(context!!).listItems(items = courseList) { _, index, text -> linLayoutPrimaryColor.setOnClickListener {
txtView_Course.text = text // update txtView // open a new color chooser dialog
MaterialDialog(context!!)
.title(R.string.primary_color)
.colorChooser(DataTypes().primaryColors, allowCustomArgb = true, initialSelection = cColorPrimary) { _, color ->
view_PrimaryColor.setBackgroundColor(color)
Aesthetic.config {
colorPrimary(color)
colorPrimaryDark(color)
apply()
}
val dialog = MaterialDialog(context!!).cancelable(false) cColorPrimary = color
PreferencesController.save(context!!)
}
.positiveButton(R.string.select)
.show()
}
linLayoutAccentColor.setOnClickListener {
// open a new color chooser dialog
MaterialDialog(context!!)
.title(R.string.accent_color)
.colorChooser(DataTypes().accentColors, allowCustomArgb = true, initialSelection = cColorAccent) { _, color ->
view_AccentColor.setBackgroundColor(color)
Aesthetic.config {
colorAccent(color)
apply()
}
cColorAccent = color
PreferencesController.save(context!!)
}
.positiveButton(R.string.select)
.show()
}
switchBuffet.setOnClickListener {
cShowBuffet = switchBuffet.isChecked
PreferencesController.save(context!!)
println(switchBuffet.isChecked)
}
}
fun selectCourse(context: Context) {
val courseNameList = ArrayList<String>()
coursesList.forEach { (_, courseName) ->
courseNameList.add(courseName)
}
// open a new dialog
MaterialDialog(context)
.title(R.string.select_course)
.listItems(items = courseNameList) { _, index, _ ->
val dialog = MaterialDialog(context).cancelable(false)
.cancelOnTouchOutside(false) .cancelOnTouchOutside(false)
.customView(R.layout.dialog_loading) .customView(R.layout.dialog_loading)
dialog.show() dialog.show()
doAsync { doAsync {
cCourse = cCourseTTLinkList[index] // set the course cCourse = coursesList[index] // set the course
PreferencesController.save(context!!) PreferencesController.save(context)
// update current & next weeks timetable // update current & next weeks timetable
cTimeTableCurrentWeek = TimeTableParser().getTimeTable(cCourse.courseLink) TCoRAPIController(context).getTimetable(cCourse.courseName, 0)
cTimeTableNextWeek = TimeTableParser().getTimeTable(cCourse.courseLink.replace("week=0","week=1")) TCoRAPIController(context).getTimetable(cCourse.courseName, 1)
CacheController(context).readTimetable(cCourse.courseName, 0)
CacheController(context).readTimetable(cCourse.courseName, 1)
uiThread { uiThread {
dialog.dismiss() dialog.dismiss()
@ -119,37 +188,7 @@ class SettingsFragment : Fragment() {
} }
} }
.show() .show()
}
linLayoutInfo.setOnClickListener {
// open a new info dialog
MaterialDialog(context!!)
.title(R.string.about)
.message(R.string.about_text)
.show()
}
linLayoutMainColor.setOnClickListener {
// open a new color chooser dialog
val colors = intArrayOf(Color.BLACK, Color.DKGRAY, Color.RED, Color.GREEN, Color.YELLOW)
MaterialDialog(context!!)
.title(R.string.primary_color)
.colorChooser(colors, allowCustomArgb = true, initialSelection = cColor) { _, color ->
viewPrimaryColor.setBackgroundColor(color)
Aesthetic.config {
colorPrimary(color)
colorPrimaryDark(color)
apply()
}
cColor = color
PreferencesController.save(context!!)
}
.positiveButton(R.string.select)
.show()
}
} }
} }

View File

@ -26,18 +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_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.PreferencesController.Companion.cTimeTableCurrentWeek
import org.mosad.seil0.projectlaogai.PreferencesController.Companion.cTimeTableNextWeek
import org.mosad.seil0.projectlaogai.R import org.mosad.seil0.projectlaogai.R
import org.mosad.seil0.projectlaogai.controller.CacheController.Companion.timetables
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.uicomponents.LessonCardView import org.mosad.seil0.projectlaogai.uicomponents.*
import org.mosad.seil0.projectlaogai.uicomponents.LessonTextView
import org.mosad.seil0.projectlaogai.uicomponents.MensaDayCardView
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.* import java.util.*
@ -47,16 +44,12 @@ import java.util.*
*/ */
class TimeTableFragment : Fragment() { class TimeTableFragment : Fragment() {
private lateinit var linLayoutTTFragment: 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_time_table, container, false) val view: View = inflater.inflate(R.layout.fragment_timetable, container, false)
linLayoutTTFragment = view.findViewById(R.id.linLayout_TTFragment) if (timetables[0].days.isNotEmpty() && timetables[1].days.isNotEmpty()) {
addWeeks()
if (cTimeTableCurrentWeek.days.isNotEmpty()) {
addCurrentWeek()
} else { } else {
// TODO show card with error msg // TODO show card with error msg
} }
@ -65,107 +58,87 @@ class TimeTableFragment : Fragment() {
} }
/** /**
* add the remaining days of the current week to the timetable screen * add the all days with at least one lesson to the timetable screen
*/ */
private fun addCurrentWeek() { private fun addWeeks() = doAsync {
val dayIndex = NotRetardedCalendar().getDayOfWeekIndex() val dayIndex = NotRetardedCalendar().getDayOfWeekIndex()
val formatter = SimpleDateFormat("E dd.MM", Locale.GERMANY) // TODO change to android call when min api is 24 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()
doAsync { uiThread {
uiThread { // add the current week
for (day in dayIndex..5) {
var helpLesson = LessonLinearLayout(context)
val dayCardView = DayCardView(context!!)
dayCardView.setDayHeading(formatter.format(calendar.time))
// add current weeks days // for each timeslot of the day
for (day in dayIndex..5) { for ((tsIndex, timeslot) in timetables[0].days[day].timeslots.withIndex()) {
val cardViewTimeTableDay = MensaDayCardView(context!!, null)
cardViewTimeTableDay.setDayHeading(formatter.format(calendar.time))
// for each timeslot of the day for(lesson in timeslot) {
for ((i, timeslot) in cTimeTableCurrentWeek.days[day].timeslots.withIndex()) {
val lessonCardView = LessonCardView(context!!, null)
lessonCardView.getTxtViewTime().text = DataTypes().getTime()[i]
//println(timeslot) if(lesson.lessonSubject.isNotEmpty()) {
for (lesson in timeslot) { val lessonLayout = LessonLinearLayout(context)
val lessonTxtView = LessonTextView(context!!) lessonLayout.setLesson(lesson, DataTypes().getTime()[tsIndex])
lessonTxtView.setLesson(lesson) dayCardView.getLinLayoutDay().addView(lessonLayout)
// TODO why does this exist if (lesson != timeslot.last())
if (lessonTxtView.text.length > 3) lessonLayout.disableDivider()
lessonCardView.getLinLayoutLesson().addView(lessonTxtView)
helpLesson = lessonLayout
} }
// only add the lesson if it contains data
if (lessonCardView.getLinLayoutLesson().childCount > 1)
cardViewTimeTableDay.getLinLayoutMensaDay().addView(lessonCardView)
}
calendar.add(Calendar.DATE, 1)
// if the day contains no lessons add a text "No lesson today"
if (cardViewTimeTableDay.getLinLayoutMensaDay().childCount <= 1) {
val lessonTxtView = LessonTextView(context!!)
lessonTxtView.setText(resources.getString(R.string.no_lesson_today))
val lessonCardView = LessonCardView(context!!, null)
lessonCardView.getLinLayoutLesson().addView(lessonTxtView)
cardViewTimeTableDay.getLinLayoutMensaDay().addView(lessonCardView)
}
linLayoutTTFragment.addView(cardViewTimeTableDay)
}
// add next weeks days, max number = dayIndex, if timetable was loaded
if (cTimeTableNextWeek.days.isNotEmpty()) {
calendar.add(Calendar.DATE, 1) // before this we are at a sunday (no lecture on sundays!)
for (day in 0..(dayIndex - 1)) {
val cardViewTimeTableDay = MensaDayCardView(context!!, null)
cardViewTimeTableDay.setDayHeading(formatter.format(calendar.time))
// for each timeslot of the day
for ((i, timeslot) in cTimeTableNextWeek.days[day].timeslots.withIndex()) {
val lessonCardView = LessonCardView(context!!, null)
lessonCardView.getTxtViewTime().text = DataTypes().getTime()[i]
for (lesson in timeslot) {
val lessonTxtView = LessonTextView(context!!)
lessonTxtView.setLesson(lesson)
if (lessonTxtView.text.length > 3)
lessonCardView.getLinLayoutLesson().addView(lessonTxtView)
}
// only add the lesson if it contains data
if (lessonCardView.getLinLayoutLesson().childCount > 1)
cardViewTimeTableDay.getLinLayoutMensaDay().addView(lessonCardView)
}
calendar.add(Calendar.DATE, 1)
// if the day contains no lessons add a text "No lesson today"
if (cardViewTimeTableDay.getLinLayoutMensaDay().childCount <= 1) {
val lessonTxtView = LessonTextView(context!!)
lessonTxtView.setText(resources.getString(R.string.no_lesson_today))
val lessonCardView = LessonCardView(context!!, null)
lessonCardView.getLinLayoutLesson().addView(lessonTxtView)
cardViewTimeTableDay.getLinLayoutMensaDay().addView(lessonCardView)
}
linLayoutTTFragment.addView(cardViewTimeTableDay)
} }
} }
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)
}
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)) {
var helpLesson = LessonLinearLayout(context!!)
val dayCardView = DayCardView(context!!)
dayCardView.setDayHeading(formatter.format(calendar.time))
// for each timeslot of the day
for ((tsIndex, timeslot) in timetables[1].days[day].timeslots.withIndex()) {
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)
} }
} }
} }
} }

View File

@ -22,11 +22,55 @@
package org.mosad.seil0.projectlaogai.hsoparser package org.mosad.seil0.projectlaogai.hsoparser
import android.graphics.Color
import java.util.* import java.util.*
import kotlin.collections.ArrayList
class DataTypes { class DataTypes {
val times = arrayOf("8.00 - 9.30", "9.45 - 11.15" ,"11.35 - 13.05", "14.00 -15.30", "15.45 - 17.15", "17.30 - 19.00") val times = arrayOf("8.00 - 9.30", "9.45 - 11.15" ,"11.35 - 13.05", "14.00 -15.30", "15.45 - 17.15", "17.30 - 19.00")
val primaryColors = intArrayOf(
Color.parseColor("#E53935"),
Color.parseColor("#E91E63"),
Color.parseColor("#9C27B0"),
Color.parseColor("#673AB7"),
Color.parseColor("#3F51B5"),
Color.parseColor("#2196F3"),
Color.parseColor("#03A9F4"),
Color.parseColor("#00BCD4"),
Color.parseColor("#009688"),
Color.parseColor("#4CAF50"),
Color.parseColor("#8BC34A"),
Color.parseColor("#CDDC39"),
Color.parseColor("#FDD835"),
Color.parseColor("#FFB300"),
Color.parseColor("#FB8C00"),
Color.parseColor("#FF5722"),
Color.parseColor("#795548"),
Color.parseColor("#9E9E9E"),
Color.parseColor("#607B8B"),
Color.parseColor("#000000")
)
val accentColors = intArrayOf(
Color.parseColor("#FF1744"),
Color.parseColor("#F50057"),
Color.parseColor("#D500F9"),
Color.parseColor("#3F51B5"),
Color.parseColor("#3D5AFE"),
Color.parseColor("#2979FF"),
Color.parseColor("#00B0FF"),
Color.parseColor("#00E5FF"),
Color.parseColor("#1DE9B6"),
Color.parseColor("#00E676"),
Color.parseColor("#C6FF00"),
Color.parseColor("#FFD600"),
Color.parseColor("#FFC400"),
Color.parseColor("#FF9100"),
Color.parseColor("#FF3D00"),
Color.parseColor("#000000")
)
init { init {
// do something // do something
} }
@ -53,15 +97,30 @@ class NotRetardedCalendar {
} }
} }
fun getTomorrowWeekIndex(): Int {
return when(calendar.get(Calendar.DAY_OF_WEEK)) {
Calendar.MONDAY -> 1
Calendar.TUESDAY -> 2
Calendar.WEDNESDAY -> 3
Calendar.THURSDAY -> 4
Calendar.FRIDAY -> 5
Calendar.SATURDAY -> 6
Calendar.SUNDAY -> 0
else -> 7
}
}
} }
data class Course(val courseLink: String, val courseName: String) data class Course(val courseLink: String, val courseName: String)
data class Meal(val day: String, val heading: String, val parts: ArrayList<String>, val additives: String) data class Meal(val day: String, val heading: String, val parts: ArrayList<String>, val additives: String)
data class Meals(val meals: ArrayList<Meal>)
data class MensaWeek(val days: Array<Meals> = Array(7) { Meals(ArrayList()) })
data class Lesson(val lessonSubject: String, val lessonTeacher: String, val lessonRoom:String, val lessonRemark: String) data class Lesson(val lessonSubject: String, val lessonTeacher: String, val lessonRoom:String, val lessonRemark: String)
data class TimeTableDay( val timeslots: Array<ArrayList<Lesson>> = Array(6) { ArrayList<Lesson>()}) data class TimetableDay( val timeslots: Array<ArrayList<Lesson>> = Array(6) { ArrayList<Lesson>()})
data class TimeTable(val days: Array<TimeTableDay> = Array(6) { TimeTableDay() }) data class TimetableWeek(val days: Array<TimetableDay> = Array(6) { TimetableDay() })

View File

@ -1,76 +0,0 @@
/**
* ProjectLaogai
*
* Copyright 2019 <seil0@mosad.xyz>
*
* 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
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
*/
package org.mosad.seil0.projectlaogai.hsoparser
import org.jsoup.Jsoup
import java.util.*
class MensaParser {
/**
* returns the mensa menu for the whole week
*/
fun getMensaMenu(): ArrayList<Meal> {
val mealList = ArrayList<Meal>()
val menuHTML = Jsoup.connect("https://www.swfr.de/de/essen-trinken/speiseplaene/mensa-offenburg/").get()
menuHTML.select("#speiseplan-tabs").select("div.tab-content").select("div.menu-tagesplan").forEachIndexed { _, element ->
val day = element.select("h3").text()
for (i in 0 .. (element.select("div.row h4").size - 1)) {
try {
val heading = element.select("div.row h4")[i].text()
val parts = ArrayList<String>(element.select("div.row").select("div.menu-info")[i].html().substringBefore("<span").replace("<br>", " ").split("\n"))
val additives = element.select("div.row").select("div.menu-info")[i].select("span.show-with-allergenes").text()
mealList.add(Meal(day, heading, parts, additives))
} catch (e: Exception) {
// catch
}
}
}
return mealList
}
/**
* return the mensa menu of a given day (Mon - Sat)
*/
fun getMensaMenuDay(mealList: ArrayList<Meal>, day: Int): ArrayList<Meal> {
val dayMenus = ArrayList<Meal>()
val strDay: String = when (day) {
Calendar.MONDAY -> "Mon"
Calendar.TUESDAY -> "Die"
Calendar.WEDNESDAY -> "Mit"
Calendar.THURSDAY -> "Don"
Calendar.FRIDAY -> "Fre"
Calendar.SATURDAY -> "Sam"
else -> "TODAY"
}
for (meal in mealList) {
if (meal.day.contains(strDay))
dayMenus.add(meal)
}
return dayMenus
}
}

View File

@ -1,184 +0,0 @@
/**
* ProjectLaogai
*
* Copyright 2019 <seil0@mosad.xyz>
*
* 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
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
*/
package org.mosad.seil0.projectlaogai.hsoparser
import org.jsoup.Jsoup
class TimeTableParser {
private val days = arrayOf("Monday", "Tuesday" ,"Wednesday", "Thursday", "Friday", "Saturday")
private var courseTTLinkList = ArrayList<Course>()
/**
* get the timetable from the given url
* the timetable is organised per row not per column;
* Mon 1, Tue 1, Wed 1, Thur 1, Fri 1, Sat 1, Mon 2 and so on
*/
fun getTimeTable(courseTTURL: String): TimeTable {
var timeTableWeek = TimeTable() // this must be a var!
val scheduleHTML = Jsoup.connect(courseTTURL).get()
// create the timetable array
/* for (i in 0..5) {
var timeTableDay = arrayOf<Lesson>()
for (j in 0..5) {
timeTableDay += Lesson("", "","","")
}
timeTableWeek += timeTableDay
}*/
//val week = scheduleHTML.select("h1.timetable-caption").text()
//println("$week successful!\n")
val rows= scheduleHTML.select("table.timetable").select("tr[scope=\"row\"]")
var sDay = -1
var sRow = -1
var sLesson = Lesson("", "", "", "")
// get each row with index, reflects 1 timeslot per day
for ((rowIndex, row) in rows.withIndex()) {
var day = 0
row.select("td.lastcol, td[style]").forEach { element ->
// elements are now all lessons, including empty ones
//println("-------------> Element (Day.Timeslot: " + day + "." + rowIndex + "): " + element)
//println("Day.Timeslot: " + day + "." + rowIndex + " lesson: " + element.select("div.lesson-subject").text() + ", " + element.select("div.lesson-teacher").text())
// if there is a lecture with rowspan="2", we need to shift everything by one to the left. This is stupid and ugly there needs to bee an API
if ((sDay > -1 && sRow > -1) && (sDay == day && ((sRow + 1) == rowIndex))) {
// we found a lecture that is longer than 1 lesson
timeTableWeek.days[day].timeslots[rowIndex].add(sLesson) // this just works if there is one lecture per slot
// adjust the following slot
sDay++
sLesson = Lesson(element.select("div.lesson-subject").text(), element.select("div.lesson-teacher").text(), element.select("div.lesson-room").text(), element.select("div.lesson-remark").text())
// adjust the slot directly as we don't get there anymore
if(sDay == 5) {
timeTableWeek.days[day + 1].timeslots[rowIndex].add(sLesson)
}
} else {
timeTableWeek.days[day].timeslots[rowIndex].add(Lesson(element.select("div.lesson-subject").text(), element.select("div.lesson-teacher").text(), element.select("div.lesson-room").text(), element.select("div.lesson-remark").text()))
}
// we found a lecture with rowspan="2", save day, row and lesson for later adjustment
if(element.toString().contains("rowspan=\"2\"")) {
sDay = day
sRow = rowIndex
sLesson = timeTableWeek.days[day].timeslots[rowIndex].get(index = 0)
}
if(element.hasClass("lastcol")) day++
}
}
printTimeTableWeek(timeTableWeek)
/*scheduleHTML.select("table.timetable").select("td.lastcol").forEachIndexed { index, element ->
//println("Index: " + index + " lesson: " + element.select("div.lesson-subject").text() + ", " + element.select("div.lesson-teacher").text())
timeTableWeek[index % 6][index / 6] = Lesson(element.select("div.lesson-subject").text(), element.select("div.lesson-teacher").text(), element.select("div.lesson-room").text(), element.select("div.lesson-remark").text())
}*/
return timeTableWeek
}
/**
* parse all courses from the courses site at https://www.hs-offenburg.de/studium/vorlesungsplaene/
*/
fun getCourseTTLinks(): ArrayList<Course> {
val courseHTML = Jsoup.connect("https://www.hs-offenburg.de/studium/vorlesungsplaene/").get()
courseHTML.select("ul.index-group").select("li.Class").select("a[href]").forEachIndexed { _, element ->
courseTTLinkList.add(Course(element.attr("href").replace("http", "https"),element.text()))
}
return courseTTLinkList
}
@Suppress("unused")
fun printTimeTableWeekOLD (timeTableWeek: Array<Array<Lesson>>) {
for (j in 0..5) print(days[j].padEnd(25 ,' ') + " | ")
println()
for (j in 0..5) print("-".padEnd(26 + (j.toFloat().div(j).toInt()), '-') + "+")
println()
for (i in 0..5) {
for (j in 0..5) print(timeTableWeek[j][i].lessonSubject.padEnd(25 ,' ').substring(0,25) + " | ")
println()
for (j in 0..5) print(timeTableWeek[j][i].lessonTeacher.padEnd(25 ,' ').substring(0,25) + " | ")
println()
for (j in 0..5) print(timeTableWeek[j][i].lessonRoom.padEnd(25 ,' ').substring(0,25) + " | ")
println()
for (j in 0..5) print("-".padEnd(26 + (j.toFloat().div(j).toInt()), '-') + "+")
println()
}
println(" \n")
}
@Suppress("unused")
fun printTimeTableWeek(timetable: TimeTable) {
for (j in 0..5) print(days[j].padEnd(75 ,' ') + " | ")
println()
for (j in 0..5) print("-".padEnd(76 + (j.toFloat().div(j).toInt()), '-') + "+")
println()
// the timeslot
for (i in 0..5) {
for (j in 0..5) {
val ldiff = if (timetable.days[j].timeslots[i].size == 0) 1 else timetable.days[j].timeslots[i].size
for (lesson in timetable.days[j].timeslots[i]) print(lesson.lessonSubject.padEnd(75/ldiff ,' '))
if (ldiff == 2) print(" ")
print(" | ")
}
println()
for (j in 0..5) {
val ldiff = if (timetable.days[j].timeslots[i].size == 0) 1 else timetable.days[j].timeslots[i].size
for (lesson in timetable.days[j].timeslots[i]) print(lesson.lessonTeacher.padEnd(75/ldiff ,' '))
if (ldiff == 2) print(" ")
print(" | ")
}
println()
for (j in 0..5) {
val ldiff = if (timetable.days[j].timeslots[i].size == 0) 1 else timetable.days[j].timeslots[i].size
for (lesson in timetable.days[j].timeslots[i]) print(lesson.lessonRoom.padEnd(75/ldiff ,' '))
if (ldiff == 2) print(" ")
print(" | ")
}
println()
for (j in 0..5) print("-".padEnd(76 + (j.toFloat().div(j).toInt()), '-') + "+")
println()
}
println(" \n")
}
}

View File

@ -24,31 +24,26 @@ package org.mosad.seil0.projectlaogai.uicomponents
import android.content.Context import android.content.Context
import android.graphics.Color import android.graphics.Color
import android.util.AttributeSet
import android.widget.LinearLayout import android.widget.LinearLayout
import android.widget.TextView import androidx.cardview.widget.CardView
import kotlinx.android.synthetic.main.cardview_day.view.*
import org.mosad.seil0.projectlaogai.R import org.mosad.seil0.projectlaogai.R
class LessonCardView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) : androidx.cardview.widget.CardView(context, attrs){ class DayCardView(context: Context) : CardView(context) {
private var linLayoutLesson: LinearLayout
private var txtViewTime: TextView
init { init {
inflate(context, R.layout.lesson_cardview,this) inflate(context, R.layout.cardview_day,this)
linLayoutLesson = findViewById(R.id.linLayout_Lesson)
txtViewTime = findViewById(R.id.txtView_Time)
// workaround to prevent a white border // workaround to prevent a white border
this.setBackgroundColor(Color.TRANSPARENT) this.setBackgroundColor(Color.TRANSPARENT)
} }
fun getLinLayoutLesson(): LinearLayout { fun getLinLayoutDay() : LinearLayout {
return linLayoutLesson return linLayout_Day
} }
fun getTxtViewTime(): TextView { fun setDayHeading(heading: String) {
return txtViewTime txtView_DayHeading.text = heading
} }
} }

View File

@ -23,32 +23,28 @@
package org.mosad.seil0.projectlaogai.uicomponents package org.mosad.seil0.projectlaogai.uicomponents
import android.content.Context import android.content.Context
import android.util.AttributeSet import android.view.View
import android.widget.LinearLayout import android.widget.LinearLayout
import android.widget.TextView import androidx.cardview.widget.CardView
import kotlinx.android.synthetic.main.linearlayout_lesson.view.*
import org.mosad.seil0.projectlaogai.R import org.mosad.seil0.projectlaogai.R
import org.mosad.seil0.projectlaogai.hsoparser.Lesson
class MensaDayCardView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) : androidx.cardview.widget.CardView(context, attrs){ class LessonLinearLayout(context: Context?) : LinearLayout(context) {
private var linLayoutMensaDay: LinearLayout
private var txtViewDayHeading: TextView
init { init {
inflate(context, R.layout.mensaday_cardview,this) CardView.inflate(context, R.layout.linearlayout_lesson, this)
linLayoutMensaDay = findViewById(R.id.linLayout_MensaDay)
txtViewDayHeading = findViewById(R.id.txtView_DayHeading)
// workaround to prevent a white border
//this.setBackgroundColor(Color.TRANSPARENT)
} }
fun getLinLayoutMensaDay(): LinearLayout { fun setLesson(lesson: Lesson, time: String) {
return linLayoutMensaDay txtView_lessonTime.text = time
txtView_lessonSubject.text = lesson.lessonSubject
txtView_lessonTeacher.text = lesson.lessonTeacher
txtView_lessonRoom.text = lesson.lessonRoom
} }
fun setDayHeading(heading: String) { fun disableDivider() {
txtViewDayHeading.text = heading divider_lesson.visibility = View.GONE
} }
} }

View File

@ -1,26 +0,0 @@
package org.mosad.seil0.projectlaogai.uicomponents
import android.content.Context
import android.graphics.Color
import android.util.AttributeSet
import android.widget.TextView
import org.mosad.seil0.projectlaogai.hsoparser.Lesson
class LessonTextView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) : TextView(context, attrs) {
init {
this.setTextColor(Color.BLACK)
this.textSize = 16F
this.setPadding(0,6,0,0)
}
fun setLesson(lesson: Lesson) {
this.text = resources.getString(org.mosad.seil0.projectlaogai.R.string.string_new_line, lesson.lessonSubject)
this.append(lesson.lessonTeacher + "\n")
this.append(lesson.lessonRoom)
}
fun setText(text: String) {
this.text = text
}
}

View File

@ -0,0 +1,53 @@
/**
* ProjectLaogai
*
* Copyright 2019 <seil0@mosad.xyz>
*
* 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
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
*/
package org.mosad.seil0.projectlaogai.uicomponents
import android.content.Context
import android.view.View
import android.widget.LinearLayout
import androidx.cardview.widget.CardView
import kotlinx.android.synthetic.main.linearlayout_meal.view.*
import org.mosad.seil0.projectlaogai.R
import org.mosad.seil0.projectlaogai.hsoparser.Meal
class MealLinearLayout(context: Context?): LinearLayout(context) {
init {
CardView.inflate(context, R.layout.linearlayout_meal, this)
}
fun setMeal(meal: Meal) {
txtView_MealHeading.text = meal.heading
meal.parts.forEachIndexed { partIndex, part ->
txtView_Meal.append(part)
if(partIndex < (meal.parts.size - 1))
txtView_Meal.append("\n")
}
}
fun disableDivider() {
divider_meal.visibility = View.GONE
}
}

View File

@ -1,31 +0,0 @@
package org.mosad.seil0.projectlaogai.uicomponents
import android.content.Context
import android.graphics.Color
import android.util.AttributeSet
import android.widget.TextView
import org.mosad.seil0.projectlaogai.R
class MenuCardView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) : androidx.cardview.widget.CardView(context, attrs){
private var txtViewMenuHeading: TextView
private var txtViewMenu: TextView
init {
inflate(context, R.layout.menu_cardview,this)
txtViewMenuHeading = findViewById(R.id.txtView_MenuHeading)
txtViewMenu = findViewById(R.id.txtView_Menu)
// workaround to prevent a white border
this.setBackgroundColor(Color.TRANSPARENT)
}
fun setMenuHeading(heading: String) {
txtViewMenuHeading.text = heading
}
fun getTxtViewMenu(): TextView {
return txtViewMenu
}
}

View File

@ -1,8 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item <item android:drawable="@color/colorPrimary"/>
android:drawable="@color/colorPrimary"/>
<!--TODO when minAPI is 23 use this--> <!--TODO when minAPI is 23 use this-->
<!--<item android:gravity="center" android:width="144dp" android:height="144dp">--> <!--<item android:gravity="center" android:width="144dp" android:height="144dp">-->

View File

@ -21,6 +21,7 @@
android:layout_gravity="start" android:layout_gravity="start"
android:fitsSystemWindows="true" android:fitsSystemWindows="true"
app:headerLayout="@layout/nav_header_main" app:headerLayout="@layout/nav_header_main"
app:itemTextColor="?colorAccent"
app:menu="@menu/activity_main_drawer"/> app:menu="@menu/activity_main_drawer"/>
</androidx.drawerlayout.widget.DrawerLayout> </androidx.drawerlayout.widget.DrawerLayout>

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content" app:cardUseCompatPadding="true"
app:cardElevation="5dp" app:cardBackgroundColor="@color/themeSecondary"
>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent" android:id="@+id/linLayout_Day">
<TextView
android:text="@string/sample_date"
android:layout_width="match_parent"
android:layout_height="wrap_content" android:id="@+id/txtView_DayHeading" android:textSize="18sp"
android:textAlignment="center" android:textStyle="bold" android:textColor="?colorAccent"/>
</LinearLayout>
</androidx.cardview.widget.CardView>

View File

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
tools:context=".fragments.HomeFragment"> tools:context=".fragments.HomeFragment">
@ -10,97 +9,13 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<androidx.cardview.widget.CardView
android:id="@+id/cardView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:layout_marginTop="5dp"
android:layout_marginEnd="5dp"
android:clickable="false"
android:maxHeight="125dp"
app:cardUseCompatPadding="true"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" android:elevation="5dp">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_marginBottom="2dp">
<TextView
android:text="@string/meal_1"
android:layout_width="match_parent"
android:layout_height="wrap_content" android:id="@+id/txtView_Menu1Heading"
android:textStyle="bold" android:textAlignment="center" android:textSize="16sp"
android:typeface="sans" android:fontFamily="sans-serif" android:paddingBottom="5dp"/>
<TextView
android:id="@+id/txtViewMenu1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="sans-serif"
android:textAlignment="center"
android:textSize="16sp"
android:textStyle="bold"
android:typeface="sans"
android:textIsSelectable="true"/>
</LinearLayout>
</androidx.cardview.widget.CardView>
<androidx.cardview.widget.CardView
android:id="@+id/cardView2"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:cardUseCompatPadding="true"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/cardView" android:elevation="5dp"
android:layout_marginEnd="5dp" android:layout_marginStart="5dp">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_marginBottom="2dp">
<TextView
android:text="@string/meal_2"
android:layout_width="match_parent"
android:layout_height="wrap_content" android:id="@+id/txtView_Menu2Heading"
android:textAlignment="center" android:textStyle="bold" android:textSize="16sp"
android:typeface="sans" android:fontFamily="sans-serif" android:paddingBottom="5dp"/>
<TextView
android:id="@+id/txtViewMenu2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="sans-serif"
android:textAlignment="center"
android:textSize="16sp"
android:textStyle="bold"
android:typeface="sans"
android:textIsSelectable="true"/>
</LinearLayout>
</androidx.cardview.widget.CardView>
<ScrollView <ScrollView
android:layout_width="0dp" android:layout_width="match_parent"
android:layout_height="0dp" android:layout_height="match_parent">
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/cardView2" android:id="@+id/scrollViewTimeTable"
android:background="@color/md_divider_dark_theme" android:paddingTop="6dp"
android:layout_marginTop="5dp">
<LinearLayout <LinearLayout
android:id="@+id/linLayoutTimeTable"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent" android:layout_width="match_parent"
app:layout_constraintEnd_toEndOf="parent" android:layout_height="wrap_content" android:id="@+id/linLayout_Home">
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/cardView2">
</LinearLayout> </LinearLayout>
</ScrollView> </ScrollView>

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
tools:context=".fragments.MensaFragment"> tools:context=".fragments.MensaFragment">
@ -15,10 +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_MensaFragment" android:layout_height="wrap_content" android:id="@+id/linLayout_Mensa"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" android:background="@color/themePrimary">
app:layout_constraintTop_toTopOf="parent"
>
</LinearLayout> </LinearLayout>
</ScrollView> </ScrollView>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -14,7 +14,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" app:layout_constraintTop_toTopOf="parent" android:layout_height="match_parent" app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent"
> android:background="@android:color/background_light">
<androidx.cardview.widget.CardView <androidx.cardview.widget.CardView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -30,7 +30,7 @@
android:layout_height="wrap_content" android:id="@+id/txtView_Info" android:layout_height="wrap_content" android:id="@+id/txtView_Info"
android:typeface="sans" android:typeface="sans"
android:textSize="18sp" android:textStyle="bold" android:fontFamily="sans-serif" android:textSize="18sp" android:textStyle="bold" android:fontFamily="sans-serif"
android:layout_margin="7dp" android:textColor="@color/colorPrimary"/> android:layout_margin="7dp" android:textColor="?colorAccent"/>
<LinearLayout <LinearLayout
android:orientation="vertical" android:orientation="vertical"
android:layout_width="match_parent" android:layout_width="match_parent"
@ -78,7 +78,7 @@
android:orientation="vertical" android:orientation="vertical"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_margin="7dp" android:layout_height="match_parent" android:layout_margin="7dp"
android:id="@+id/linLayout_Info"> android:id="@+id/linLayout_About">
<TextView <TextView
android:text="@string/about_txtView" android:text="@string/about_txtView"
android:layout_width="match_parent" android:layout_width="match_parent"
@ -86,9 +86,9 @@
android:textStyle="bold" android:textSize="16sp" android:textStyle="bold" android:textSize="16sp"
android:textColor="@android:color/primary_text_light"/> android:textColor="@android:color/primary_text_light"/>
<TextView <TextView
android:text="@string/version" android:text="@string/about_version"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:id="@+id/txtView_Version"/> android:layout_height="wrap_content" android:id="@+id/txtView_AboutDesc"/>
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
</androidx.cardview.widget.CardView> </androidx.cardview.widget.CardView>
@ -100,20 +100,20 @@
<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_Settings"> android:layout_height="wrap_content" android:id="@+id/linLayout_Settings" android:padding="7dp">
<TextView <TextView
android:text="@string/settings" android:text="@string/settings"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:id="@+id/txtView_Settings" android:layout_height="wrap_content" android:id="@+id/txtView_Settings"
android:typeface="sans" android:typeface="sans"
android:textSize="18sp" android:textColor="@color/design_default_color_primary" android:textSize="18sp" android:textColor="?colorAccent"
android:textStyle="bold" android:layout_margin="7dp" android:paddingTop="3dp"/> android:textStyle="bold" android:paddingTop="3dp"/>
<LinearLayout <LinearLayout
android:orientation="horizontal" android:orientation="horizontal"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_margin="7dp" android:layout_height="wrap_content"
android:gravity="center_vertical|end" android:gravity="center_vertical|end"
android:clickable="true" android:id="@+id/linLayout_MainColor" android:focusable="true"> android:clickable="true" android:id="@+id/linLayout_PrimaryColor" android:focusable="true">
<LinearLayout <LinearLayout
android:orientation="vertical" android:orientation="vertical"
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -125,7 +125,7 @@
android:textSize="16sp" android:textStyle="bold" android:textSize="16sp" android:textStyle="bold"
android:textColor="@android:color/primary_text_light"/> android:textColor="@android:color/primary_text_light"/>
<TextView <TextView
android:text="@string/main_color_desc" android:text="@string/primary_color_desc"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:id="@+id/txtView_PrimaryColorDesc"/> android:layout_height="wrap_content" android:id="@+id/txtView_PrimaryColorDesc"/>
</LinearLayout> </LinearLayout>
@ -140,6 +140,44 @@
android:background="?colorPrimary"/> android:background="?colorPrimary"/>
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical|end"
android:clickable="true" android:id="@+id/linLayout_AccentColor" android:focusable="true">
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:text="@string/accent_color"
android:layout_width="match_parent"
android:layout_height="wrap_content" android:id="@+id/txtView_AccentColor"
android:textSize="16sp" android:textStyle="bold"
android:textColor="@android:color/primary_text_light"/>
<TextView
android:text="@string/accent_color_desc"
android:layout_width="match_parent"
android:layout_height="wrap_content" android:id="@+id/txtView_AccentColorDesc"/>
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_margin="7dp"
android:gravity="end">
<View
android:layout_width="40dp"
android:layout_height="40dp" android:id="@+id/view_AccentColor"
android:background="?colorAccent"/>
</LinearLayout>
</LinearLayout>
<Switch
android:layout_width="match_parent"
android:layout_height="wrap_content" android:id="@+id/switch_buffet"
android:textSize="16sp"
android:textColor="@android:color/primary_text_light" android:textStyle="bold"
android:text="@string/show_buffet"/>
</LinearLayout> </LinearLayout>
</androidx.cardview.widget.CardView> </androidx.cardview.widget.CardView>
</LinearLayout> </LinearLayout>

View File

@ -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_TTFragment"> android:layout_height="wrap_content" android:id="@+id/linLayout_Timetable"
android:background="@color/themePrimary">
</LinearLayout> </LinearLayout>
</ScrollView> </ScrollView>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -1,23 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardBackgroundColor="@android:color/background_light"
app:cardElevation="5dp"
app:cardUseCompatPadding="true" app:cardPreventCornerOverlap="false" app:contentPadding="5dp">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent" android:id="@+id/linLayout_Lesson">
<TextView
android:id="@+id/txtView_Time"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="end"
android:text="@string/a_time"/>
</LinearLayout>
</androidx.cardview.widget.CardView>

View File

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content" android:id="@+id/linLayout_lesson" android:padding="7dp">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content" android:id="@+id/txtView_lessonSubject" android:layout_weight="1"
android:textSize="15sp" android:textColor="@color/textPrimary"/>
<TextView
android:text="@string/a_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content" android:id="@+id/txtView_lessonTime" android:layout_weight="1"
android:textColor="@color/textSecondary" android:gravity="end"/>
</LinearLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content" android:id="@+id/txtView_lessonTeacher" android:textSize="15sp"
android:textColor="@color/textPrimary"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content" android:id="@+id/txtView_lessonRoom"
android:textColor="@color/textPrimary"/>
<View
android:id="@+id/divider_lesson"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="?android:attr/listDivider"
/>
</LinearLayout>

View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent" android:id="@+id/linLayout_Meal" android:padding="7dp">
<TextView
android:text="@string/meal"
android:layout_width="match_parent"
android:layout_height="wrap_content" android:id="@+id/txtView_MealHeading" android:textSize="18sp"
android:textColor="@color/textPrimary" android:textAlignment="center" android:paddingBottom="5dp"
android:textStyle="bold"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content" android:id="@+id/txtView_Meal" android:textSize="15sp"
android:textColor="@color/textPrimary" android:textAlignment="center"/>
<View
android:id="@+id/divider_meal"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="?android:attr/listDivider"
/>
</LinearLayout>

View File

@ -1,22 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="9dp"
app:cardElevation="5dp"
app:cardBackgroundColor="@color/colorMensaDay"
app:cardUseCompatPadding="true">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content" android:id="@+id/linLayout_MensaDay" android:paddingBottom="5dp">
<TextView
android:text="@string/sample_date"
android:layout_width="match_parent"
android:layout_height="wrap_content" android:id="@+id/txtView_DayHeading" android:textAlignment="center"
android:textSize="20sp" android:textStyle="bold" android:typeface="sans" android:paddingBottom="5dp"/>
</LinearLayout>
</androidx.cardview.widget.CardView>

View File

@ -1,42 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/cardView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:layout_marginTop="5dp"
android:layout_marginEnd="5dp"
android:clickable="false"
android:maxHeight="125dp"
app:cardUseCompatPadding="true"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:text="@string/meal_1"
android:layout_width="match_parent"
android:layout_height="wrap_content" android:id="@+id/txtView_MenuHeading"
android:textStyle="bold" android:textAlignment="center" android:textSize="16sp"
android:typeface="sans" android:fontFamily="sans-serif" android:paddingBottom="5dp"/>
<TextView
android:id="@+id/txtView_Menu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="sans-serif"
android:textAlignment="center"
android:textSize="16sp"
android:textStyle="bold"
android:typeface="sans"
android:textIsSelectable="true"/>
</LinearLayout>
</androidx.cardview.widget.CardView>

View File

@ -27,7 +27,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingTop="@dimen/nav_header_vertical_spacing" android:paddingTop="@dimen/nav_header_vertical_spacing"
android:text="@string/nav_header_title" android:text="@string/nav_header_title"
android:textAppearance="@style/TextAppearance.AppCompat.Body1"/> android:textAppearance="@style/TextAppearance.AppCompat.Body1" android:id="@+id/txtView_nav_header_title"/>
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"

View File

@ -4,7 +4,10 @@
tools:showIn="navigation_view"> tools:showIn="navigation_view">
<group android:checkableBehavior="single"> <group android:checkableBehavior="single">
<item android:id="@+id/nav_home" android:title="@string/home" android:icon="@drawable/ic_baseline_home_24dp"/> <item
android:id="@+id/nav_home"
android:title="@string/home"
android:icon="@drawable/ic_baseline_home_24dp"/>
<item <item
android:id="@+id/nav_mensa" android:id="@+id/nav_mensa"
android:icon="@drawable/ic_local_dining_black_24dp" android:icon="@drawable/ic_local_dining_black_24dp"

View File

@ -5,12 +5,10 @@
<string name="timetable">Stundenplan</string> <string name="timetable">Stundenplan</string>
<string name="moodle">Moodle</string> <string name="moodle">Moodle</string>
<string name="settings">Einstellungen</string> <string name="settings">Einstellungen</string>
<string name="meal_1">Essen 1</string> <string name="meal">Essen</string>
<string name="meal_2">Essen 2</string> <string name="today_date">Heute, %1$s</string>
<string name="meal_1_tomorrow">Essen 1, Morgen</string> <string name="tomorrow_date">Morgen, %1$s</string>
<string name="meal_2_tomorrow">Essen 1, Morgen</string> <string name="mensa_closed">keine Essensausgabe</string>
<string name="no_meal_today">heute keine Essensausgabe</string>
<string name="no_meal_tomorrow">morgen keine Essensausgabe</string>
<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>
@ -19,11 +17,15 @@
<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>
<string name="primary_color">Primärfarbe</string> <string name="primary_color">Hauptfarbe</string>
<string name="main_color_desc">Die Primärfarbe, standard ist Schwarz</string> <string name="primary_color_desc">Die Primärfarbe, Standard ist Schwarz.</string>
<string name="accent_color">Akzentfarbe</string>
<string name="accent_color_desc">Die Akzentfarbe, Standard ist indigo</string>
<string name="select">auswählen</string> <string name="select">auswählen</string>
<string name="about">über</string> <string name="about_dialog_heading">Über</string>
<string name="loading_timetable">lade Stundenplan …</string> <string name="loading_timetable">lade Stundenplan …</string>
<string name="navigation_drawer_close">Navigationsleiste schließen</string> <string name="navigation_drawer_close">Navigationsleiste schließen</string>
<string name="navigation_drawer_open">Navigationsleiste öffnen</string> <string name="navigation_drawer_open">Navigationsleiste öffnen</string>
<string name="show_buffet">Buffet immer anzeigen</string>
<string name="select_course">Wähle deinen Studiengang aus</string>
</resources> </resources>

View File

@ -2,7 +2,31 @@
<resources> <resources>
<color name="colorPrimary">#000000</color> <color name="colorPrimary">#000000</color>
<color name="colorPrimaryDark">#000000</color> <color name="colorPrimaryDark">#000000</color>
<color name="colorAccent">#d81b60</color> <color name="colorAccent">#3F51B5</color>
<color name="colorMensaDay">#ebe8e9</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="themeSecondary">#FFFFFF</color>
<color name="themeTertiary">#FAFAFA</color> <!-- TODO find a better color -->
<color name="textPrimary">#000000</color>
<color name="textSecondary">#818181</color>
<!--theme color section, not the working colors-->
<color name="textPrimaryDark">#FFFFFF</color>
<color name="textSecondaryDark">#E0E0E0</color>
<color name="textPrimaryLight">#000000</color>
<color name="textSecondaryLight">#818181</color>
<color name="themePrimaryDark">#000000</color>
<color name="themeSecondaryDark">#303030</color>
<color name="themeTertiaryDark">#424242</color>
<color name="themePrimaryLight">#FFFFFF</color>
<color name="themeSecondaryLight">#FFFFFF</color>
<color name="themeTertiaryLight">#424242</color> <!-- TODO find a better color -->
<color name="test">#424242</color>
</resources> </resources>

View File

@ -2,7 +2,7 @@
<string name="app_name" translatable="false">Project Laogai</string> <string name="app_name" translatable="false">Project Laogai</string>
<string name="navigation_drawer_open">Open navigation drawer</string> <string name="navigation_drawer_open">Open navigation drawer</string>
<string name="navigation_drawer_close">Close navigation drawer</string> <string name="navigation_drawer_close">Close navigation drawer</string>
<string name="nav_header_title" translatable="false">hso App 0.3.3</string> <string name="nav_header_title" translatable="false">Project Laogai</string>
<string name="nav_header_subtitle" translatable="false">seil0@mosad.xyz</string> <string name="nav_header_subtitle" translatable="false">seil0@mosad.xyz</string>
<string name="nav_header_desc" translatable="false">Project Laogai</string> <string name="nav_header_desc" translatable="false">Project Laogai</string>
@ -12,12 +12,10 @@
<string name="moodle">Moodle</string> <string name="moodle">Moodle</string>
<string name="settings">Settings</string> <string name="settings">Settings</string>
<string name="meal_1">Meal 1</string> <string name="meal">Meal</string>
<string name="meal_2">Meal 2</string> <string name="today_date">Today, %1$s</string>
<string name="meal_1_tomorrow">Meal 1, tomorrow</string> <string name="tomorrow_date">Tomorrow, %1$s</string>
<string name="meal_2_tomorrow">Meal 2, tomorrow</string> <string name="mensa_closed">the Mensa is closed</string>
<string name="no_meal_today">Mensa closed today</string>
<string name="no_meal_tomorrow">Mensa closed tomorrow</string>
<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>
@ -28,28 +26,31 @@
<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>
<string name="sample_date" translatable="false">Montag, 30.02</string> <string name="sample_date" translatable="false">Montag, 30.02</string>
<string name="a_lesson" translatable="false">a lesson\na teacher\na room</string>
<string name="a_time" translatable="false">0.00 23.59</string> <string name="a_time" translatable="false">0.00 23.59</string>
<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="select_course">Select your course</string>
<string name="primary_color">primary color</string> <string name="primary_color">primary color</string>
<string name="main_color_desc">The primary color, default is black</string> <string name="primary_color_desc">The primary color, default is black.</string>
<string name="accent_color">accent color</string>
<string name="accent_color_desc">The accent color, default is indigo.</string>
<string name="show_buffet">always show buffet</string>
<string name="select">select</string> <string name="select">select</string>
<string name="version" translatable="false">version 0.3.3</string>
<string name="about">about</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_text" translatable="false">"This software is made by @Seil0 and is published under the terms and <string name="about_version" translatable="false">version %1$s (%2$s)</string>
conditions of GPL 3. For further information visit \ngit.mosad.xyz/Seil0/ProjectLaogai \n\n© 2018-2019 <string name="about_dialog_heading">About</string>
seil0@mosad.xyz " <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>
<string name="loading_timetable">loading timetable …</string> <string name="loading_timetable">loading timetable …</string>
<string name="string_new_line" translatable="false">%1$s\n</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>
<string name="save_key_colorAccent" translatable="false">org.mosad.seil0.projectlaogai.colorAccent</string>
<string name="save_key_showBuffet" translatable="false">org.mosad.seil0.projectlaogai.showBuffet</string>
<string name="save_key_coursesCacheTime" translatable="false">org.mosad.seil0.projectlaogai.coursesCacheTime</string>
<string name="save_key_mensaCacheTime" translatable="false">org.mosad.seil0.projectlaogai.mensaCacheTime</string>
<string name="save_key_timetableCacheTime" translatable="false">org.mosad.seil0.projectlaogai.timetableCacheTime</string>
</resources> </resources>

View File

@ -7,7 +7,7 @@ buildscript {
jcenter() jcenter()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:3.3.1' classpath 'com.android.tools.build:gradle:3.3.2'
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
@ -19,7 +19,6 @@ allprojects {
repositories { repositories {
google() google()
jcenter() jcenter()
maven { url "https://dl.bintray.com/drummer-aidan/maven/" }
} }
} }

View File

@ -0,0 +1,8 @@
ProjectLaogai is a app to access the timetable and the mensa menu
of Hochschule Offenburg.
Features:
* check out the mensa menu of this and next week
* access your timetable
* open moodle
* probably some funny bugs

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 KiB

View File

@ -0,0 +1 @@
access the timetable and mensa menu at Hochschule Offenburg

View File

@ -0,0 +1 @@
ProjectLaogai