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 -5
View File
@@ -5,11 +5,11 @@ plugins {
}
android {
namespace 'com.denizk0461.studip'
namespace 'com.denizk0461.weserplaner'
compileSdk 33
defaultConfig {
applicationId "com.denizk0461.studip"
applicationId "com.denizk0461.weserplaner"
minSdk 24
targetSdk 33
versionCode 1
@@ -26,6 +26,7 @@ android {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.debug
}
}
compileOptions {
@@ -51,9 +52,6 @@ dependencies {
implementation 'androidx.navigation:navigation-ui-ktx:2.5.3'
implementation 'androidx.core:core-ktx:1.10.0'
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"
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.os.Bundle
@@ -8,12 +8,12 @@ import android.webkit.WebView
import android.webkit.WebViewClient
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.ViewModelProvider
import com.denizk0461.studip.R
import com.denizk0461.studip.data.showErrorSnackBar
import com.denizk0461.studip.data.showToast
import com.denizk0461.studip.databinding.ActivityFetcherBinding
import com.denizk0461.studip.sheet.TextSheet
import com.denizk0461.studip.viewmodel.FetcherViewModel
import com.denizk0461.weserplaner.R
import com.denizk0461.weserplaner.data.showErrorSnackBar
import com.denizk0461.weserplaner.data.showToast
import com.denizk0461.weserplaner.databinding.ActivityFetcherBinding
import com.denizk0461.weserplaner.sheet.TextSheet
import com.denizk0461.weserplaner.viewmodel.FetcherViewModel
import java.io.IOException
import java.net.URLDecoder
@@ -1,10 +1,10 @@
package com.denizk0461.studip.activity
package com.denizk0461.weserplaner.activity
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.WindowCompat
import com.denizk0461.studip.R
import com.denizk0461.studip.databinding.ActivityImageBinding
import com.denizk0461.weserplaner.R
import com.denizk0461.weserplaner.databinding.ActivityImageBinding
/**
* 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 androidx.core.view.WindowCompat
@@ -7,9 +7,9 @@ import androidx.lifecycle.ViewModelProvider
import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.fragment.findNavController
import androidx.navigation.ui.setupWithNavController
import com.denizk0461.studip.R
import com.denizk0461.studip.databinding.ActivityMainBinding
import com.denizk0461.studip.viewmodel.MainViewModel
import com.denizk0461.weserplaner.R
import com.denizk0461.weserplaner.databinding.ActivityMainBinding
import com.denizk0461.weserplaner.viewmodel.MainViewModel
/**
* 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.view.LayoutInflater
@@ -6,15 +6,15 @@ import android.view.ViewGroup
import androidx.appcompat.content.res.AppCompatResources
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import com.denizk0461.studip.R
import com.denizk0461.studip.data.AppDiffUtilCallback
import com.denizk0461.studip.data.getThemedColor
import com.denizk0461.studip.databinding.ItemCanteenBinding
import com.denizk0461.studip.databinding.ItemCanteenLineBinding
import com.denizk0461.studip.databinding.ItemIconBinding
import com.denizk0461.studip.model.CanteenOfferGroup
import com.denizk0461.studip.model.CanteenOfferGroupElement
import com.denizk0461.studip.model.DietaryPreferences
import com.denizk0461.weserplaner.R
import com.denizk0461.weserplaner.data.AppDiffUtilCallback
import com.denizk0461.weserplaner.data.getThemedColor
import com.denizk0461.weserplaner.databinding.ItemCanteenBinding
import com.denizk0461.weserplaner.databinding.ItemCanteenLineBinding
import com.denizk0461.weserplaner.databinding.ItemIconBinding
import com.denizk0461.weserplaner.model.CanteenOfferGroup
import com.denizk0461.weserplaner.model.CanteenOfferGroupElement
import com.denizk0461.weserplaner.model.DietaryPreferences
/**
* 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 androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.lifecycle.Lifecycle
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.
@@ -1,4 +1,4 @@
package com.denizk0461.studip.adapter
package com.denizk0461.weserplaner.adapter
import android.content.res.ColorStateList
import android.view.LayoutInflater
@@ -6,12 +6,12 @@ import android.view.ViewGroup
import androidx.appcompat.content.res.AppCompatResources.getDrawable
import androidx.recyclerview.widget.DiffUtil
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.denizk0461.studip.data.getThemedColor
import com.denizk0461.studip.data.parseToMinutes
import com.denizk0461.studip.model.StudIPEvent
import com.denizk0461.studip.databinding.ItemEventBinding
import com.denizk0461.weserplaner.data.getThemedColor
import com.denizk0461.weserplaner.data.parseToMinutes
import com.denizk0461.weserplaner.model.StudIPEvent
import com.denizk0461.weserplaner.databinding.ItemEventBinding
import java.util.*
/**
@@ -98,12 +98,12 @@ class StudIPEventItemAdapter(
}
// Set the divider colour to the text colour
holder.binding.divider.dividerColor =
theme.getThemedColor(com.denizk0461.studip.R.attr.colorText)
theme.getThemedColor(com.denizk0461.weserplaner.R.attr.colorText)
// Set ripple colour
holder.binding.linearLayout.background = getDrawable(
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
@@ -114,7 +114,7 @@ class StudIPEventItemAdapter(
ColorStateList.valueOf(theme.getThemedColor(R.attr.colorSurface))
// 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
holder.binding.divider.dividerColor = theme.getThemedColor(R.attr.colorOutlineVariant)
@@ -122,7 +122,7 @@ class StudIPEventItemAdapter(
// Set ripple colour
holder.binding.linearLayout.background = getDrawable(
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 androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.lifecycle.Lifecycle
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.
@@ -1,4 +1,4 @@
package com.denizk0461.studip.data
package com.denizk0461.weserplaner.data
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.res.Resources
@@ -11,10 +11,10 @@ import android.widget.Toast
import androidx.annotation.AttrRes
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import com.denizk0461.studip.R
import com.denizk0461.studip.exception.AcademicQuarterNotApplicableException
import com.denizk0461.studip.exception.ParcelNotFoundException
import com.denizk0461.studip.sheet.TextSheet
import com.denizk0461.weserplaner.R
import com.denizk0461.weserplaner.exception.AcademicQuarterNotApplicableException
import com.denizk0461.weserplaner.exception.ParcelNotFoundException
import com.denizk0461.weserplaner.sheet.TextSheet
import com.google.android.material.snackbar.Snackbar
import kotlin.jvm.Throws
@@ -1,4 +1,4 @@
package com.denizk0461.studip.data
package com.denizk0461.weserplaner.data
import android.view.View
import androidx.fragment.app.Fragment
@@ -1,8 +1,8 @@
package com.denizk0461.studip.data
package com.denizk0461.weserplaner.data
import android.app.Application
import com.denizk0461.studip.db.AppRepository
import com.denizk0461.studip.model.StudIPEvent
import com.denizk0461.weserplaner.db.AppRepository
import com.denizk0461.weserplaner.model.StudIPEvent
import org.jsoup.Jsoup
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
@@ -1,8 +1,8 @@
package com.denizk0461.studip.data
package com.denizk0461.weserplaner.data
import android.app.Application
import com.denizk0461.studip.db.AppRepository
import com.denizk0461.studip.model.*
import com.denizk0461.weserplaner.db.AppRepository
import com.denizk0461.weserplaner.model.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import org.jsoup.Jsoup
@@ -139,7 +139,8 @@ class StwParser(application: Application) {
// Retrieve all opening hours.
it.children().forEach { element ->
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 {
element.children().forEach { subElement ->
openingHours += subElement.textWithBreaks() + '\n'
@@ -392,6 +393,14 @@ class StwParser(application: Application) {
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 {
action()
} catch (e: Exception) {
@@ -1,8 +1,8 @@
package com.denizk0461.studip.db
package com.denizk0461.weserplaner.db
import androidx.lifecycle.LiveData
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
@@ -1,10 +1,10 @@
package com.denizk0461.studip.db
package com.denizk0461.weserplaner.db
import android.content.Context
import androidx.room.Database
import androidx.room.Room
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.
@@ -1,10 +1,10 @@
package com.denizk0461.studip.db
package com.denizk0461.weserplaner.db
import android.app.Application
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
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
@@ -1,4 +1,4 @@
package com.denizk0461.studip.exception
package com.denizk0461.weserplaner.exception
import java.io.IOException
@@ -1,4 +1,4 @@
package com.denizk0461.studip.exception
package com.denizk0461.weserplaner.exception
import java.io.IOException
@@ -1,8 +1,8 @@
package com.denizk0461.studip.fragment
package com.denizk0461.weserplaner.fragment
import android.content.Context
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
@@ -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
*/
@@ -1,4 +1,4 @@
package com.denizk0461.studip.fragment
package com.denizk0461.weserplaner.fragment
import android.os.Bundle
import android.view.LayoutInflater
@@ -6,14 +6,14 @@ import android.view.View
import android.view.ViewGroup
import androidx.appcompat.widget.PopupMenu
import androidx.fragment.app.viewModels
import com.denizk0461.studip.R
import com.denizk0461.studip.adapter.CanteenOfferPageAdapter
import com.denizk0461.studip.data.getTextSheet
import com.denizk0461.studip.data.setRainbowProgressCircle
import com.denizk0461.studip.data.showErrorSnackBar
import com.denizk0461.studip.databinding.FragmentCanteenBinding
import com.denizk0461.studip.model.*
import com.denizk0461.studip.viewmodel.CanteenViewModel
import com.denizk0461.weserplaner.R
import com.denizk0461.weserplaner.adapter.CanteenOfferPageAdapter
import com.denizk0461.weserplaner.data.getTextSheet
import com.denizk0461.weserplaner.data.setRainbowProgressCircle
import com.denizk0461.weserplaner.data.showErrorSnackBar
import com.denizk0461.weserplaner.databinding.FragmentCanteenBinding
import com.denizk0461.weserplaner.model.*
import com.denizk0461.weserplaner.viewmodel.CanteenViewModel
import com.google.android.material.tabs.TabLayoutMediator
/**
@@ -61,17 +61,12 @@ class CanteenFragment : AppFragment() {
binding.swipeRefreshLayout.setRainbowProgressCircle()
// Set currently selected canteen to the button
// binding.buttonCanteenPicker.text = getCurrentlySelectedCanteenName()
binding.appTitleBar.text = getString(
R.string.title_canteen_template,
getCurrentlySelectedCanteenName(),
)
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
val chipMap = mapOf(
@@ -262,10 +257,20 @@ class CanteenFragment : AppFragment() {
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
}
})
}
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.view.LayoutInflater
@@ -6,15 +6,15 @@ import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.viewModels
import androidx.recyclerview.widget.LinearLayoutManager
import com.denizk0461.studip.adapter.CanteenOfferItemAdapter
import com.denizk0461.studip.adapter.StudIPEventPageAdapter
import com.denizk0461.studip.databinding.RecyclerViewBinding
import com.denizk0461.studip.model.CanteenOffer
import com.denizk0461.studip.model.CanteenOfferGroup
import com.denizk0461.studip.model.CanteenOfferGroupElement
import com.denizk0461.studip.model.DietaryPreferences
import com.denizk0461.studip.sheet.AllergenSheet
import com.denizk0461.studip.viewmodel.CanteenPageViewModel
import com.denizk0461.weserplaner.adapter.CanteenOfferItemAdapter
import com.denizk0461.weserplaner.adapter.StudIPEventPageAdapter
import com.denizk0461.weserplaner.databinding.RecyclerViewBinding
import com.denizk0461.weserplaner.model.CanteenOffer
import com.denizk0461.weserplaner.model.CanteenOfferGroup
import com.denizk0461.weserplaner.model.CanteenOfferGroupElement
import com.denizk0461.weserplaner.model.DietaryPreferences
import com.denizk0461.weserplaner.sheet.AllergenSheet
import com.denizk0461.weserplaner.viewmodel.CanteenPageViewModel
/**
* 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
// 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
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.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.viewModels
import com.denizk0461.studip.R
import com.denizk0461.studip.adapter.StudIPEventPageAdapter
import com.denizk0461.studip.databinding.FragmentEventBinding
import com.denizk0461.studip.sheet.ScheduleUpdateSheet
import com.denizk0461.studip.viewmodel.EventViewModel
import com.denizk0461.weserplaner.R
import com.denizk0461.weserplaner.adapter.StudIPEventPageAdapter
import com.denizk0461.weserplaner.databinding.FragmentEventBinding
import com.denizk0461.weserplaner.sheet.ScheduleUpdateSheet
import com.denizk0461.weserplaner.viewmodel.EventViewModel
import com.google.android.material.tabs.TabLayoutMediator
import java.util.*
@@ -1,4 +1,4 @@
package com.denizk0461.studip.fragment
package com.denizk0461.weserplaner.fragment
import android.os.Bundle
import android.view.LayoutInflater
@@ -6,12 +6,12 @@ import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.viewModels
import androidx.recyclerview.widget.LinearLayoutManager
import com.denizk0461.studip.adapter.StudIPEventPageAdapter
import com.denizk0461.studip.adapter.StudIPEventItemAdapter
import com.denizk0461.studip.databinding.RecyclerViewBinding
import com.denizk0461.studip.model.StudIPEvent
import com.denizk0461.studip.sheet.ScheduleUpdateSheet
import com.denizk0461.studip.viewmodel.EventPageViewModel
import com.denizk0461.weserplaner.adapter.StudIPEventPageAdapter
import com.denizk0461.weserplaner.adapter.StudIPEventItemAdapter
import com.denizk0461.weserplaner.databinding.RecyclerViewBinding
import com.denizk0461.weserplaner.model.StudIPEvent
import com.denizk0461.weserplaner.sheet.ScheduleUpdateSheet
import com.denizk0461.weserplaner.viewmodel.EventPageViewModel
/**
* 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.content.Intent
@@ -8,16 +8,16 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.viewModels
import com.denizk0461.studip.BuildConfig
import com.denizk0461.studip.R
import com.denizk0461.studip.activity.FetcherActivity
import com.denizk0461.studip.activity.ImageActivity
import com.denizk0461.studip.data.getTextSheet
import com.denizk0461.studip.data.showToast
import com.denizk0461.studip.databinding.FragmentSettingsBinding
import com.denizk0461.studip.sheet.AllergenConfigSheet
import com.denizk0461.studip.sheet.DevCodeSheet
import com.denizk0461.studip.viewmodel.SettingsViewModel
import com.denizk0461.weserplaner.BuildConfig
import com.denizk0461.weserplaner.R
import com.denizk0461.weserplaner.activity.FetcherActivity
import com.denizk0461.weserplaner.activity.ImageActivity
import com.denizk0461.weserplaner.data.getTextSheet
import com.denizk0461.weserplaner.data.showToast
import com.denizk0461.weserplaner.databinding.FragmentSettingsBinding
import com.denizk0461.weserplaner.sheet.AllergenConfigSheet
import com.denizk0461.weserplaner.sheet.DevCodeSheet
import com.denizk0461.weserplaner.viewmodel.SettingsViewModel
import java.text.SimpleDateFormat
import java.util.*
@@ -38,6 +38,9 @@ class SettingsFragment : AppFragment() {
// View model reference for providing access to the database
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
private var appVersionClick = 1
@@ -135,7 +138,12 @@ class SettingsFragment : AppFragment() {
// Set long click listener for licences button to open dev code sheet
binding.buttonLicences.setOnLongClickListener {
openBottomSheet(DevCodeSheet())
if (licencesLongClick > 3) {
openBottomSheet(DevCodeSheet())
licencesLongClick = 1
} else {
licencesLongClick += 1
}
true
}
@@ -148,18 +156,18 @@ class SettingsFragment : AppFragment() {
// Set click listener for the app version button
binding.buttonAppVersion.setOnClickListener {
when (appVersionClick) {
3 -> {
4 -> {
startActivity(Intent(context, ImageActivity::class.java).also { intent ->
val bundle = Bundle()
bundle.putString("img", "garbage")
intent.putExtras(bundle)
})
}
15 -> showToast(context, getString(R.string.settings_app_version_15))
20 -> showToast(context, getString(R.string.settings_app_version_20))
30 -> showToast(context, getString(R.string.settings_app_version_30))
20 -> showToast(context, getString(R.string.settings_app_version_15))
35 -> showToast(context, getString(R.string.settings_app_version_20))
50 -> showToast(context, getString(R.string.settings_app_version_30))
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))
200 -> showToast(context, getString(R.string.settings_app_version_200))
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
@@ -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.
@@ -1,4 +1,4 @@
package com.denizk0461.studip.model
package com.denizk0461.weserplaner.model
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,
@@ -1,4 +1,4 @@
package com.denizk0461.studip.model
package com.denizk0461.weserplaner.model
import android.os.Parcel
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.
@@ -1,4 +1,4 @@
package com.denizk0461.studip.model
package com.denizk0461.weserplaner.model
import androidx.room.Entity
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.ForeignKey
@@ -1,4 +1,4 @@
package com.denizk0461.studip.model
package com.denizk0461.weserplaner.model
import androidx.room.Entity
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.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
@@ -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.
@@ -1,4 +1,4 @@
package com.denizk0461.studip.model
package com.denizk0461.weserplaner.model
import android.os.Parcel
import android.os.Parcelable
@@ -1,14 +1,14 @@
package com.denizk0461.studip.sheet
package com.denizk0461.weserplaner.sheet
import android.os.Bundle
import android.view.View
import androidx.fragment.app.viewModels
import com.denizk0461.studip.R
import com.denizk0461.studip.data.showToast
import com.denizk0461.studip.data.viewBinding
import com.denizk0461.studip.databinding.SheetAllergenConfigBinding
import com.denizk0461.studip.model.AllergenPreferences
import com.denizk0461.studip.viewmodel.AllergenConfigViewModel
import com.denizk0461.weserplaner.R
import com.denizk0461.weserplaner.data.showToast
import com.denizk0461.weserplaner.data.viewBinding
import com.denizk0461.weserplaner.databinding.SheetAllergenConfigBinding
import com.denizk0461.weserplaner.model.AllergenPreferences
import com.denizk0461.weserplaner.viewmodel.AllergenConfigViewModel
/**
* 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.os.Bundle
import android.view.LayoutInflater
import android.view.View
import androidx.appcompat.content.res.AppCompatResources.getDrawable
import com.denizk0461.studip.R
import com.denizk0461.studip.data.getParcelableCompat
import com.denizk0461.studip.data.getThemedColor
import com.denizk0461.studip.data.showToast
import com.denizk0461.studip.data.viewBinding
import com.denizk0461.studip.databinding.ItemSheetPreferenceBinding
import com.denizk0461.studip.databinding.SheetAllergenBinding
import com.denizk0461.studip.exception.ParcelNotFoundException
import com.denizk0461.studip.model.Allergens
import com.denizk0461.studip.model.CanteenOfferGroupElement
import com.denizk0461.studip.model.DietaryPreferences
import com.denizk0461.weserplaner.R
import com.denizk0461.weserplaner.data.getParcelableCompat
import com.denizk0461.weserplaner.data.getThemedColor
import com.denizk0461.weserplaner.data.showToast
import com.denizk0461.weserplaner.data.viewBinding
import com.denizk0461.weserplaner.databinding.ItemSheetPreferenceBinding
import com.denizk0461.weserplaner.databinding.SheetAllergenBinding
import com.denizk0461.weserplaner.exception.ParcelNotFoundException
import com.denizk0461.weserplaner.model.Allergens
import com.denizk0461.weserplaner.model.CanteenOfferGroupElement
import com.denizk0461.weserplaner.model.DietaryPreferences
/**
* 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.os.Bundle
@@ -1,4 +1,4 @@
package com.denizk0461.studip.sheet
package com.denizk0461.weserplaner.sheet
import android.content.Intent
import android.net.Uri
@@ -6,12 +6,12 @@ import android.os.Bundle
import android.util.Base64
import android.view.View
import androidx.fragment.app.viewModels
import com.denizk0461.studip.R
import com.denizk0461.studip.activity.ImageActivity
import com.denizk0461.studip.data.showToast
import com.denizk0461.studip.data.viewBinding
import com.denizk0461.studip.databinding.SheetDevCodeBinding
import com.denizk0461.studip.viewmodel.DevCodeViewModel
import com.denizk0461.weserplaner.R
import com.denizk0461.weserplaner.activity.ImageActivity
import com.denizk0461.weserplaner.data.showToast
import com.denizk0461.weserplaner.data.viewBinding
import com.denizk0461.weserplaner.databinding.SheetDevCodeBinding
import com.denizk0461.weserplaner.viewmodel.DevCodeViewModel
import java.nio.charset.StandardCharsets
/**
@@ -58,6 +58,8 @@ class DevCodeSheet : AppSheet(R.layout.sheet_dev_code) {
"Q0FMTE1F".d64 -> launchLink("aHR0cHM6Ly95b3V0dS5iZS8xbTV1WnJNMnktMA==".d64)
"SkFNSVJP".d64 -> launchLink("aHR0cHM6Ly95b3V0dS5iZS9fMVZoT2c0N3ozNA==".d64)
"TE9ORUxZ".d64 -> launchLink("aHR0cHM6Ly95b3V0dS5iZS9uLURFNHNfc3d5Zw==".d64)
"QkVBVVRZ".d64 -> launchLink("aHR0cHM6Ly95b3V0dS5iZS9vbVQ1ckttVTVfaw==".d64)
"Uk9NQ09N".d64 -> launchLink("aHR0cHM6Ly95b3V0dS5iZS9HUW1nUG5uZjE4WQ==".d64)
"Qk9KQUNL".d64 -> {
startActivity(Intent(context, ImageActivity::class.java).also { intent ->
val bundle = Bundle()
@@ -1,4 +1,4 @@
package com.denizk0461.studip.sheet
package com.denizk0461.weserplaner.sheet
import android.os.Bundle
import android.view.View
@@ -7,19 +7,19 @@ import androidx.appcompat.widget.PopupMenu
import androidx.core.widget.addTextChangedListener
import androidx.fragment.app.viewModels
import androidx.transition.TransitionManager
import com.denizk0461.studip.R
import com.denizk0461.studip.data.getParcelableCompat
import com.denizk0461.studip.data.getTimestampAcademicQuarterEnd
import com.denizk0461.studip.data.getTimestampAcademicQuarterStart
import com.denizk0461.studip.data.parseToMinutes
import com.denizk0461.studip.data.showToast
import com.denizk0461.studip.data.timeslotsForAcademicQuarter
import com.denizk0461.studip.data.viewBinding
import com.denizk0461.studip.databinding.SheetScheduleUpdateBinding
import com.denizk0461.studip.exception.AcademicQuarterNotApplicableException
import com.denizk0461.studip.exception.ParcelNotFoundException
import com.denizk0461.studip.model.StudIPEvent
import com.denizk0461.studip.viewmodel.ScheduleUpdateViewModel
import com.denizk0461.weserplaner.R
import com.denizk0461.weserplaner.data.getParcelableCompat
import com.denizk0461.weserplaner.data.getTimestampAcademicQuarterEnd
import com.denizk0461.weserplaner.data.getTimestampAcademicQuarterStart
import com.denizk0461.weserplaner.data.parseToMinutes
import com.denizk0461.weserplaner.data.showToast
import com.denizk0461.weserplaner.data.timeslotsForAcademicQuarter
import com.denizk0461.weserplaner.data.viewBinding
import com.denizk0461.weserplaner.databinding.SheetScheduleUpdateBinding
import com.denizk0461.weserplaner.exception.AcademicQuarterNotApplicableException
import com.denizk0461.weserplaner.exception.ParcelNotFoundException
import com.denizk0461.weserplaner.model.StudIPEvent
import com.denizk0461.weserplaner.viewmodel.ScheduleUpdateViewModel
import com.google.android.material.timepicker.MaterialTimePicker
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 {
// Check if any of the text fields are empty
checkIfTextFieldsEmpty {
// 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,
// Check the time stamps. If start > end, show an error
if (timeslotStart.parseToMinutes() > timeslotEnd.parseToMinutes()) {
showToast(
context,
getString(R.string.sheet_schedule_update_timestamp_error_mixed),
)
)
// Dismiss the sheet upon update
dismiss()
// If the time stamps are equal, show an error
} else if (timeslotEnd.parseToMinutes() == timeslotStart.parseToMinutes()) {
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
binding.buttonDelete.visibility = View.GONE
// Prepare update/save button
// Prepare save button
binding.buttonSave.setOnClickListener {
// Check if any of the text fields are empty
checkIfTextFieldsEmpty {
// 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,
// Check the time stamps. If start > end, show an error
if (timeslotStart.parseToMinutes() > timeslotEnd.parseToMinutes()) {
showToast(
context,
getString(R.string.sheet_schedule_update_timestamp_error_mixed),
)
)
// Dismiss the sheet upon update
dismiss()
// If the time stamps are equal, show an error
} else if (timeslotEnd.parseToMinutes() == timeslotStart.parseToMinutes()) {
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.
val newTimestamp = "$hours:${String.format("%02d", minutes)}"
if (isEventStart && newTimestamp.parseToMinutes() > timeslotEnd.parseToMinutes()) {
// If editing start and start > end, show an error
showToast(context, getString(R.string.sheet_schedule_update_timestamp_error_start))
// If editing end and end < start, show an error
} else if (!isEventStart && newTimestamp.parseToMinutes() < timeslotStart.parseToMinutes()) {
showToast(context, getString(R.string.sheet_schedule_update_timestamp_error_end))
// If the new timestamp is valid, save it
if (isEventStart) {
timeslotStart = newTimestamp
binding.buttonTimeStart.text = newTimestamp
} else {
// If the new timestamp is valid, save it
if (isEventStart) {
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),
)
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),
)
}
/**
@@ -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
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
if (binding.editTextTitle.text.toString().isBlank()) {
// 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.view.View
import com.denizk0461.studip.R
import com.denizk0461.studip.data.viewBinding
import com.denizk0461.studip.databinding.SheetTextBinding
import com.denizk0461.weserplaner.R
import com.denizk0461.weserplaner.data.viewBinding
import com.denizk0461.weserplaner.databinding.SheetTextBinding
/**
* 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 com.denizk0461.studip.model.AllergenPreferences
import com.denizk0461.studip.model.SettingsPreferences
import com.denizk0461.weserplaner.model.AllergenPreferences
import com.denizk0461.weserplaner.model.SettingsPreferences
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 androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.viewModelScope
import com.denizk0461.studip.db.AppRepository
import com.denizk0461.weserplaner.db.AppRepository
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
@@ -1,11 +1,11 @@
package com.denizk0461.studip.viewmodel
package com.denizk0461.weserplaner.viewmodel
import android.app.Application
import androidx.lifecycle.LiveData
import com.denizk0461.studip.model.AllergenPreferences
import com.denizk0461.studip.model.CanteenOffer
import com.denizk0461.studip.model.DietaryPreferences
import com.denizk0461.studip.model.SettingsPreferences
import com.denizk0461.weserplaner.model.AllergenPreferences
import com.denizk0461.weserplaner.model.CanteenOffer
import com.denizk0461.weserplaner.model.DietaryPreferences
import com.denizk0461.weserplaner.model.SettingsPreferences
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 androidx.lifecycle.LiveData
import androidx.lifecycle.viewModelScope
import com.denizk0461.studip.data.StwParser
import com.denizk0461.studip.model.*
import com.denizk0461.weserplaner.data.StwParser
import com.denizk0461.weserplaner.model.*
import kotlinx.coroutines.Dispatchers
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
*/
@@ -1,4 +1,4 @@
package com.denizk0461.studip.viewmodel
package com.denizk0461.weserplaner.viewmodel
import android.app.Application
@@ -1,12 +1,12 @@
package com.denizk0461.studip.viewmodel
package com.denizk0461.weserplaner.viewmodel
import android.app.Application
import androidx.lifecycle.LiveData
import com.denizk0461.studip.model.SettingsPreferences
import com.denizk0461.studip.model.StudIPEvent
import com.denizk0461.weserplaner.model.SettingsPreferences
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
*/
@@ -1,10 +1,10 @@
package com.denizk0461.studip.viewmodel
package com.denizk0461.weserplaner.viewmodel
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
*/
@@ -1,12 +1,12 @@
package com.denizk0461.studip.viewmodel
package com.denizk0461.weserplaner.viewmodel
import android.app.Application
import com.denizk0461.studip.data.StudIPParser
import com.denizk0461.weserplaner.data.StudIPParser
import java.io.IOException
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
*/
@@ -1,10 +1,10 @@
package com.denizk0461.studip.viewmodel
package com.denizk0461.weserplaner.viewmodel
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
*/
@@ -1,7 +1,7 @@
package com.denizk0461.studip.viewmodel
package com.denizk0461.weserplaner.viewmodel
import android.app.Application
import com.denizk0461.studip.model.StudIPEvent
import com.denizk0461.weserplaner.model.StudIPEvent
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 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
*/
@@ -16,6 +16,7 @@ class SettingsViewModel(app: Application) : AppViewModel(app) {
var preferenceCurrentDay: Boolean
get() = repo.getBooleanPreference(
SettingsPreferences.CURRENT_DAY,
defaultValue = true,
)
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"
app:chipIconTint="@color/list_chip_fair_text"
app:chipBackgroundColor="@color/list_chip_fair_bg"
app:chipStrokeColor="@color/list_chip_stroke"
android:text="@string/pref_fair"/>
<com.google.android.material.chip.Chip
@@ -70,6 +71,7 @@
android:textColor="@color/list_chip_fish_text"
app:chipIconTint="@color/list_chip_fish_text"
app:chipBackgroundColor="@color/list_chip_fish_bg"
app:chipStrokeColor="@color/list_chip_stroke"
android:text="@string/pref_fish"/>
<com.google.android.material.chip.Chip
@@ -82,6 +84,7 @@
android:textColor="@color/list_chip_poultry_text"
app:chipIconTint="@color/list_chip_poultry_text"
app:chipBackgroundColor="@color/list_chip_poultry_bg"
app:chipStrokeColor="@color/list_chip_stroke"
android:text="@string/pref_poultry"/>
<com.google.android.material.chip.Chip
@@ -94,6 +97,7 @@
android:textColor="@color/list_chip_lamb_text"
app:chipIconTint="@color/list_chip_lamb_text"
app:chipBackgroundColor="@color/list_chip_lamb_bg"
app:chipStrokeColor="@color/list_chip_stroke"
android:text="@string/pref_lamb"/>
<com.google.android.material.chip.Chip
@@ -106,6 +110,7 @@
android:textColor="@color/list_chip_vital_text"
app:chipIconTint="@color/list_chip_vital_text"
app:chipBackgroundColor="@color/list_chip_vital_bg"
app:chipStrokeColor="@color/list_chip_stroke"
android:text="@string/pref_vital"/>
<com.google.android.material.chip.Chip
@@ -118,6 +123,7 @@
android:textColor="@color/list_chip_beef_text"
app:chipIconTint="@color/list_chip_beef_text"
app:chipBackgroundColor="@color/list_chip_beef_bg"
app:chipStrokeColor="@color/list_chip_stroke"
android:text="@string/pref_beef"/>
<com.google.android.material.chip.Chip
@@ -130,6 +136,7 @@
android:textColor="@color/list_chip_pork_text"
app:chipIconTint="@color/list_chip_pork_text"
app:chipBackgroundColor="@color/list_chip_pork_bg"
app:chipStrokeColor="@color/list_chip_stroke"
android:text="@string/pref_pork"/>
<com.google.android.material.chip.Chip
@@ -142,6 +149,7 @@
android:textColor="@color/list_chip_vegetarian_text"
app:chipIconTint="@color/list_chip_vegetarian_text"
app:chipBackgroundColor="@color/list_chip_vegetarian_bg"
app:chipStrokeColor="@color/list_chip_stroke"
android:text="@string/pref_vegetarian"/>
<com.google.android.material.chip.Chip
@@ -154,6 +162,7 @@
android:textColor="@color/list_chip_vegan_text"
app:chipIconTint="@color/list_chip_vegan_text"
app:chipBackgroundColor="@color/list_chip_vegan_bg"
app:chipStrokeColor="@color/list_chip_stroke"
android:text="@string/pref_vegan"/>
<com.google.android.material.chip.Chip
@@ -166,6 +175,7 @@
android:textColor="@color/list_chip_game_text"
app:chipIconTint="@color/list_chip_game_text"
app:chipBackgroundColor="@color/list_chip_game_bg"
app:chipStrokeColor="@color/list_chip_stroke"
android:text="@string/pref_game"/>
</com.google.android.material.chip.ChipGroup>
+2 -2
View File
@@ -27,7 +27,7 @@
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@id/button_cancel"
android:text="@string/sheet_cheat_header"/>
android:text="@string/question_mark"/>
<com.google.android.material.button.MaterialButton
style="@style/Widget.Material3.Button.TextButton"
@@ -68,7 +68,7 @@
style="@style/Widget.Material3.Button.TonalButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/confirm"
android:text="@string/question_mark"
android:layout_gravity="end"
android:layout_marginTop="8dp"
android:layout_marginEnd="24dp"
@@ -7,16 +7,16 @@
<fragment
android:id="@+id/schedule"
android:name="com.denizk0461.studip.fragment.EventFragment"
android:name="com.denizk0461.weserplaner.fragment.EventFragment"
android:label="EventFragment"
tools:layout="@layout/fragment_event"/>
<fragment
android:id="@+id/canteen"
android:name="com.denizk0461.studip.fragment.CanteenFragment"
android:name="com.denizk0461.weserplaner.fragment.CanteenFragment"
android:label="CanteenFragment"/>
<fragment
android:id="@+id/settings"
android:name="com.denizk0461.studip.fragment.SettingsFragment"
android:name="com.denizk0461.weserplaner.fragment.SettingsFragment"
android:label="SettingsFragment"
tools:layout="@layout/fragment_settings"/>
</navigation>
+5 -3
View File
@@ -1,5 +1,5 @@
<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>
@@ -53,6 +53,8 @@
<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_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_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>
@@ -185,10 +187,10 @@
<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_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 -->
<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_subtitle">Ressourcen, die diese App möglich gemacht haben</string>
+9 -5
View File
@@ -1,5 +1,5 @@
<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>
@@ -54,6 +54,8 @@
<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_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_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>
@@ -67,7 +69,7 @@
<string name="canteen_fab_refresh_content_desc">Refresh offers</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_food">Canteen Offers</string>
@@ -189,10 +191,10 @@
<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_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 -->
<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_subtitle">Resources that made this app possible</string>
@@ -210,11 +212,13 @@
<string name="settings_app_version_200" translatable="false">\\__*</string>
<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>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>trans rights are human rights 🏳️‍⚧️</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>
</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)
}
}