WeserPlaner 1.0.0: updated minor things and changed name from 'Stud.IP Timetable' to 'WeserPlaner'

This commit is contained in:
denizk0461
2023-05-06 22:56:37 +02:00
parent e1ea3ecc11
commit 4ad952f1ae
68 changed files with 358 additions and 372 deletions
-3
View File
@@ -1,3 +0,0 @@
# Default ignored files
/shelf/
/workspace.xml
-17
View File
@@ -1,17 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="deploymentTargetDropDown">
<targetSelectedWithDropDown>
<Target>
<type value="QUICK_BOOT_TARGET" />
<deviceKey>
<Key>
<type value="VIRTUAL_DEVICE_PATH" />
<value value="C:\Users\kduez\.android\avd\Pixel_6_A13_.avd" />
</Key>
</deviceKey>
</Target>
</targetSelectedWithDropDown>
<timeTargetWasSelectedWithDropDown value="2023-05-02T10:34:36.007714500Z" />
</component>
</project>
-1
View File
@@ -7,7 +7,6 @@
<option name="testRunner" value="GRADLE" /> <option name="testRunner" value="GRADLE" />
<option name="distributionType" value="DEFAULT_WRAPPED" /> <option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" /> <option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleJvm" value="Embedded JDK" />
<option name="modules"> <option name="modules">
<set> <set>
<option value="$PROJECT_DIR$" /> <option value="$PROJECT_DIR$" />
-23
View File
@@ -1,23 +0,0 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="AddConversionCallMigration" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AmbiguousExpressionInWhenBranchMigration" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AndroidLintLambdaLast" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AndroidLintLogConditional" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AndroidLintNegativeMargin" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AndroidLintStringFormatTrivial" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AndroidLintTypos" enabled="true" level="TYPO" enabled_by_default="true" />
<inspection_tool class="BooleanParameter" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="Destructure" enabled="true" level="INFO" enabled_by_default="true" />
<inspection_tool class="DirectUseOfResultType" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="IncompleteDestructuring" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="NoConstructorMigration" enabled="true" level="ERROR" enabled_by_default="true" />
<inspection_tool class="NonExhaustiveWhenStatementMigration" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="PublicApiImplicitType" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="RedundantInnerClassModifier" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="ReplaceCollectionCountWithSize" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="ReplaceNotNullAssertionWithElvisReturn" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="WhenWithOnlyElse" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
</profile>
</component>
Generated
+1 -1
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="VcsDirectoryMappings"> <component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" /> <mapping directory="" vcs="Git" />
</component> </component>
</project> </project>
+3 -5
View File
@@ -5,11 +5,11 @@ plugins {
} }
android { android {
namespace 'com.denizk0461.studip' namespace 'com.denizk0461.weserplaner'
compileSdk 33 compileSdk 33
defaultConfig { defaultConfig {
applicationId "com.denizk0461.studip" applicationId "com.denizk0461.weserplaner"
minSdk 24 minSdk 24
targetSdk 33 targetSdk 33
versionCode 1 versionCode 1
@@ -26,6 +26,7 @@ android {
release { release {
minifyEnabled false minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.debug
} }
} }
compileOptions { compileOptions {
@@ -51,9 +52,6 @@ dependencies {
implementation 'androidx.navigation:navigation-ui-ktx:2.5.3' implementation 'androidx.navigation:navigation-ui-ktx:2.5.3'
implementation 'androidx.core:core-ktx:1.10.0' implementation 'androidx.core:core-ktx:1.10.0'
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.2.0-alpha01' implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.2.0-alpha01'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
implementation "androidx.room:room-runtime:2.5.1" implementation "androidx.room:room-runtime:2.5.1"
kapt "androidx.room:room-compiler:2.5.1" kapt "androidx.room:room-compiler:2.5.1"
Binary file not shown.
@@ -1,24 +0,0 @@
package com.denizk0461.studip
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.Assert.*
/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("com.denizk0461.studip", appContext.packageName)
}
}
@@ -1,4 +1,4 @@
package com.denizk0461.studip.activity package com.denizk0461.weserplaner.activity
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.os.Bundle import android.os.Bundle
@@ -8,12 +8,12 @@ import android.webkit.WebView
import android.webkit.WebViewClient import android.webkit.WebViewClient
import androidx.fragment.app.FragmentActivity import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import com.denizk0461.studip.R import com.denizk0461.weserplaner.R
import com.denizk0461.studip.data.showErrorSnackBar import com.denizk0461.weserplaner.data.showErrorSnackBar
import com.denizk0461.studip.data.showToast import com.denizk0461.weserplaner.data.showToast
import com.denizk0461.studip.databinding.ActivityFetcherBinding import com.denizk0461.weserplaner.databinding.ActivityFetcherBinding
import com.denizk0461.studip.sheet.TextSheet import com.denizk0461.weserplaner.sheet.TextSheet
import com.denizk0461.studip.viewmodel.FetcherViewModel import com.denizk0461.weserplaner.viewmodel.FetcherViewModel
import java.io.IOException import java.io.IOException
import java.net.URLDecoder import java.net.URLDecoder
@@ -1,10 +1,10 @@
package com.denizk0461.studip.activity package com.denizk0461.weserplaner.activity
import android.os.Bundle import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.WindowCompat import androidx.core.view.WindowCompat
import com.denizk0461.studip.R import com.denizk0461.weserplaner.R
import com.denizk0461.studip.databinding.ActivityImageBinding import com.denizk0461.weserplaner.databinding.ActivityImageBinding
/** /**
* Activity used solely to display a single image. Not a critical part of the app. * Activity used solely to display a single image. Not a critical part of the app.
@@ -1,4 +1,4 @@
package com.denizk0461.studip.activity package com.denizk0461.weserplaner.activity
import android.os.Bundle import android.os.Bundle
import androidx.core.view.WindowCompat import androidx.core.view.WindowCompat
@@ -7,9 +7,9 @@ import androidx.lifecycle.ViewModelProvider
import androidx.navigation.fragment.NavHostFragment import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import androidx.navigation.ui.setupWithNavController import androidx.navigation.ui.setupWithNavController
import com.denizk0461.studip.R import com.denizk0461.weserplaner.R
import com.denizk0461.studip.databinding.ActivityMainBinding import com.denizk0461.weserplaner.databinding.ActivityMainBinding
import com.denizk0461.studip.viewmodel.MainViewModel import com.denizk0461.weserplaner.viewmodel.MainViewModel
/** /**
* Main activity that handles all common fragments. This is opened on app launch. * Main activity that handles all common fragments. This is opened on app launch.
@@ -1,4 +1,4 @@
package com.denizk0461.studip.adapter package com.denizk0461.weserplaner.adapter
import android.content.res.ColorStateList import android.content.res.ColorStateList
import android.view.LayoutInflater import android.view.LayoutInflater
@@ -6,15 +6,15 @@ import android.view.ViewGroup
import androidx.appcompat.content.res.AppCompatResources import androidx.appcompat.content.res.AppCompatResources
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.denizk0461.studip.R import com.denizk0461.weserplaner.R
import com.denizk0461.studip.data.AppDiffUtilCallback import com.denizk0461.weserplaner.data.AppDiffUtilCallback
import com.denizk0461.studip.data.getThemedColor import com.denizk0461.weserplaner.data.getThemedColor
import com.denizk0461.studip.databinding.ItemCanteenBinding import com.denizk0461.weserplaner.databinding.ItemCanteenBinding
import com.denizk0461.studip.databinding.ItemCanteenLineBinding import com.denizk0461.weserplaner.databinding.ItemCanteenLineBinding
import com.denizk0461.studip.databinding.ItemIconBinding import com.denizk0461.weserplaner.databinding.ItemIconBinding
import com.denizk0461.studip.model.CanteenOfferGroup import com.denizk0461.weserplaner.model.CanteenOfferGroup
import com.denizk0461.studip.model.CanteenOfferGroupElement import com.denizk0461.weserplaner.model.CanteenOfferGroupElement
import com.denizk0461.studip.model.DietaryPreferences import com.denizk0461.weserplaner.model.DietaryPreferences
/** /**
* Custom RecyclerView adapter that lays out the offers of a given canteen on a given day. * Custom RecyclerView adapter that lays out the offers of a given canteen on a given day.
@@ -1,11 +1,11 @@
package com.denizk0461.studip.adapter package com.denizk0461.weserplaner.adapter
import android.os.Bundle import android.os.Bundle
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentManager
import androidx.lifecycle.Lifecycle import androidx.lifecycle.Lifecycle
import androidx.viewpager2.adapter.FragmentStateAdapter import androidx.viewpager2.adapter.FragmentStateAdapter
import com.denizk0461.studip.fragment.CanteenPageFragment import com.denizk0461.weserplaner.fragment.CanteenPageFragment
/** /**
* Custom ViewPager adapter for managing multiple pages of canteen offers. * Custom ViewPager adapter for managing multiple pages of canteen offers.
@@ -1,4 +1,4 @@
package com.denizk0461.studip.adapter package com.denizk0461.weserplaner.adapter
import android.content.res.ColorStateList import android.content.res.ColorStateList
import android.view.LayoutInflater import android.view.LayoutInflater
@@ -6,12 +6,12 @@ import android.view.ViewGroup
import androidx.appcompat.content.res.AppCompatResources.getDrawable import androidx.appcompat.content.res.AppCompatResources.getDrawable
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.denizk0461.studip.data.AppDiffUtilCallback import com.denizk0461.weserplaner.data.AppDiffUtilCallback
import com.google.android.material.R import com.google.android.material.R
import com.denizk0461.studip.data.getThemedColor import com.denizk0461.weserplaner.data.getThemedColor
import com.denizk0461.studip.data.parseToMinutes import com.denizk0461.weserplaner.data.parseToMinutes
import com.denizk0461.studip.model.StudIPEvent import com.denizk0461.weserplaner.model.StudIPEvent
import com.denizk0461.studip.databinding.ItemEventBinding import com.denizk0461.weserplaner.databinding.ItemEventBinding
import java.util.* import java.util.*
/** /**
@@ -98,12 +98,12 @@ class StudIPEventItemAdapter(
} }
// Set the divider colour to the text colour // Set the divider colour to the text colour
holder.binding.divider.dividerColor = holder.binding.divider.dividerColor =
theme.getThemedColor(com.denizk0461.studip.R.attr.colorText) theme.getThemedColor(com.denizk0461.weserplaner.R.attr.colorText)
// Set ripple colour // Set ripple colour
holder.binding.linearLayout.background = getDrawable( holder.binding.linearLayout.background = getDrawable(
holder.binding.root.context, holder.binding.root.context,
com.denizk0461.studip.R.drawable.selectable_item_background_highlighted, com.denizk0461.weserplaner.R.drawable.selectable_item_background_highlighted,
) )
// Otherwise, apply colours to ensure that the item will not be highlighted // Otherwise, apply colours to ensure that the item will not be highlighted
@@ -114,7 +114,7 @@ class StudIPEventItemAdapter(
ColorStateList.valueOf(theme.getThemedColor(R.attr.colorSurface)) ColorStateList.valueOf(theme.getThemedColor(R.attr.colorSurface))
// Set the card's stroke to its default colour // Set the card's stroke to its default colour
strokeColor = theme.getThemedColor(R.attr.colorOutline) strokeColor = theme.getThemedColor(R.attr.colorOutlineVariant)
} }
// Set the divider colour to its default value // Set the divider colour to its default value
holder.binding.divider.dividerColor = theme.getThemedColor(R.attr.colorOutlineVariant) holder.binding.divider.dividerColor = theme.getThemedColor(R.attr.colorOutlineVariant)
@@ -122,7 +122,7 @@ class StudIPEventItemAdapter(
// Set ripple colour // Set ripple colour
holder.binding.linearLayout.background = getDrawable( holder.binding.linearLayout.background = getDrawable(
holder.binding.root.context, holder.binding.root.context,
com.denizk0461.studip.R.drawable.selectable_item_background, com.denizk0461.weserplaner.R.drawable.selectable_item_background,
) )
} }
@@ -1,11 +1,11 @@
package com.denizk0461.studip.adapter package com.denizk0461.weserplaner.adapter
import android.os.Bundle import android.os.Bundle
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentManager
import androidx.lifecycle.Lifecycle import androidx.lifecycle.Lifecycle
import androidx.viewpager2.adapter.FragmentStateAdapter import androidx.viewpager2.adapter.FragmentStateAdapter
import com.denizk0461.studip.fragment.EventPageFragment import com.denizk0461.weserplaner.fragment.EventPageFragment
/** /**
* Custom ViewPager adapter for managing multiple pages of Stud.IP events. * Custom ViewPager adapter for managing multiple pages of Stud.IP events.
@@ -1,4 +1,4 @@
package com.denizk0461.studip.data package com.denizk0461.weserplaner.data
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
@@ -1,4 +1,4 @@
package com.denizk0461.studip.data package com.denizk0461.weserplaner.data
import android.content.Context import android.content.Context
import android.content.res.Resources import android.content.res.Resources
@@ -11,10 +11,10 @@ import android.widget.Toast
import androidx.annotation.AttrRes import androidx.annotation.AttrRes
import androidx.coordinatorlayout.widget.CoordinatorLayout import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import com.denizk0461.studip.R import com.denizk0461.weserplaner.R
import com.denizk0461.studip.exception.AcademicQuarterNotApplicableException import com.denizk0461.weserplaner.exception.AcademicQuarterNotApplicableException
import com.denizk0461.studip.exception.ParcelNotFoundException import com.denizk0461.weserplaner.exception.ParcelNotFoundException
import com.denizk0461.studip.sheet.TextSheet import com.denizk0461.weserplaner.sheet.TextSheet
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import kotlin.jvm.Throws import kotlin.jvm.Throws
@@ -1,4 +1,4 @@
package com.denizk0461.studip.data package com.denizk0461.weserplaner.data
import android.view.View import android.view.View
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
@@ -1,8 +1,8 @@
package com.denizk0461.studip.data package com.denizk0461.weserplaner.data
import android.app.Application import android.app.Application
import com.denizk0461.studip.db.AppRepository import com.denizk0461.weserplaner.db.AppRepository
import com.denizk0461.studip.model.StudIPEvent import com.denizk0461.weserplaner.model.StudIPEvent
import org.jsoup.Jsoup import org.jsoup.Jsoup
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
@@ -1,8 +1,8 @@
package com.denizk0461.studip.data package com.denizk0461.weserplaner.data
import android.app.Application import android.app.Application
import com.denizk0461.studip.db.AppRepository import com.denizk0461.weserplaner.db.AppRepository
import com.denizk0461.studip.model.* import com.denizk0461.weserplaner.model.*
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.jsoup.Jsoup import org.jsoup.Jsoup
@@ -139,7 +139,8 @@ class StwParser(application: Application) {
// Retrieve all opening hours. // Retrieve all opening hours.
it.children().forEach { element -> it.children().forEach { element ->
if (element.tag().toString() == "p") { if (element.tag().toString() == "p") {
openingHours += element.textWithBreaks().trim() + "\n" // Uni-Mensa is not parsed properly // Uni-Mensa is not parsed properly
openingHours += element.textWithBreaks().trim() + "\n"
} else { } else {
element.children().forEach { subElement -> element.children().forEach { subElement ->
openingHours += subElement.textWithBreaks() + '\n' openingHours += subElement.textWithBreaks() + '\n'
@@ -392,6 +393,14 @@ class StwParser(application: Application) {
else -> "00" // shouldn't occur else -> "00" // shouldn't occur
} }
/**
* Retrieve a given element T through a certain action, or else retrieve a safe object, if the
* action throws an exception.
*
* @param orElse return value if action throws
* @param action action to try to retrieve value T
* @return a value T without throwing an exception
*/
private fun <T> getOrElse(orElse: T, action: () -> T): T = try { private fun <T> getOrElse(orElse: T, action: () -> T): T = try {
action() action()
} catch (e: Exception) { } catch (e: Exception) {
@@ -1,8 +1,8 @@
package com.denizk0461.studip.db package com.denizk0461.weserplaner.db
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.room.* import androidx.room.*
import com.denizk0461.studip.model.* import com.denizk0461.weserplaner.model.*
/** /**
* Database access object used for all database transactions in the app. Can be accessed through an * Database access object used for all database transactions in the app. Can be accessed through an
@@ -1,10 +1,10 @@
package com.denizk0461.studip.db package com.denizk0461.weserplaner.db
import android.content.Context import android.content.Context
import androidx.room.Database import androidx.room.Database
import androidx.room.Room import androidx.room.Room
import androidx.room.RoomDatabase import androidx.room.RoomDatabase
import com.denizk0461.studip.model.* import com.denizk0461.weserplaner.model.*
/** /**
* Room database that holds all objects that need to be saved to persistent storage. * Room database that holds all objects that need to be saved to persistent storage.
@@ -1,10 +1,10 @@
package com.denizk0461.studip.db package com.denizk0461.weserplaner.db
import android.app.Application import android.app.Application
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import com.denizk0461.studip.model.* import com.denizk0461.weserplaner.model.*
/** /**
* Repository objects that acts as a mediator between view models and the database to retrieve data * Repository objects that acts as a mediator between view models and the database to retrieve data
@@ -1,4 +1,4 @@
package com.denizk0461.studip.exception package com.denizk0461.weserplaner.exception
import java.io.IOException import java.io.IOException
@@ -1,4 +1,4 @@
package com.denizk0461.studip.exception package com.denizk0461.weserplaner.exception
import java.io.IOException import java.io.IOException
@@ -1,8 +1,8 @@
package com.denizk0461.studip.fragment package com.denizk0461.weserplaner.fragment
import android.content.Context import android.content.Context
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import com.denizk0461.studip.sheet.AppSheet import com.denizk0461.weserplaner.sheet.AppSheet
/** /**
* Fragment super class providing common functionality. Fragments are used for providing the user * Fragment super class providing common functionality. Fragments are used for providing the user
@@ -24,7 +24,7 @@ open class AppFragment : Fragment() {
} }
/** /**
* Opens a bottom sheet. Sheet must be a subclass of [com.denizk0461.studip.sheet.AppSheet]. * Opens a bottom sheet. Sheet must be a subclass of [com.denizk0461.weserplaner.sheet.AppSheet].
* *
* @param sheet element that will be displayed * @param sheet element that will be displayed
*/ */
@@ -1,4 +1,4 @@
package com.denizk0461.studip.fragment package com.denizk0461.weserplaner.fragment
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
@@ -6,14 +6,14 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.appcompat.widget.PopupMenu import androidx.appcompat.widget.PopupMenu
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
import com.denizk0461.studip.R import com.denizk0461.weserplaner.R
import com.denizk0461.studip.adapter.CanteenOfferPageAdapter import com.denizk0461.weserplaner.adapter.CanteenOfferPageAdapter
import com.denizk0461.studip.data.getTextSheet import com.denizk0461.weserplaner.data.getTextSheet
import com.denizk0461.studip.data.setRainbowProgressCircle import com.denizk0461.weserplaner.data.setRainbowProgressCircle
import com.denizk0461.studip.data.showErrorSnackBar import com.denizk0461.weserplaner.data.showErrorSnackBar
import com.denizk0461.studip.databinding.FragmentCanteenBinding import com.denizk0461.weserplaner.databinding.FragmentCanteenBinding
import com.denizk0461.studip.model.* import com.denizk0461.weserplaner.model.*
import com.denizk0461.studip.viewmodel.CanteenViewModel import com.denizk0461.weserplaner.viewmodel.CanteenViewModel
import com.google.android.material.tabs.TabLayoutMediator import com.google.android.material.tabs.TabLayoutMediator
/** /**
@@ -61,17 +61,12 @@ class CanteenFragment : AppFragment() {
binding.swipeRefreshLayout.setRainbowProgressCircle() binding.swipeRefreshLayout.setRainbowProgressCircle()
// Set currently selected canteen to the button // Set currently selected canteen to the button
// binding.buttonCanteenPicker.text = getCurrentlySelectedCanteenName()
binding.appTitleBar.text = getString( binding.appTitleBar.text = getString(
R.string.title_canteen_template, R.string.title_canteen_template,
getCurrentlySelectedCanteenName(), getCurrentlySelectedCanteenName(),
) )
binding.appTitleBar.isSelected = true binding.appTitleBar.isSelected = true
// Set up button to display info (most likely opening hours)
// binding.buttonInfo.setOnClickListener {
//
// }
// Assign a preference value to every button to filter for dietary preferences // Assign a preference value to every button to filter for dietary preferences
val chipMap = mapOf( val chipMap = mapOf(
@@ -262,10 +257,20 @@ class CanteenFragment : AppFragment() {
getString(R.string.canteen_fetch_error) getString(R.string.canteen_fetch_error)
) )
/* /*
* Tell the swipe refresh layout to stop refreshing. * Tell the swipe refresh layout to stop refreshing.
*/ */
binding.swipeRefreshLayout.isRefreshing = false binding.swipeRefreshLayout.isRefreshing = false
} }
}) })
} }
override fun onPause() {
if (_binding != null) {
/*
* Stop the refreshing animation if the user switches fragments.
*/
binding.swipeRefreshLayout.isRefreshing = false
}
super.onPause()
}
} }
@@ -1,4 +1,4 @@
package com.denizk0461.studip.fragment package com.denizk0461.weserplaner.fragment
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
@@ -6,15 +6,15 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import com.denizk0461.studip.adapter.CanteenOfferItemAdapter import com.denizk0461.weserplaner.adapter.CanteenOfferItemAdapter
import com.denizk0461.studip.adapter.StudIPEventPageAdapter import com.denizk0461.weserplaner.adapter.StudIPEventPageAdapter
import com.denizk0461.studip.databinding.RecyclerViewBinding import com.denizk0461.weserplaner.databinding.RecyclerViewBinding
import com.denizk0461.studip.model.CanteenOffer import com.denizk0461.weserplaner.model.CanteenOffer
import com.denizk0461.studip.model.CanteenOfferGroup import com.denizk0461.weserplaner.model.CanteenOfferGroup
import com.denizk0461.studip.model.CanteenOfferGroupElement import com.denizk0461.weserplaner.model.CanteenOfferGroupElement
import com.denizk0461.studip.model.DietaryPreferences import com.denizk0461.weserplaner.model.DietaryPreferences
import com.denizk0461.studip.sheet.AllergenSheet import com.denizk0461.weserplaner.sheet.AllergenSheet
import com.denizk0461.studip.viewmodel.CanteenPageViewModel import com.denizk0461.weserplaner.viewmodel.CanteenPageViewModel
/** /**
* Fragment that is instantiated by [StudIPEventPageAdapter] to display individual days' pages and * Fragment that is instantiated by [StudIPEventPageAdapter] to display individual days' pages and
@@ -46,7 +46,11 @@ class CanteenPageFragment : AppFragment(), CanteenOfferItemAdapter.OnClickListen
private var currentDay: Int = -1 private var currentDay: Int = -1
// Instantiate the view binding // Instantiate the view binding
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?,
): View {
// Retrieve current day to fetch items specifically for that day // Retrieve current day to fetch items specifically for that day
currentDay = arguments?.getInt("currentDay") ?: -1 currentDay = arguments?.getInt("currentDay") ?: -1
@@ -1,15 +1,15 @@
package com.denizk0461.studip.fragment package com.denizk0461.weserplaner.fragment
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 androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
import com.denizk0461.studip.R import com.denizk0461.weserplaner.R
import com.denizk0461.studip.adapter.StudIPEventPageAdapter import com.denizk0461.weserplaner.adapter.StudIPEventPageAdapter
import com.denizk0461.studip.databinding.FragmentEventBinding import com.denizk0461.weserplaner.databinding.FragmentEventBinding
import com.denizk0461.studip.sheet.ScheduleUpdateSheet import com.denizk0461.weserplaner.sheet.ScheduleUpdateSheet
import com.denizk0461.studip.viewmodel.EventViewModel import com.denizk0461.weserplaner.viewmodel.EventViewModel
import com.google.android.material.tabs.TabLayoutMediator import com.google.android.material.tabs.TabLayoutMediator
import java.util.* import java.util.*
@@ -1,4 +1,4 @@
package com.denizk0461.studip.fragment package com.denizk0461.weserplaner.fragment
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
@@ -6,12 +6,12 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import com.denizk0461.studip.adapter.StudIPEventPageAdapter import com.denizk0461.weserplaner.adapter.StudIPEventPageAdapter
import com.denizk0461.studip.adapter.StudIPEventItemAdapter import com.denizk0461.weserplaner.adapter.StudIPEventItemAdapter
import com.denizk0461.studip.databinding.RecyclerViewBinding import com.denizk0461.weserplaner.databinding.RecyclerViewBinding
import com.denizk0461.studip.model.StudIPEvent import com.denizk0461.weserplaner.model.StudIPEvent
import com.denizk0461.studip.sheet.ScheduleUpdateSheet import com.denizk0461.weserplaner.sheet.ScheduleUpdateSheet
import com.denizk0461.studip.viewmodel.EventPageViewModel import com.denizk0461.weserplaner.viewmodel.EventPageViewModel
/** /**
* Fragment that is instantiated by [StudIPEventPageAdapter] to display individual days' pages and * Fragment that is instantiated by [StudIPEventPageAdapter] to display individual days' pages and
@@ -1,4 +1,4 @@
package com.denizk0461.studip.fragment package com.denizk0461.weserplaner.fragment
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Intent import android.content.Intent
@@ -8,16 +8,16 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
import com.denizk0461.studip.BuildConfig import com.denizk0461.weserplaner.BuildConfig
import com.denizk0461.studip.R import com.denizk0461.weserplaner.R
import com.denizk0461.studip.activity.FetcherActivity import com.denizk0461.weserplaner.activity.FetcherActivity
import com.denizk0461.studip.activity.ImageActivity import com.denizk0461.weserplaner.activity.ImageActivity
import com.denizk0461.studip.data.getTextSheet import com.denizk0461.weserplaner.data.getTextSheet
import com.denizk0461.studip.data.showToast import com.denizk0461.weserplaner.data.showToast
import com.denizk0461.studip.databinding.FragmentSettingsBinding import com.denizk0461.weserplaner.databinding.FragmentSettingsBinding
import com.denizk0461.studip.sheet.AllergenConfigSheet import com.denizk0461.weserplaner.sheet.AllergenConfigSheet
import com.denizk0461.studip.sheet.DevCodeSheet import com.denizk0461.weserplaner.sheet.DevCodeSheet
import com.denizk0461.studip.viewmodel.SettingsViewModel import com.denizk0461.weserplaner.viewmodel.SettingsViewModel
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.* import java.util.*
@@ -38,6 +38,9 @@ class SettingsFragment : AppFragment() {
// View model reference for providing access to the database // View model reference for providing access to the database
private val viewModel: SettingsViewModel by viewModels() private val viewModel: SettingsViewModel by viewModels()
// How many long clicks the user has done on the licences button
private var licencesLongClick = 1
// Click counter on the app version button // Click counter on the app version button
private var appVersionClick = 1 private var appVersionClick = 1
@@ -135,7 +138,12 @@ class SettingsFragment : AppFragment() {
// Set long click listener for licences button to open dev code sheet // Set long click listener for licences button to open dev code sheet
binding.buttonLicences.setOnLongClickListener { binding.buttonLicences.setOnLongClickListener {
openBottomSheet(DevCodeSheet()) if (licencesLongClick > 3) {
openBottomSheet(DevCodeSheet())
licencesLongClick = 1
} else {
licencesLongClick += 1
}
true true
} }
@@ -148,18 +156,18 @@ class SettingsFragment : AppFragment() {
// Set click listener for the app version button // Set click listener for the app version button
binding.buttonAppVersion.setOnClickListener { binding.buttonAppVersion.setOnClickListener {
when (appVersionClick) { when (appVersionClick) {
3 -> { 4 -> {
startActivity(Intent(context, ImageActivity::class.java).also { intent -> startActivity(Intent(context, ImageActivity::class.java).also { intent ->
val bundle = Bundle() val bundle = Bundle()
bundle.putString("img", "garbage") bundle.putString("img", "garbage")
intent.putExtras(bundle) intent.putExtras(bundle)
}) })
} }
15 -> showToast(context, getString(R.string.settings_app_version_15)) 20 -> showToast(context, getString(R.string.settings_app_version_15))
20 -> showToast(context, getString(R.string.settings_app_version_20)) 35 -> showToast(context, getString(R.string.settings_app_version_20))
30 -> showToast(context, getString(R.string.settings_app_version_30)) 50 -> showToast(context, getString(R.string.settings_app_version_30))
90 -> showToast(context, getString(R.string.settings_app_version_90)) 90 -> showToast(context, getString(R.string.settings_app_version_90))
121 -> showToast(context, getString(R.string.settings_app_version_121)) // 121 -> showToast(context, getString(R.string.settings_app_version_121))
165 -> showToast(context, getString(R.string.settings_app_version_165)) 165 -> showToast(context, getString(R.string.settings_app_version_165))
200 -> showToast(context, getString(R.string.settings_app_version_200)) 200 -> showToast(context, getString(R.string.settings_app_version_200))
222 -> { 222 -> {
@@ -1,4 +1,4 @@
package com.denizk0461.studip.model package com.denizk0461.weserplaner.model
/** /**
* Class for managing allergen preferences. The user can tell the app which substances they are * Class for managing allergen preferences. The user can tell the app which substances they are
@@ -1,6 +1,6 @@
package com.denizk0461.studip.model package com.denizk0461.weserplaner.model
import com.denizk0461.studip.R import com.denizk0461.weserplaner.R
/** /**
* This class provides static functions for dealing with allergens present in a canteen offer. * This class provides static functions for dealing with allergens present in a canteen offer.
@@ -1,4 +1,4 @@
package com.denizk0461.studip.model package com.denizk0461.weserplaner.model
import androidx.room.ColumnInfo import androidx.room.ColumnInfo
@@ -1,4 +1,4 @@
package com.denizk0461.studip.model package com.denizk0461.weserplaner.model
/** /**
* Grouping element that holds instances of CanteenOfferGroupElement.kt that share date, category, * Grouping element that holds instances of CanteenOfferGroupElement.kt that share date, category,
@@ -1,4 +1,4 @@
package com.denizk0461.studip.model package com.denizk0461.weserplaner.model
import android.os.Parcel import android.os.Parcel
import android.os.Parcelable import android.os.Parcelable
@@ -1,6 +1,6 @@
package com.denizk0461.studip.model package com.denizk0461.weserplaner.model
import com.denizk0461.studip.R import com.denizk0461.weserplaner.R
/** /**
* Enumeration for more concisely looking up, specifying, and iterating through dietary preferences. * Enumeration for more concisely looking up, specifying, and iterating through dietary preferences.
@@ -1,4 +1,4 @@
package com.denizk0461.studip.model package com.denizk0461.weserplaner.model
import androidx.room.Entity import androidx.room.Entity
import androidx.room.PrimaryKey import androidx.room.PrimaryKey
@@ -1,4 +1,4 @@
package com.denizk0461.studip.model package com.denizk0461.weserplaner.model
import androidx.room.Entity import androidx.room.Entity
import androidx.room.ForeignKey import androidx.room.ForeignKey
@@ -1,4 +1,4 @@
package com.denizk0461.studip.model package com.denizk0461.weserplaner.model
import androidx.room.Entity import androidx.room.Entity
import androidx.room.PrimaryKey import androidx.room.PrimaryKey
@@ -1,4 +1,4 @@
package com.denizk0461.studip.model package com.denizk0461.weserplaner.model
import androidx.room.ColumnInfo import androidx.room.ColumnInfo
import androidx.room.Entity import androidx.room.Entity
@@ -1,4 +1,4 @@
package com.denizk0461.studip.model package com.denizk0461.weserplaner.model
/** /**
* Enumeration class for user-set preferences that will be saved in persistent storage via * Enumeration class for user-set preferences that will be saved in persistent storage via
@@ -1,6 +1,6 @@
package com.denizk0461.studip.model package com.denizk0461.weserplaner.model
import com.denizk0461.studip.R import com.denizk0461.weserplaner.R
/** /**
* Enumeration used to save and apply custom colours to Stud.IP events. * Enumeration used to save and apply custom colours to Stud.IP events.
@@ -1,4 +1,4 @@
package com.denizk0461.studip.model package com.denizk0461.weserplaner.model
import android.os.Parcel import android.os.Parcel
import android.os.Parcelable import android.os.Parcelable
@@ -1,14 +1,14 @@
package com.denizk0461.studip.sheet package com.denizk0461.weserplaner.sheet
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
import com.denizk0461.studip.R import com.denizk0461.weserplaner.R
import com.denizk0461.studip.data.showToast import com.denizk0461.weserplaner.data.showToast
import com.denizk0461.studip.data.viewBinding import com.denizk0461.weserplaner.data.viewBinding
import com.denizk0461.studip.databinding.SheetAllergenConfigBinding import com.denizk0461.weserplaner.databinding.SheetAllergenConfigBinding
import com.denizk0461.studip.model.AllergenPreferences import com.denizk0461.weserplaner.model.AllergenPreferences
import com.denizk0461.studip.viewmodel.AllergenConfigViewModel import com.denizk0461.weserplaner.viewmodel.AllergenConfigViewModel
/** /**
* Configuration sheet for the user to pick substances they are allergic against. Offers containing * Configuration sheet for the user to pick substances they are allergic against. Offers containing
@@ -1,21 +1,21 @@
package com.denizk0461.studip.sheet package com.denizk0461.weserplaner.sheet
import android.content.res.ColorStateList import android.content.res.ColorStateList
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 androidx.appcompat.content.res.AppCompatResources.getDrawable import androidx.appcompat.content.res.AppCompatResources.getDrawable
import com.denizk0461.studip.R import com.denizk0461.weserplaner.R
import com.denizk0461.studip.data.getParcelableCompat import com.denizk0461.weserplaner.data.getParcelableCompat
import com.denizk0461.studip.data.getThemedColor import com.denizk0461.weserplaner.data.getThemedColor
import com.denizk0461.studip.data.showToast import com.denizk0461.weserplaner.data.showToast
import com.denizk0461.studip.data.viewBinding import com.denizk0461.weserplaner.data.viewBinding
import com.denizk0461.studip.databinding.ItemSheetPreferenceBinding import com.denizk0461.weserplaner.databinding.ItemSheetPreferenceBinding
import com.denizk0461.studip.databinding.SheetAllergenBinding import com.denizk0461.weserplaner.databinding.SheetAllergenBinding
import com.denizk0461.studip.exception.ParcelNotFoundException import com.denizk0461.weserplaner.exception.ParcelNotFoundException
import com.denizk0461.studip.model.Allergens import com.denizk0461.weserplaner.model.Allergens
import com.denizk0461.studip.model.CanteenOfferGroupElement import com.denizk0461.weserplaner.model.CanteenOfferGroupElement
import com.denizk0461.studip.model.DietaryPreferences import com.denizk0461.weserplaner.model.DietaryPreferences
/** /**
* This class is used to display further information on a canteen offer to the user. Unlike the name * This class is used to display further information on a canteen offer to the user. Unlike the name
@@ -1,4 +1,4 @@
package com.denizk0461.studip.sheet package com.denizk0461.weserplaner.sheet
import android.content.Context import android.content.Context
import android.os.Bundle import android.os.Bundle
@@ -1,4 +1,4 @@
package com.denizk0461.studip.sheet package com.denizk0461.weserplaner.sheet
import android.content.Intent import android.content.Intent
import android.net.Uri import android.net.Uri
@@ -6,12 +6,12 @@ import android.os.Bundle
import android.util.Base64 import android.util.Base64
import android.view.View import android.view.View
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
import com.denizk0461.studip.R import com.denizk0461.weserplaner.R
import com.denizk0461.studip.activity.ImageActivity import com.denizk0461.weserplaner.activity.ImageActivity
import com.denizk0461.studip.data.showToast import com.denizk0461.weserplaner.data.showToast
import com.denizk0461.studip.data.viewBinding import com.denizk0461.weserplaner.data.viewBinding
import com.denizk0461.studip.databinding.SheetDevCodeBinding import com.denizk0461.weserplaner.databinding.SheetDevCodeBinding
import com.denizk0461.studip.viewmodel.DevCodeViewModel import com.denizk0461.weserplaner.viewmodel.DevCodeViewModel
import java.nio.charset.StandardCharsets import java.nio.charset.StandardCharsets
/** /**
@@ -58,6 +58,8 @@ class DevCodeSheet : AppSheet(R.layout.sheet_dev_code) {
"Q0FMTE1F".d64 -> launchLink("aHR0cHM6Ly95b3V0dS5iZS8xbTV1WnJNMnktMA==".d64) "Q0FMTE1F".d64 -> launchLink("aHR0cHM6Ly95b3V0dS5iZS8xbTV1WnJNMnktMA==".d64)
"SkFNSVJP".d64 -> launchLink("aHR0cHM6Ly95b3V0dS5iZS9fMVZoT2c0N3ozNA==".d64) "SkFNSVJP".d64 -> launchLink("aHR0cHM6Ly95b3V0dS5iZS9fMVZoT2c0N3ozNA==".d64)
"TE9ORUxZ".d64 -> launchLink("aHR0cHM6Ly95b3V0dS5iZS9uLURFNHNfc3d5Zw==".d64) "TE9ORUxZ".d64 -> launchLink("aHR0cHM6Ly95b3V0dS5iZS9uLURFNHNfc3d5Zw==".d64)
"QkVBVVRZ".d64 -> launchLink("aHR0cHM6Ly95b3V0dS5iZS9vbVQ1ckttVTVfaw==".d64)
"Uk9NQ09N".d64 -> launchLink("aHR0cHM6Ly95b3V0dS5iZS9HUW1nUG5uZjE4WQ==".d64)
"Qk9KQUNL".d64 -> { "Qk9KQUNL".d64 -> {
startActivity(Intent(context, ImageActivity::class.java).also { intent -> startActivity(Intent(context, ImageActivity::class.java).also { intent ->
val bundle = Bundle() val bundle = Bundle()
@@ -1,4 +1,4 @@
package com.denizk0461.studip.sheet package com.denizk0461.weserplaner.sheet
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
@@ -7,19 +7,19 @@ import androidx.appcompat.widget.PopupMenu
import androidx.core.widget.addTextChangedListener import androidx.core.widget.addTextChangedListener
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
import androidx.transition.TransitionManager import androidx.transition.TransitionManager
import com.denizk0461.studip.R import com.denizk0461.weserplaner.R
import com.denizk0461.studip.data.getParcelableCompat import com.denizk0461.weserplaner.data.getParcelableCompat
import com.denizk0461.studip.data.getTimestampAcademicQuarterEnd import com.denizk0461.weserplaner.data.getTimestampAcademicQuarterEnd
import com.denizk0461.studip.data.getTimestampAcademicQuarterStart import com.denizk0461.weserplaner.data.getTimestampAcademicQuarterStart
import com.denizk0461.studip.data.parseToMinutes import com.denizk0461.weserplaner.data.parseToMinutes
import com.denizk0461.studip.data.showToast import com.denizk0461.weserplaner.data.showToast
import com.denizk0461.studip.data.timeslotsForAcademicQuarter import com.denizk0461.weserplaner.data.timeslotsForAcademicQuarter
import com.denizk0461.studip.data.viewBinding import com.denizk0461.weserplaner.data.viewBinding
import com.denizk0461.studip.databinding.SheetScheduleUpdateBinding import com.denizk0461.weserplaner.databinding.SheetScheduleUpdateBinding
import com.denizk0461.studip.exception.AcademicQuarterNotApplicableException import com.denizk0461.weserplaner.exception.AcademicQuarterNotApplicableException
import com.denizk0461.studip.exception.ParcelNotFoundException import com.denizk0461.weserplaner.exception.ParcelNotFoundException
import com.denizk0461.studip.model.StudIPEvent import com.denizk0461.weserplaner.model.StudIPEvent
import com.denizk0461.studip.viewmodel.ScheduleUpdateViewModel import com.denizk0461.weserplaner.viewmodel.ScheduleUpdateViewModel
import com.google.android.material.timepicker.MaterialTimePicker import com.google.android.material.timepicker.MaterialTimePicker
import com.google.android.material.timepicker.TimeFormat import com.google.android.material.timepicker.TimeFormat
@@ -100,27 +100,41 @@ class ScheduleUpdateSheet : AppSheet(R.layout.sheet_schedule_update) {
} }
} }
// Prepare update/save button // Prepare update button
binding.buttonSave.setOnClickListener { binding.buttonSave.setOnClickListener {
// Check if any of the text fields are empty // Check if any of the text fields are empty
checkIfTextFieldsEmpty { checkIfTextFieldsEmpty {
// Update the event if all fields are filled // Check the time stamps. If start > end, show an error
viewModel.update( if (timeslotStart.parseToMinutes() > timeslotEnd.parseToMinutes()) {
// construct new StudIPEvent from the data the user may have edited showToast(
StudIPEvent( context,
eventId = event.eventId, getString(R.string.sheet_schedule_update_timestamp_error_mixed),
title = binding.editTextTitle.text.toString().trim(),
lecturer = binding.editTextLecturers.text.toString().trim(),
room = binding.editTextRoom.text.toString().trim(),
day = selectedDay,
timeslotStart = timeslotStart,
timeslotEnd = timeslotEnd,
timeslotId = timeslotStart.parseToMinutes(),
colour = colour,
) )
) // If the time stamps are equal, show an error
// Dismiss the sheet upon update } else if (timeslotEnd.parseToMinutes() == timeslotStart.parseToMinutes()) {
dismiss() showToast(
context,
getString(R.string.sheet_schedule_update_timestamp_error_equal),
)
} else {
// Update the event if all fields are filled
viewModel.update(
// construct new StudIPEvent from the data the user may have edited
StudIPEvent(
eventId = event.eventId,
title = binding.editTextTitle.text.toString().trim(),
lecturer = binding.editTextLecturers.text.toString().trim(),
room = binding.editTextRoom.text.toString().trim(),
day = selectedDay,
timeslotStart = timeslotStart,
timeslotEnd = timeslotEnd,
timeslotId = timeslotStart.parseToMinutes(),
colour = colour,
)
)
// Dismiss the sheet upon update
dismiss()
}
} }
} }
@@ -141,26 +155,40 @@ class ScheduleUpdateSheet : AppSheet(R.layout.sheet_schedule_update) {
// Hide delete button, since there is nothing to delete // Hide delete button, since there is nothing to delete
binding.buttonDelete.visibility = View.GONE binding.buttonDelete.visibility = View.GONE
// Prepare update/save button // Prepare save button
binding.buttonSave.setOnClickListener { binding.buttonSave.setOnClickListener {
// Check if any of the text fields are empty // Check if any of the text fields are empty
checkIfTextFieldsEmpty { checkIfTextFieldsEmpty {
// Insert new event into the database // Check the time stamps. If start > end, show an error
viewModel.insert( if (timeslotStart.parseToMinutes() > timeslotEnd.parseToMinutes()) {
// construct new StudIPEvent from the data the user may have edited showToast(
StudIPEvent( context,
title = binding.editTextTitle.text.toString().trim(), getString(R.string.sheet_schedule_update_timestamp_error_mixed),
lecturer = binding.editTextLecturers.text.toString().trim(),
room = binding.editTextRoom.text.toString().trim(),
day = selectedDay,
timeslotStart = timeslotStart,
timeslotEnd = timeslotEnd,
timeslotId = timeslotStart.parseToMinutes(),
colour = colour,
) )
) // If the time stamps are equal, show an error
// Dismiss the sheet upon update } else if (timeslotEnd.parseToMinutes() == timeslotStart.parseToMinutes()) {
dismiss() showToast(
context,
getString(R.string.sheet_schedule_update_timestamp_error_equal),
)
} else {
// Insert new event into the database
viewModel.insert(
// construct new StudIPEvent from the data the user may have edited
StudIPEvent(
title = binding.editTextTitle.text.toString().trim(),
lecturer = binding.editTextLecturers.text.toString().trim(),
room = binding.editTextRoom.text.toString().trim(),
day = selectedDay,
timeslotStart = timeslotStart,
timeslotEnd = timeslotEnd,
timeslotId = timeslotStart.parseToMinutes(),
colour = colour,
)
)
// Dismiss the sheet upon update
dismiss()
}
} }
} }
} }
@@ -310,29 +338,21 @@ class ScheduleUpdateSheet : AppSheet(R.layout.sheet_schedule_update) {
// Parse the separate ints into a timestamp string. Add a leading zero if necessary. // Parse the separate ints into a timestamp string. Add a leading zero if necessary.
val newTimestamp = "$hours:${String.format("%02d", minutes)}" val newTimestamp = "$hours:${String.format("%02d", minutes)}"
if (isEventStart && newTimestamp.parseToMinutes() > timeslotEnd.parseToMinutes()) { // If the new timestamp is valid, save it
// If editing start and start > end, show an error if (isEventStart) {
showToast(context, getString(R.string.sheet_schedule_update_timestamp_error_start)) timeslotStart = newTimestamp
// If editing end and end < start, show an error binding.buttonTimeStart.text = newTimestamp
} else if (!isEventStart && newTimestamp.parseToMinutes() < timeslotStart.parseToMinutes()) {
showToast(context, getString(R.string.sheet_schedule_update_timestamp_error_end))
} else { } else {
// If the new timestamp is valid, save it timeslotEnd = newTimestamp
if (isEventStart) { binding.buttonTimeEnd.text = newTimestamp
timeslotStart = newTimestamp
binding.buttonTimeStart.text = newTimestamp
} else {
timeslotEnd = newTimestamp
binding.buttonTimeEnd.text = newTimestamp
}
// Set appropriate visibility to the academic quarter button
TransitionManager.beginDelayedTransition(binding.sheet.parent as ViewGroup)
binding.buttonAcademicQuarter.visibility = getVisibilityForAcademicQuarter(
timeslotsForAcademicQuarter.contains(timeslotStart),
timeslotsForAcademicQuarter.contains(timeslotEnd),
)
} }
// Set appropriate visibility to the academic quarter button
TransitionManager.beginDelayedTransition(binding.sheet.parent as ViewGroup)
binding.buttonAcademicQuarter.visibility = getVisibilityForAcademicQuarter(
timeslotsForAcademicQuarter.contains(timeslotStart),
timeslotsForAcademicQuarter.contains(timeslotEnd),
)
} }
/** /**
@@ -346,6 +366,9 @@ class ScheduleUpdateSheet : AppSheet(R.layout.sheet_schedule_update) {
// Assume at the start that no fields are empty; this may be changed during the checks // Assume at the start that no fields are empty; this may be changed during the checks
var hasEmptyFields = false var hasEmptyFields = false
// Prepare animation if errors will be posted to the text fields
TransitionManager.beginDelayedTransition(binding.sheet.parent as ViewGroup)
// Check if the title field is blank // Check if the title field is blank
if (binding.editTextTitle.text.toString().isBlank()) { if (binding.editTextTitle.text.toString().isBlank()) {
// Set an error on the title field // Set an error on the title field
@@ -1,10 +1,10 @@
package com.denizk0461.studip.sheet package com.denizk0461.weserplaner.sheet
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import com.denizk0461.studip.R import com.denizk0461.weserplaner.R
import com.denizk0461.studip.data.viewBinding import com.denizk0461.weserplaner.data.viewBinding
import com.denizk0461.studip.databinding.SheetTextBinding import com.denizk0461.weserplaner.databinding.SheetTextBinding
/** /**
* Bottom sheet used for displaying any sort of text to the user. * Bottom sheet used for displaying any sort of text to the user.
@@ -1,8 +1,8 @@
package com.denizk0461.studip.viewmodel package com.denizk0461.weserplaner.viewmodel
import android.app.Application import android.app.Application
import com.denizk0461.studip.model.AllergenPreferences import com.denizk0461.weserplaner.model.AllergenPreferences
import com.denizk0461.studip.model.SettingsPreferences import com.denizk0461.weserplaner.model.SettingsPreferences
class AllergenConfigViewModel(application: Application) : AppViewModel(application) { class AllergenConfigViewModel(application: Application) : AppViewModel(application) {
@@ -1,9 +1,9 @@
package com.denizk0461.studip.viewmodel package com.denizk0461.weserplaner.viewmodel
import android.app.Application import android.app.Application
import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.denizk0461.studip.db.AppRepository import com.denizk0461.weserplaner.db.AppRepository
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
@@ -1,11 +1,11 @@
package com.denizk0461.studip.viewmodel package com.denizk0461.weserplaner.viewmodel
import android.app.Application import android.app.Application
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import com.denizk0461.studip.model.AllergenPreferences import com.denizk0461.weserplaner.model.AllergenPreferences
import com.denizk0461.studip.model.CanteenOffer import com.denizk0461.weserplaner.model.CanteenOffer
import com.denizk0461.studip.model.DietaryPreferences import com.denizk0461.weserplaner.model.DietaryPreferences
import com.denizk0461.studip.model.SettingsPreferences import com.denizk0461.weserplaner.model.SettingsPreferences
class CanteenPageViewModel(app: Application) : AppViewModel(app) { class CanteenPageViewModel(app: Application) : AppViewModel(app) {
@@ -1,15 +1,15 @@
package com.denizk0461.studip.viewmodel package com.denizk0461.weserplaner.viewmodel
import android.app.Application import android.app.Application
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.denizk0461.studip.data.StwParser import com.denizk0461.weserplaner.data.StwParser
import com.denizk0461.studip.model.* import com.denizk0461.weserplaner.model.*
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
/** /**
* View model for [com.denizk0461.studip.fragment.CanteenFragment] * View model for [com.denizk0461.weserplaner.fragment.CanteenFragment]
* *
* @param app reference to the app * @param app reference to the app
*/ */
@@ -1,4 +1,4 @@
package com.denizk0461.studip.viewmodel package com.denizk0461.weserplaner.viewmodel
import android.app.Application import android.app.Application
@@ -1,12 +1,12 @@
package com.denizk0461.studip.viewmodel package com.denizk0461.weserplaner.viewmodel
import android.app.Application import android.app.Application
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import com.denizk0461.studip.model.SettingsPreferences import com.denizk0461.weserplaner.model.SettingsPreferences
import com.denizk0461.studip.model.StudIPEvent import com.denizk0461.weserplaner.model.StudIPEvent
/** /**
* View model for [com.denizk0461.studip.fragment.EventPageFragment] * View model for [com.denizk0461.weserplaner.fragment.EventPageFragment]
* *
* @param app reference to the app * @param app reference to the app
*/ */
@@ -1,10 +1,10 @@
package com.denizk0461.studip.viewmodel package com.denizk0461.weserplaner.viewmodel
import android.app.Application import android.app.Application
import com.denizk0461.studip.model.SettingsPreferences import com.denizk0461.weserplaner.model.SettingsPreferences
/** /**
* View model for [com.denizk0461.studip.fragment.EventFragment] * View model for [com.denizk0461.weserplaner.fragment.EventFragment]
* *
* @param app reference to the app * @param app reference to the app
*/ */
@@ -1,12 +1,12 @@
package com.denizk0461.studip.viewmodel package com.denizk0461.weserplaner.viewmodel
import android.app.Application import android.app.Application
import com.denizk0461.studip.data.StudIPParser import com.denizk0461.weserplaner.data.StudIPParser
import java.io.IOException import java.io.IOException
import kotlin.jvm.Throws import kotlin.jvm.Throws
/** /**
* View model for [com.denizk0461.studip.activity.FetcherActivity] * View model for [com.denizk0461.weserplaner.activity.FetcherActivity]
* *
* @param app reference to the app * @param app reference to the app
*/ */
@@ -1,10 +1,10 @@
package com.denizk0461.studip.viewmodel package com.denizk0461.weserplaner.viewmodel
import android.app.Application import android.app.Application
import com.denizk0461.studip.model.SettingsPreferences import com.denizk0461.weserplaner.model.SettingsPreferences
/** /**
* View model for [com.denizk0461.studip.activity.MainActivity] * View model for [com.denizk0461.weserplaner.activity.MainActivity]
* *
* @param application reference to the app * @param application reference to the app
*/ */
@@ -1,7 +1,7 @@
package com.denizk0461.studip.viewmodel package com.denizk0461.weserplaner.viewmodel
import android.app.Application import android.app.Application
import com.denizk0461.studip.model.StudIPEvent import com.denizk0461.weserplaner.model.StudIPEvent
class ScheduleUpdateViewModel(application: Application) : AppViewModel(application) { class ScheduleUpdateViewModel(application: Application) : AppViewModel(application) {
@@ -1,10 +1,10 @@
package com.denizk0461.studip.viewmodel package com.denizk0461.weserplaner.viewmodel
import android.app.Application import android.app.Application
import com.denizk0461.studip.model.SettingsPreferences import com.denizk0461.weserplaner.model.SettingsPreferences
/** /**
* View model for [com.denizk0461.studip.fragment.SettingsFragment] * View model for [com.denizk0461.weserplaner.fragment.SettingsFragment]
* *
* @param app reference to the app * @param app reference to the app
*/ */
@@ -16,6 +16,7 @@ class SettingsViewModel(app: Application) : AppViewModel(app) {
var preferenceCurrentDay: Boolean var preferenceCurrentDay: Boolean
get() = repo.getBooleanPreference( get() = repo.getBooleanPreference(
SettingsPreferences.CURRENT_DAY, SettingsPreferences.CURRENT_DAY,
defaultValue = true,
) )
set(newValue) { repo.setPreference(SettingsPreferences.CURRENT_DAY, newValue) } set(newValue) { repo.setPreference(SettingsPreferences.CURRENT_DAY, newValue) }
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@android:color/transparent" android:state_checked="true"/>
<item android:color="?attr/colorOutlineVariant"/>
</selector>
@@ -58,6 +58,7 @@
android:textColor="@color/list_chip_fair_text" android:textColor="@color/list_chip_fair_text"
app:chipIconTint="@color/list_chip_fair_text" app:chipIconTint="@color/list_chip_fair_text"
app:chipBackgroundColor="@color/list_chip_fair_bg" app:chipBackgroundColor="@color/list_chip_fair_bg"
app:chipStrokeColor="@color/list_chip_stroke"
android:text="@string/pref_fair"/> android:text="@string/pref_fair"/>
<com.google.android.material.chip.Chip <com.google.android.material.chip.Chip
@@ -70,6 +71,7 @@
android:textColor="@color/list_chip_fish_text" android:textColor="@color/list_chip_fish_text"
app:chipIconTint="@color/list_chip_fish_text" app:chipIconTint="@color/list_chip_fish_text"
app:chipBackgroundColor="@color/list_chip_fish_bg" app:chipBackgroundColor="@color/list_chip_fish_bg"
app:chipStrokeColor="@color/list_chip_stroke"
android:text="@string/pref_fish"/> android:text="@string/pref_fish"/>
<com.google.android.material.chip.Chip <com.google.android.material.chip.Chip
@@ -82,6 +84,7 @@
android:textColor="@color/list_chip_poultry_text" android:textColor="@color/list_chip_poultry_text"
app:chipIconTint="@color/list_chip_poultry_text" app:chipIconTint="@color/list_chip_poultry_text"
app:chipBackgroundColor="@color/list_chip_poultry_bg" app:chipBackgroundColor="@color/list_chip_poultry_bg"
app:chipStrokeColor="@color/list_chip_stroke"
android:text="@string/pref_poultry"/> android:text="@string/pref_poultry"/>
<com.google.android.material.chip.Chip <com.google.android.material.chip.Chip
@@ -94,6 +97,7 @@
android:textColor="@color/list_chip_lamb_text" android:textColor="@color/list_chip_lamb_text"
app:chipIconTint="@color/list_chip_lamb_text" app:chipIconTint="@color/list_chip_lamb_text"
app:chipBackgroundColor="@color/list_chip_lamb_bg" app:chipBackgroundColor="@color/list_chip_lamb_bg"
app:chipStrokeColor="@color/list_chip_stroke"
android:text="@string/pref_lamb"/> android:text="@string/pref_lamb"/>
<com.google.android.material.chip.Chip <com.google.android.material.chip.Chip
@@ -106,6 +110,7 @@
android:textColor="@color/list_chip_vital_text" android:textColor="@color/list_chip_vital_text"
app:chipIconTint="@color/list_chip_vital_text" app:chipIconTint="@color/list_chip_vital_text"
app:chipBackgroundColor="@color/list_chip_vital_bg" app:chipBackgroundColor="@color/list_chip_vital_bg"
app:chipStrokeColor="@color/list_chip_stroke"
android:text="@string/pref_vital"/> android:text="@string/pref_vital"/>
<com.google.android.material.chip.Chip <com.google.android.material.chip.Chip
@@ -118,6 +123,7 @@
android:textColor="@color/list_chip_beef_text" android:textColor="@color/list_chip_beef_text"
app:chipIconTint="@color/list_chip_beef_text" app:chipIconTint="@color/list_chip_beef_text"
app:chipBackgroundColor="@color/list_chip_beef_bg" app:chipBackgroundColor="@color/list_chip_beef_bg"
app:chipStrokeColor="@color/list_chip_stroke"
android:text="@string/pref_beef"/> android:text="@string/pref_beef"/>
<com.google.android.material.chip.Chip <com.google.android.material.chip.Chip
@@ -130,6 +136,7 @@
android:textColor="@color/list_chip_pork_text" android:textColor="@color/list_chip_pork_text"
app:chipIconTint="@color/list_chip_pork_text" app:chipIconTint="@color/list_chip_pork_text"
app:chipBackgroundColor="@color/list_chip_pork_bg" app:chipBackgroundColor="@color/list_chip_pork_bg"
app:chipStrokeColor="@color/list_chip_stroke"
android:text="@string/pref_pork"/> android:text="@string/pref_pork"/>
<com.google.android.material.chip.Chip <com.google.android.material.chip.Chip
@@ -142,6 +149,7 @@
android:textColor="@color/list_chip_vegetarian_text" android:textColor="@color/list_chip_vegetarian_text"
app:chipIconTint="@color/list_chip_vegetarian_text" app:chipIconTint="@color/list_chip_vegetarian_text"
app:chipBackgroundColor="@color/list_chip_vegetarian_bg" app:chipBackgroundColor="@color/list_chip_vegetarian_bg"
app:chipStrokeColor="@color/list_chip_stroke"
android:text="@string/pref_vegetarian"/> android:text="@string/pref_vegetarian"/>
<com.google.android.material.chip.Chip <com.google.android.material.chip.Chip
@@ -154,6 +162,7 @@
android:textColor="@color/list_chip_vegan_text" android:textColor="@color/list_chip_vegan_text"
app:chipIconTint="@color/list_chip_vegan_text" app:chipIconTint="@color/list_chip_vegan_text"
app:chipBackgroundColor="@color/list_chip_vegan_bg" app:chipBackgroundColor="@color/list_chip_vegan_bg"
app:chipStrokeColor="@color/list_chip_stroke"
android:text="@string/pref_vegan"/> android:text="@string/pref_vegan"/>
<com.google.android.material.chip.Chip <com.google.android.material.chip.Chip
@@ -166,6 +175,7 @@
android:textColor="@color/list_chip_game_text" android:textColor="@color/list_chip_game_text"
app:chipIconTint="@color/list_chip_game_text" app:chipIconTint="@color/list_chip_game_text"
app:chipBackgroundColor="@color/list_chip_game_bg" app:chipBackgroundColor="@color/list_chip_game_bg"
app:chipStrokeColor="@color/list_chip_stroke"
android:text="@string/pref_game"/> android:text="@string/pref_game"/>
</com.google.android.material.chip.ChipGroup> </com.google.android.material.chip.ChipGroup>
+2 -2
View File
@@ -27,7 +27,7 @@
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@id/button_cancel" app:layout_constraintEnd_toStartOf="@id/button_cancel"
android:text="@string/sheet_cheat_header"/> android:text="@string/question_mark"/>
<com.google.android.material.button.MaterialButton <com.google.android.material.button.MaterialButton
style="@style/Widget.Material3.Button.TextButton" style="@style/Widget.Material3.Button.TextButton"
@@ -68,7 +68,7 @@
style="@style/Widget.Material3.Button.TonalButton" style="@style/Widget.Material3.Button.TonalButton"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/confirm" android:text="@string/question_mark"
android:layout_gravity="end" android:layout_gravity="end"
android:layout_marginTop="8dp" android:layout_marginTop="8dp"
android:layout_marginEnd="24dp" android:layout_marginEnd="24dp"
@@ -7,16 +7,16 @@
<fragment <fragment
android:id="@+id/schedule" android:id="@+id/schedule"
android:name="com.denizk0461.studip.fragment.EventFragment" android:name="com.denizk0461.weserplaner.fragment.EventFragment"
android:label="EventFragment" android:label="EventFragment"
tools:layout="@layout/fragment_event"/> tools:layout="@layout/fragment_event"/>
<fragment <fragment
android:id="@+id/canteen" android:id="@+id/canteen"
android:name="com.denizk0461.studip.fragment.CanteenFragment" android:name="com.denizk0461.weserplaner.fragment.CanteenFragment"
android:label="CanteenFragment"/> android:label="CanteenFragment"/>
<fragment <fragment
android:id="@+id/settings" android:id="@+id/settings"
android:name="com.denizk0461.studip.fragment.SettingsFragment" android:name="com.denizk0461.weserplaner.fragment.SettingsFragment"
android:label="SettingsFragment" android:label="SettingsFragment"
tools:layout="@layout/fragment_settings"/> tools:layout="@layout/fragment_settings"/>
</navigation> </navigation>
+5 -3
View File
@@ -1,5 +1,5 @@
<resources> <resources>
<string name="app_name">Stud.IP Timetable</string> <!-- <string name="app_name">sixminutes</string>-->
<string name="toast_first_launch">Hey, danke, dass Du meine App ausprobierst! ~Deniz</string> <string name="toast_first_launch">Hey, danke, dass Du meine App ausprobierst! ~Deniz</string>
@@ -53,6 +53,8 @@
<string name="sheet_schedule_update_room_hint">Raum</string> <string name="sheet_schedule_update_room_hint">Raum</string>
<string name="sheet_schedule_update_hint_quarter">Auf akademisches Viertel umstellen</string> <string name="sheet_schedule_update_hint_quarter">Auf akademisches Viertel umstellen</string>
<string name="sheet_schedule_update_hint_quarter_error">Sorry, ein Fehler ist aufgetreten!</string> <string name="sheet_schedule_update_hint_quarter_error">Sorry, ein Fehler ist aufgetreten!</string>
<string name="sheet_schedule_update_timestamp_error_mixed">Der Kurs kann nicht enden bevor er aufhört.</string>
<string name="sheet_schedule_update_timestamp_error_equal">Der Kurs kann nicht zur gleichen Zeit anfangen und aufhören.</string>
<string name="sheet_schedule_update_timestamp_error_start">Der Kurs kann nicht anfangen nachdem er aufhört!</string> <string name="sheet_schedule_update_timestamp_error_start">Der Kurs kann nicht anfangen nachdem er aufhört!</string>
<string name="sheet_schedule_update_timestamp_error_end">Der Kurs kann nicht enden bevor er anfängt!</string> <string name="sheet_schedule_update_timestamp_error_end">Der Kurs kann nicht enden bevor er anfängt!</string>
<string name="sheet_schedule_update_text_field_empty_error">Dieses Feld darf nicht leer sein</string> <string name="sheet_schedule_update_text_field_empty_error">Dieses Feld darf nicht leer sein</string>
@@ -185,10 +187,10 @@
<string name="settings_data_title">Was passiert mit meinen Daten?</string> <string name="settings_data_title">Was passiert mit meinen Daten?</string>
<string name="settings_data_subtitle">Stiehlst du meinen Stud.IP-Login?</string> <string name="settings_data_subtitle">Stiehlst du meinen Stud.IP-Login?</string>
<string name="settings_data_sheet_header">TL;DR: nein.</string> <string name="settings_data_sheet_header">TL;DR: nein.</string>
<string name="settings_data_sheet_content">Die App funktioniert standalone, was bedeutet, dass sie sich niemals mit einem Server verbindet, der mir gehört. Sie ist ein Web-Scraper, also ein Programm, welches eine Internetseite öffnet und dann all die Informationen dieser Webseite herunterlädt und analysiert. In diesem Fall sind es die Webseiten der Mensen und Cafeterien des Studierendenwerks Bremen (stw-bremen.de) sowie die Stud.IP-Seite (elearning.uni-bremen.de).\n\nDies funktioniert relativ einfach für die Essenspläne, da diese Pläne öffentlich zugänglich sind. Um jedoch Deinen persönlichen Stud.IP-Stundenplan herunterzuladen, braucht die App Zugriff auf diese Webseite während Dein Account eingeloggt ist. Dies erfolgt, indem die App Dich mit deinem Account einloggen lässt - dies geschieht, wenn Du den Knopf zum Aktualisieren des Plans drückst und die App Dir die Login-Seite zeigt - und Du dann den Knopf klickst, um den Inhalt, den HTML-Quellcode, herunterzuladen. Der HTML-Quellcode beinhält Informationen darüber, was auf einer Webseite angezeigt wird und wie es aussehen soll, aber er kann niemals persönliche Details beinhalten, wie zum Beispiel Passwörter oder andere Daten, die auf Deinem Gerät vorhanden sind.\n\nDer Quellcode wird dann lokal, also auf Deinem Gerät, zu den Daten verarbeitet, die Du dann in der App sehen kannst, ohne, dass jegliche Daten irgendwohin geschickt werden müssten.\n\nSolltest du dich versichern wollen, dass wirklich keine Daten an irgendwelche Server verschickt wird, kannst Du jederzeit das Projekt erkunden, da es Open-Source und auf meinen GitHub-Profil öffentlich zugänglich ist:\nhttps://github.com/denizk0461/studip-timetable/\n\nSchreib mir ansonsten gerne eine E-Mail:\ndenizk0461@gmail.com\ndeniz7@uni-bremen.de</string> <string name="settings_data_sheet_content">Die App funktioniert standalone, was bedeutet, dass sie sich niemals mit einem Server verbindet, der mir gehört. Sie ist ein Web-Scraper, also ein Programm, welches eine Internetseite öffnet und dann all die Informationen dieser Webseite herunterlädt und analysiert. In diesem Fall sind es die Webseiten der Mensen und Cafeterien des Studierendenwerks Bremen (stw-bremen.de) sowie die Stud.IP-Seite (elearning.uni-bremen.de).\n\nDies funktioniert relativ einfach für die Essenspläne, da diese Pläne öffentlich zugänglich sind. Um jedoch Deinen persönlichen Stud.IP-Stundenplan herunterzuladen, braucht die App Zugriff auf diese Webseite während Dein Account eingeloggt ist. Dies erfolgt, indem die App Dich mit deinem Account einloggen lässt - dies geschieht, wenn Du den Knopf zum Aktualisieren des Plans drückst und die App Dir die Login-Seite zeigt - und Du dann den Knopf klickst, um den Inhalt, den HTML-Quellcode, herunterzuladen. Der HTML-Quellcode beinhält Informationen darüber, was auf einer Webseite angezeigt wird und wie es aussehen soll, aber er kann niemals persönliche Details beinhalten, wie zum Beispiel Passwörter oder andere Daten, die auf Deinem Gerät vorhanden sind.\n\nDer Quellcode wird dann lokal, also auf Deinem Gerät, zu den Daten verarbeitet, die Du dann in der App sehen kannst, ohne, dass jegliche Daten irgendwohin geschickt werden müssten.\n\nSolltest du dich versichern wollen, dass wirklich keine Daten an irgendwelche Server verschickt wird, kannst Du jederzeit das Projekt erkunden, da es Open-Source und auf meinen GitHub-Profil öffentlich zugänglich ist:\nhttps://github.com/denizk0461/weserplaner/\n\nSchreib mir ansonsten gerne eine E-Mail:\ndenizk0461@gmail.com\ndeniz7@uni-bremen.de</string>
<!-- unused - use for possible future implementation of Crashlytics --> <!-- unused - use for possible future implementation of Crashlytics -->
<string name="settings_data_sheet_header_crashlytics">TL;DR: nein, aber Google könnte mir Bescheid geben, falls die App mal abstürzt.</string> <string name="settings_data_sheet_header_crashlytics">TL;DR: nein, aber Google könnte mir Bescheid geben, falls die App mal abstürzt.</string>
<string name="settings_data_sheet_content_crashlytics">Die App funktioniert standalone, was bedeutet, dass sie sich niemals mit einem Server verbindet, der mir gehört. Sie ist ein Web-Scraper, also ein Programm, welches eine Internetseite öffnet und dann all die Informationen dieser Webseite herunterlädt und analysiert. In diesem Fall sind es die Webseiten der Mensen und Cafeterien des Studierendenwerks Bremen (stw-bremen.de) sowie die Stud.IP-Seite (elearning.uni-bremen.de).\n\nDies funktioniert relativ einfach für die Essenspläne, da diese Pläne öffentlich zugänglich sind. Um jedoch Deinen persönlichen Stud.IP-Stundenplan herunterzuladen, braucht die App Zugriff auf diese Webseite während Dein Account eingeloggt ist. Dies erfolgt, indem die App Dich mit deinem Account einloggen lässt - dies geschieht, wenn Du den Knopf zum Aktualisieren des Plans drückst und die App Dir die Login-Seite zeigt - und Du dann den Knopf klickst, um den Inhalt, den HTML-Quellcode, herunterzuladen. Der HTML-Quellcode beinhält Informationen darüber, was auf einer Webseite angezeigt wird und wie es aussehen soll, aber er kann niemals persönliche Details beinhalten, wie zum Beispiel Passwörter oder andere Daten, die auf Deinem Gerät vorhanden sind.\n\nDer Quellcode wird dann lokal, also auf Deinem Gerät, zu den Daten verarbeitet, die Du dann in der App sehen kannst, ohne, dass jegliche Daten irgendwohin geschickt werden müssten.\n\nEinige Daten welche nichts mit Deinen Stud.IP-Daten zu tun haben könnten jedoch dennoch nach außen geschickt werden. Diese App nutzt \"Crashlytics\" von Google. Dies ist ein Tool, welches Absturzreporte an Google-Server schickt, wenn in der App etwas schief läuft. Diese werden genutzt, um Probleme in der App zu lösen.\n\nDies ist jedoch gemäß europäischer Datenschutz-Grundverordnung Opt-In, was bedeutet, dass Du zustimmen musst, bevor Daten nach außen geschickt werden. Du wurdest danach gefragt, als Du die App zum ersten Mal gestartet hast, und du kannst jederzeit deine Meinung ändern, indem Du den Schalter hierfür in den Einstellungen umstellst. Solltest Du dich entscheiden, keine Daten verschicken zu lassen, wird auch nichts mit Google (und mir) geteilt.\n\nSolltest du dich versichern wollen, dass wirklich keine Daten an irgendwelche Server verschickt wird (abgesehen von den Absturzreports an Google), kannst Du jederzeit das Projekt erkunden, da es Open-Source und auf meinen GitHub-Profil öffentlich zugänglich ist:\nhttps://github.com/denizk0461/studip-timetable/\n\nSchreib mir ansonsten gerne eine E-Mail:\ndenizk0461@gmail.com\ndeniz7@uni-bremen.de</string> <string name="settings_data_sheet_content_crashlytics">Die App funktioniert standalone, was bedeutet, dass sie sich niemals mit einem Server verbindet, der mir gehört. Sie ist ein Web-Scraper, also ein Programm, welches eine Internetseite öffnet und dann all die Informationen dieser Webseite herunterlädt und analysiert. In diesem Fall sind es die Webseiten der Mensen und Cafeterien des Studierendenwerks Bremen (stw-bremen.de) sowie die Stud.IP-Seite (elearning.uni-bremen.de).\n\nDies funktioniert relativ einfach für die Essenspläne, da diese Pläne öffentlich zugänglich sind. Um jedoch Deinen persönlichen Stud.IP-Stundenplan herunterzuladen, braucht die App Zugriff auf diese Webseite während Dein Account eingeloggt ist. Dies erfolgt, indem die App Dich mit deinem Account einloggen lässt - dies geschieht, wenn Du den Knopf zum Aktualisieren des Plans drückst und die App Dir die Login-Seite zeigt - und Du dann den Knopf klickst, um den Inhalt, den HTML-Quellcode, herunterzuladen. Der HTML-Quellcode beinhält Informationen darüber, was auf einer Webseite angezeigt wird und wie es aussehen soll, aber er kann niemals persönliche Details beinhalten, wie zum Beispiel Passwörter oder andere Daten, die auf Deinem Gerät vorhanden sind.\n\nDer Quellcode wird dann lokal, also auf Deinem Gerät, zu den Daten verarbeitet, die Du dann in der App sehen kannst, ohne, dass jegliche Daten irgendwohin geschickt werden müssten.\n\nEinige Daten welche nichts mit Deinen Stud.IP-Daten zu tun haben könnten jedoch dennoch nach außen geschickt werden. Diese App nutzt \"Crashlytics\" von Google. Dies ist ein Tool, welches Absturzreporte an Google-Server schickt, wenn in der App etwas schief läuft. Diese werden genutzt, um Probleme in der App zu lösen.\n\nDies ist jedoch gemäß europäischer Datenschutz-Grundverordnung Opt-In, was bedeutet, dass Du zustimmen musst, bevor Daten nach außen geschickt werden. Du wurdest danach gefragt, als Du die App zum ersten Mal gestartet hast, und du kannst jederzeit deine Meinung ändern, indem Du den Schalter hierfür in den Einstellungen umstellst. Solltest Du dich entscheiden, keine Daten verschicken zu lassen, wird auch nichts mit Google (und mir) geteilt.\n\nSolltest du dich versichern wollen, dass wirklich keine Daten an irgendwelche Server verschickt wird (abgesehen von den Absturzreports an Google), kannst Du jederzeit das Projekt erkunden, da es Open-Source und auf meinen GitHub-Profil öffentlich zugänglich ist:\nhttps://github.com/denizk0461/weserplaner/\n\nSchreib mir ansonsten gerne eine E-Mail:\ndenizk0461@gmail.com\ndeniz7@uni-bremen.de</string>
<string name="settings_licences_title">Siehe Lizenzen</string> <string name="settings_licences_title">Siehe Lizenzen</string>
<string name="settings_licences_subtitle">Ressourcen, die diese App möglich gemacht haben</string> <string name="settings_licences_subtitle">Ressourcen, die diese App möglich gemacht haben</string>
+9 -5
View File
@@ -1,5 +1,5 @@
<resources> <resources>
<string name="app_name">Stud.IP Timetable</string> <string name="app_name" translatable="false">WeserPlaner</string>
<string name="toast_first_launch">Hey, thank you for trying out my app! ~Deniz</string> <string name="toast_first_launch">Hey, thank you for trying out my app! ~Deniz</string>
@@ -54,6 +54,8 @@
<string name="sheet_schedule_update_timeslot_middle" translatable="false"></string> <string name="sheet_schedule_update_timeslot_middle" translatable="false"></string>
<string name="sheet_schedule_update_hint_quarter">Change to academic quarter</string> <string name="sheet_schedule_update_hint_quarter">Change to academic quarter</string>
<string name="sheet_schedule_update_hint_quarter_error">Sorry, an error occurred!</string> <string name="sheet_schedule_update_hint_quarter_error">Sorry, an error occurred!</string>
<string name="sheet_schedule_update_timestamp_error_mixed">The course cannot end before it begins.</string>
<string name="sheet_schedule_update_timestamp_error_equal">Start and end times cannot be equal.</string>
<string name="sheet_schedule_update_timestamp_error_start">The course can\'t begin after it ends!</string> <string name="sheet_schedule_update_timestamp_error_start">The course can\'t begin after it ends!</string>
<string name="sheet_schedule_update_timestamp_error_end">The course can\'t end before it begins!</string> <string name="sheet_schedule_update_timestamp_error_end">The course can\'t end before it begins!</string>
<string name="sheet_schedule_update_text_field_empty_error">This field cannot be empty</string> <string name="sheet_schedule_update_text_field_empty_error">This field cannot be empty</string>
@@ -67,7 +69,7 @@
<string name="canteen_fab_refresh_content_desc">Refresh offers</string> <string name="canteen_fab_refresh_content_desc">Refresh offers</string>
<string name="sheet_licences_header">Licences</string> <string name="sheet_licences_header">Licences</string>
<string name="sheet_licences_content" translatable="false">Android developer resources provided by Google.\nhttps://developer.android.com/\n\nCrash reporting provided by Google.\nhttps://firebase.google.com/products/crashlytics/\n\nDesign guidelines, icons, and colour palette provided by Google.\nhttps://m3.material.io/\n\nAdditional icons provided by Flaticon.\nhttps://www.flaticon.com/\n\nWeb scraping functionality provided by Jonathan Hedley.\nhttps://jhy.io/ | https://jsoup.org/</string> <string name="sheet_licences_content" translatable="false">Android developer resources by Google.\nhttps://developer.android.com/\nandroidx.appcompat:appcompat:1.6.1\nandroidx.constraintlayout:constraintlayout:2.1.4\nandroidx.core:core-ktx:1.10.0\nandroidx.fragment:fragment-ktx:1.6.0-beta01\nandroidx.navigation:navigation-fragment-ktx:2.5.3\nandroidx.navigation:navigation-ui-ktx:2.5.3\nandroidx.preference:preference-ktx:1.2.0\nandroidx.room:room-runtime:2.5.1\nandroidx.room:room-compiler:2.5.1\nandroidx.swiperefreshlayout:swiperefreshlayout:1.2.0-alpha01\n\nDesign guidelines, icons, and colour palette by Google.\nhttps://m3.material.io/\ncom.google.android.material:material:1.9.0\n\nAdditional icons by Flaticon.\nhttps://www.flaticon.com/\n\nWeb scraping functionality by Jonathan Hedley.\nhttps://jhy.io/\nhttps://jsoup.org/\norg.jsoup:jsoup:1.15.4\n\nApp developed by Deniz Düzgören.\ndenizk0461@gmail.com\ndeniz7@uni-bremen.de</string>
<string name="title_schedule">Your Schedule</string> <string name="title_schedule">Your Schedule</string>
<string name="title_food">Canteen Offers</string> <string name="title_food">Canteen Offers</string>
@@ -189,10 +191,10 @@
<string name="settings_data_title">What happens with my data?</string> <string name="settings_data_title">What happens with my data?</string>
<string name="settings_data_subtitle">Will you steal my Stud.IP login?</string> <string name="settings_data_subtitle">Will you steal my Stud.IP login?</string>
<string name="settings_data_sheet_header">TL;DR: no.</string> <string name="settings_data_sheet_header">TL;DR: no.</string>
<string name="settings_data_sheet_content">This app works standalone, which is to say, it doesn\'t ever connect to a server I own. Instead, it is a web scraper, which means that it opens a website and then downloads and analyses all the data from that website by itself. In this case, those websites are the canteen websites of the Studierendenwerk Bremen (stw-bremen.de) and the Stud.IP page (elearning.uni-bremen.de).\n\nThis works fairly easily for the canteen offers, since the plans are public and anyone can access them. However, to access your personal Stud.IP schedule, the app needs access to that website, with your account logged in. This is done by letting you log into the website by yourself (which happens when you click the button to refresh the schedule and the app opens the login page) and then clicking a button to download the content, the HTML source code, of the website. The HTML source code contains information about which elements are shown on the website and how they look, but it can never contain your personal details such as passwords, or any other sensitive data you may store on your device.\n\nThe HTML source is then processed locally on your device, which means that your device will handle converting the HTML source to the data you will be shown in the app by itself, without needing to send any data anywhere.\n\nShould you want to reassure yourself that no data is sent to any servers, feel free to explore the project, since it is open-source and documented on my GitHub profile:\nhttps://github.com/denizk0461/studip-timetable/\n\nYou\'re also welcome to send me an email:\ndenizk0461@gmail.com\ndeniz7@uni-bremen.de</string> <string name="settings_data_sheet_content">This app works standalone, which is to say, it doesn\'t ever connect to a server I own. Instead, it is a web scraper, which means that it opens a website and then downloads and analyses all the data from that website by itself. In this case, those websites are the canteen websites of the Studierendenwerk Bremen (stw-bremen.de) and the Stud.IP page (elearning.uni-bremen.de).\n\nThis works fairly easily for the canteen offers, since the plans are public and anyone can access them. However, to access your personal Stud.IP schedule, the app needs access to that website, with your account logged in. This is done by letting you log into the website by yourself (which happens when you click the button to refresh the schedule and the app opens the login page) and then clicking a button to download the content, the HTML source code, of the website. The HTML source code contains information about which elements are shown on the website and how they look, but it can never contain your personal details such as passwords, or any other sensitive data you may store on your device.\n\nThe HTML source is then processed locally on your device, which means that your device will handle converting the HTML source to the data you will be shown in the app by itself, without needing to send any data anywhere.\n\nShould you want to reassure yourself that no data is sent to any servers, feel free to explore the project, since it is open-source and documented on my GitHub profile:\nhttps://github.com/denizk0461/weserplaner/\n\nYou\'re also welcome to send me an email:\ndenizk0461@gmail.com\ndeniz7@uni-bremen.de</string>
<!-- unused - use for possible future implementation of Crashlytics --> <!-- unused - use for possible future implementation of Crashlytics -->
<string name="settings_data_sheet_header_crashlytics">TL;DR: no, but Google may let me know if the app crashes on your device.</string> <string name="settings_data_sheet_header_crashlytics">TL;DR: no, but Google may let me know if the app crashes on your device.</string>
<string name="settings_data_sheet_content_crashlytics">This app works standalone, which is to say, it doesn\'t ever connect to a server I own. Instead, it is a web scraper, which means that it opens a website and then downloads and analyses all the data from that website by itself. In this case, those websites are the canteen websites of the Studierendenwerk Bremen (stw-bremen.de) and the Stud.IP page (elearning.uni-bremen.de).\n\nThis works fairly easily for the canteen offers, since the plans are public and anyone can access them. However, to access your personal Stud.IP schedule, the app needs access to that website, with your account logged in. This is done by letting you log into the website by yourself (which happens when you click the button to refresh the schedule and the app opens the login page) and then clicking a button to download the content, the HTML source code, of the website. The HTML source code contains information about which elements are shown on the website and how they look, but it can never contain your personal details such as passwords, or any other sensitive data you may store on your device.\n\nThe HTML source is then processed locally on your device, which means that your device will handle converting the HTML source to the data you will be shown in the app by itself, without needing to send any data anywhere.\n\nHowever, some data which has nothing to do with your Stud.IP data may still be sent outside of your device. This app uses \"Crashlytics\" by Google, which is a tool that sends crash reports to Google servers if something breaks. These are used to fix problems that occur in the app.\n\nThis, in compliance with the European General Data Protection Regulation, is of course opt-in, which means that you need to accept this before any data is sent outside of your device. You have been prompted for this when you first started the app, and you can always change your mind in the app settings by clicking the corresponding switch. Should you choose to not share crash data with Google (and me), no data will be sent outside of your device.\n\nShould you want to reassure yourself that no data is sent to any servers (outside of the crash reports from Google), feel free to explore the project, since it is open-source and documented on my GitHub profile:\nhttps://github.com/denizk0461/studip-timetable/\n\nYou\'re also welcome to send me an email:\ndenizk0461@gmail.com\ndeniz7@uni-bremen.de</string> <string name="settings_data_sheet_content_crashlytics">This app works standalone, which is to say, it doesn\'t ever connect to a server I own. Instead, it is a web scraper, which means that it opens a website and then downloads and analyses all the data from that website by itself. In this case, those websites are the canteen websites of the Studierendenwerk Bremen (stw-bremen.de) and the Stud.IP page (elearning.uni-bremen.de).\n\nThis works fairly easily for the canteen offers, since the plans are public and anyone can access them. However, to access your personal Stud.IP schedule, the app needs access to that website, with your account logged in. This is done by letting you log into the website by yourself (which happens when you click the button to refresh the schedule and the app opens the login page) and then clicking a button to download the content, the HTML source code, of the website. The HTML source code contains information about which elements are shown on the website and how they look, but it can never contain your personal details such as passwords, or any other sensitive data you may store on your device.\n\nThe HTML source is then processed locally on your device, which means that your device will handle converting the HTML source to the data you will be shown in the app by itself, without needing to send any data anywhere.\n\nHowever, some data which has nothing to do with your Stud.IP data may still be sent outside of your device. This app uses \"Crashlytics\" by Google, which is a tool that sends crash reports to Google servers if something breaks. These are used to fix problems that occur in the app.\n\nThis, in compliance with the European General Data Protection Regulation, is of course opt-in, which means that you need to accept this before any data is sent outside of your device. You have been prompted for this when you first started the app, and you can always change your mind in the app settings by clicking the corresponding switch. Should you choose to not share crash data with Google (and me), no data will be sent outside of your device.\n\nShould you want to reassure yourself that no data is sent to any servers (outside of the crash reports from Google), feel free to explore the project, since it is open-source and documented on my GitHub profile:\nhttps://github.com/denizk0461/weserplaner/\n\nYou\'re also welcome to send me an email:\ndenizk0461@gmail.com\ndeniz7@uni-bremen.de</string>
<string name="settings_licences_title">View licences</string> <string name="settings_licences_title">View licences</string>
<string name="settings_licences_subtitle">Resources that made this app possible</string> <string name="settings_licences_subtitle">Resources that made this app possible</string>
@@ -210,11 +212,13 @@
<string name="settings_app_version_200" translatable="false">\\__*</string> <string name="settings_app_version_200" translatable="false">\\__*</string>
<string-array name="cheesy_wisdoms" translatable="false"> <string-array name="cheesy_wisdoms" translatable="false">
<item>it\'s only real when it hurts</item>
<item>can\'t go back in time, every second is a new one</item> <item>can\'t go back in time, every second is a new one</item>
<item>if we only had one more day, what is the last thing you\'d say?</item> <item>if we only had one more day, what is the last thing you\'d say?</item>
<item>love with your heart, use your head for everything else</item> <item>love with your heart, use your head for everything else</item>
<item>trans rights are human rights 🏳️‍⚧️</item> <item>trans rights are human rights 🏳️‍⚧️</item>
<item>i wouldn\'t risk any more than six minutes</item> <item>i wouldn\'t risk any more than six minutes</item>
<item>do you remember yesterday?</item>
<item>look at the sky, i\'m still here</item>
<item>sample text</item>
</string-array> </string-array>
</resources> </resources>
@@ -1,17 +0,0 @@
package com.denizk0461.studip
import org.junit.Test
import org.junit.Assert.*
/**
* Example local unit test, which will execute on the development machine (host).
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
class ExampleUnitTest {
@Test
fun addition_isCorrect() {
assertEquals(4, 2 + 2)
}
}