Archived
WeserPlaner 1.0.3: adjusted layout of AllergenSheet.kt to display allergens and additives separately; FetcherActivity.kt now features a button to go directly to the user's schedule, if logged in; replaced toast messages with snack bars; ScheduleUpdateSheet.kt now notifies the user about database transactions via snack bar; schedule view now tells the user if there are no events scheduled for a day
This commit is contained in:
@@ -10,6 +10,7 @@ import androidx.fragment.app.FragmentActivity
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import com.denizk0461.weserplaner.R
|
||||
import com.denizk0461.weserplaner.data.showErrorSnackBar
|
||||
import com.denizk0461.weserplaner.data.showSnackBar
|
||||
import com.denizk0461.weserplaner.data.showToast
|
||||
import com.denizk0461.weserplaner.databinding.ActivityFetcherBinding
|
||||
import com.denizk0461.weserplaner.model.TextSheetContentId
|
||||
@@ -50,7 +51,11 @@ class FetcherActivity : FragmentActivity() {
|
||||
setContentView(binding.root)
|
||||
|
||||
// Remind the user of the help button
|
||||
showToast(this, getString(R.string.toast_info_reminder))
|
||||
theme.showSnackBar(
|
||||
binding.coordinatorLayout,
|
||||
getString(R.string.fetch_snack_info_reminder),
|
||||
binding.bottomAppBar,
|
||||
)
|
||||
|
||||
// Enabling JavaScript. See comment above lint suppression for reason why this is done.
|
||||
binding.webview.settings.apply {
|
||||
@@ -104,15 +109,19 @@ class FetcherActivity : FragmentActivity() {
|
||||
}.show(supportFragmentManager, TextSheet::class.java.simpleName)
|
||||
true
|
||||
}
|
||||
R.id.schedule -> {
|
||||
binding.webview.loadUrl(scheduleUrl)
|
||||
true
|
||||
}
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempt to load the user-set Stud.IP front page. Redirects to login page if user is
|
||||
* Attempt to load the user's Stud.IP schedule page. Redirects to login page if user is
|
||||
* not logged in.
|
||||
*/
|
||||
binding.webview.loadUrl("https://elearning.uni-bremen.de/index.php?again=yes")
|
||||
binding.webview.loadUrl(scheduleUrl)
|
||||
|
||||
binding.fab.setOnClickListener {
|
||||
|
||||
@@ -146,18 +155,18 @@ class FetcherActivity : FragmentActivity() {
|
||||
} catch (e: IOException) {
|
||||
// Let the user know that an error occurred
|
||||
theme.showErrorSnackBar(
|
||||
binding.rootView,
|
||||
binding.coordinatorLayout,
|
||||
getString(R.string.fetch_error_snack),
|
||||
binding.bottomAppBar
|
||||
binding.bottomAppBar,
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Tell the user that they must navigate to their timetable
|
||||
theme.showErrorSnackBar(
|
||||
binding.rootView,
|
||||
binding.coordinatorLayout,
|
||||
getString(R.string.fetch_error_webpage_snack),
|
||||
binding.bottomAppBar
|
||||
binding.bottomAppBar,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,19 +76,15 @@ class CanteenOfferItemAdapter(
|
||||
|
||||
// Display
|
||||
if (position == (offers.size - 1) && difference > 0) {
|
||||
holder.binding.textDifference.apply {
|
||||
visibility = View.VISIBLE
|
||||
text = if (difference == 1) {
|
||||
context.getString(R.string.canteen_item_difference_text_one)
|
||||
} else {
|
||||
context.getString(R.string.canteen_item_difference_text_other, difference)
|
||||
}
|
||||
holder.binding.differenceContainer.visibility = View.VISIBLE
|
||||
holder.binding.textDifference.text = if (difference == 1) {
|
||||
context.getString(R.string.canteen_item_difference_text_one)
|
||||
} else {
|
||||
context.getString(R.string.canteen_item_difference_text_other, difference)
|
||||
}
|
||||
} else {
|
||||
holder.binding.textDifference.apply {
|
||||
visibility = View.GONE
|
||||
text = ""
|
||||
}
|
||||
holder.binding.differenceContainer.visibility = View.GONE
|
||||
holder.binding.textDifference.text = ""
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -2,12 +2,13 @@ package com.denizk0461.weserplaner.adapter
|
||||
|
||||
import android.content.res.ColorStateList
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.content.res.AppCompatResources.getDrawable
|
||||
import androidx.recyclerview.widget.DiffUtil
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.denizk0461.weserplaner.data.AppDiffUtilCallback
|
||||
import com.google.android.material.R
|
||||
import com.denizk0461.weserplaner.R
|
||||
import com.denizk0461.weserplaner.data.getThemedColor
|
||||
import com.denizk0461.weserplaner.data.parseToMinutes
|
||||
import com.denizk0461.weserplaner.model.StudIPEvent
|
||||
@@ -19,7 +20,7 @@ import java.util.*
|
||||
*
|
||||
|
||||
* @param currentDay current day that is used to show only a given day's events (0 = Monday,
|
||||
* 4 = Friday)
|
||||
* 4 = Friday, 6 = Sunday)
|
||||
* @param onClickListener used for listening to clicks and long presses
|
||||
*/
|
||||
class StudIPEventItemAdapter(
|
||||
@@ -65,9 +66,28 @@ class StudIPEventItemAdapter(
|
||||
override fun getItemCount(): Int = events.size
|
||||
|
||||
override fun onBindViewHolder(holder: EventViewHolder, position: Int) {
|
||||
|
||||
// Retrieve item for current position
|
||||
val currentItem = events[position]
|
||||
|
||||
// Context for easier reference
|
||||
val context = holder.binding.root.context
|
||||
|
||||
// Display a notice to the user saying they have no events scheduled for the day
|
||||
if (currentItem.eventId == -1) {
|
||||
holder.binding.cardBackground.visibility = View.GONE
|
||||
holder.binding.noEventsContainer.visibility = View.VISIBLE
|
||||
holder.binding.textNoEvents.text = context.getString(
|
||||
R.string.schedule_no_events,
|
||||
context.resources.getStringArray(R.array.weekdays)[currentDay]
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
// Set visibility of the elements accordingly if there are events scheduled
|
||||
holder.binding.cardBackground.visibility = View.VISIBLE
|
||||
holder.binding.noEventsContainer.visibility = View.GONE
|
||||
|
||||
// Set up text fields with corresponding values
|
||||
holder.binding.textTitle.text = currentItem.title
|
||||
holder.binding.textLecturers.text = currentItem.lecturer
|
||||
@@ -77,14 +97,17 @@ class StudIPEventItemAdapter(
|
||||
holder.binding.textTimeslot.text = currentItem.timeslot()
|
||||
|
||||
// Get current theme
|
||||
val theme = holder.binding.root.context.theme
|
||||
val theme = context.theme
|
||||
|
||||
/*
|
||||
* Highlight the next upcoming course of the day if the user selected the option, if the day
|
||||
* of the adapter matches the current day, and if no other course has been highlighted, to
|
||||
* avoid double highlighting.
|
||||
*/
|
||||
if (highlightNextCourse && !isAnyCourseHighlighted && currentItem.isCurrentCourse(currentCalendar)) {
|
||||
if (highlightNextCourse &&
|
||||
!isAnyCourseHighlighted &&
|
||||
currentItem.isCurrentCourse(currentCalendar)
|
||||
) {
|
||||
// Ensure that no other course will be highlighted
|
||||
isAnyCourseHighlighted = true
|
||||
|
||||
@@ -98,12 +121,12 @@ class StudIPEventItemAdapter(
|
||||
}
|
||||
// Set the divider colour to the text colour
|
||||
holder.binding.divider.dividerColor =
|
||||
theme.getThemedColor(com.denizk0461.weserplaner.R.attr.colorText)
|
||||
theme.getThemedColor(R.attr.colorText)
|
||||
|
||||
// Set ripple colour
|
||||
holder.binding.linearLayout.background = getDrawable(
|
||||
holder.binding.root.context,
|
||||
com.denizk0461.weserplaner.R.drawable.selectable_item_background_highlighted,
|
||||
R.drawable.selectable_item_background_highlighted,
|
||||
)
|
||||
|
||||
// Otherwise, apply colours to ensure that the item will not be highlighted
|
||||
@@ -111,7 +134,9 @@ class StudIPEventItemAdapter(
|
||||
holder.binding.cardBackground.apply {
|
||||
// Set the card's background colour to its default value
|
||||
backgroundTintList =
|
||||
ColorStateList.valueOf(theme.getThemedColor(R.attr.colorSurface))
|
||||
ColorStateList.valueOf(theme.getThemedColor(
|
||||
com.google.android.material.R.attr.colorSurface
|
||||
))
|
||||
|
||||
// Set the card's stroke to its default colour
|
||||
strokeColor = theme.getThemedColor(R.attr.colorOutlineVariant)
|
||||
@@ -122,7 +147,7 @@ class StudIPEventItemAdapter(
|
||||
// Set ripple colour
|
||||
holder.binding.linearLayout.background = getDrawable(
|
||||
holder.binding.root.context,
|
||||
com.denizk0461.weserplaner.R.drawable.selectable_item_background,
|
||||
R.drawable.selectable_item_background,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import androidx.viewpager2.widget.ViewPager2
|
||||
import com.denizk0461.weserplaner.R
|
||||
import com.denizk0461.weserplaner.activity.FetcherActivity
|
||||
import com.denizk0461.weserplaner.adapter.StudIPEventPageAdapter
|
||||
import com.denizk0461.weserplaner.data.showSnackBar
|
||||
import com.denizk0461.weserplaner.databinding.FragmentEventBinding
|
||||
import com.denizk0461.weserplaner.sheet.ScheduleUpdateSheet
|
||||
import com.denizk0461.weserplaner.viewmodel.EventViewModel
|
||||
@@ -144,6 +145,15 @@ class EventFragment : AppFragment() {
|
||||
binding.fabAddEvent.extend()
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and shows a snack bar.
|
||||
*
|
||||
* @param text content to display in the snack bar
|
||||
*/
|
||||
fun showSnackBar(text: String) {
|
||||
context.theme.showSnackBar(binding.coordinatorLayout, text)
|
||||
}
|
||||
|
||||
// Invalidate the view binding
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
|
||||
@@ -96,7 +96,20 @@ class EventPageFragment : AppFragment(), StudIPEventItemAdapter.OnClickListener
|
||||
|
||||
// Set up LiveData observer to refresh the view on update
|
||||
viewModel.getEventsForDay(currentDay).observe(viewLifecycleOwner) { events ->
|
||||
eventAdapter.setNewData(events)
|
||||
eventAdapter.setNewData(events.ifEmpty { listOf(
|
||||
// Use an event with eventId = -1 to denote that there are no events for this day
|
||||
StudIPEvent(
|
||||
-1,
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
0,
|
||||
"",
|
||||
"",
|
||||
0,
|
||||
0,
|
||||
)
|
||||
) })
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -238,8 +238,7 @@ class SettingsFragment : AppFragment() {
|
||||
licencesLongClick = 0
|
||||
viewModel.preferenceExperimentalSettingsEnabled = true
|
||||
binding.cardExperimentalSettings.visibility = View.VISIBLE
|
||||
context.theme.showSnackBar(
|
||||
binding.coordinatorLayout,
|
||||
showSnackBar(
|
||||
getString(R.string.settings_unlocked_experiments),
|
||||
)
|
||||
} else {
|
||||
@@ -320,8 +319,7 @@ class SettingsFragment : AppFragment() {
|
||||
binding.buttonHideExperiments.setOnClickListener {
|
||||
viewModel.preferenceExperimentalSettingsEnabled = false
|
||||
binding.cardExperimentalSettings.visibility = View.GONE
|
||||
context.theme.showSnackBar(
|
||||
binding.coordinatorLayout,
|
||||
showSnackBar(
|
||||
getString(R.string.settings_hide_experiments),
|
||||
)
|
||||
}
|
||||
@@ -397,8 +395,7 @@ class SettingsFragment : AppFragment() {
|
||||
viewModel.nukeEverything()
|
||||
showToast(context, "Nuked everything")
|
||||
}
|
||||
else -> context.theme.showSnackBar(
|
||||
binding.coordinatorLayout,
|
||||
else -> showSnackBar(
|
||||
getString(R.string.settings_dev_codes_invalid)
|
||||
)
|
||||
}
|
||||
@@ -418,6 +415,15 @@ class SettingsFragment : AppFragment() {
|
||||
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(link)))
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and shows a snack bar.
|
||||
*
|
||||
* @param text content to display in the snack bar
|
||||
*/
|
||||
fun showSnackBar(text: String) {
|
||||
context.theme.showSnackBar(binding.coordinatorLayout, text)
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes Base64 to a regular string.
|
||||
*
|
||||
|
||||
@@ -4,10 +4,11 @@ import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.fragment.app.setFragmentResult
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.navigation.fragment.NavHostFragment
|
||||
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.fragment.SettingsFragment
|
||||
import com.denizk0461.weserplaner.model.AllergenPreferences
|
||||
import com.denizk0461.weserplaner.viewmodel.AllergenConfigViewModel
|
||||
|
||||
@@ -26,6 +27,17 @@ class AllergenConfigSheet : AppSheet(R.layout.sheet_allergen_config) {
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
// Set up FAB behaviour for parent fragment's FAB if activity is not null
|
||||
val parentFragment = activity?.let { activity ->
|
||||
// Retrieve parent fragment to access its functions
|
||||
val navHostFragment = activity
|
||||
.supportFragmentManager
|
||||
.fragments[0] as NavHostFragment
|
||||
navHostFragment
|
||||
.childFragmentManager
|
||||
.primaryNavigationFragment as SettingsFragment
|
||||
}
|
||||
|
||||
// Retrieve allergens as currently set by the user from view model
|
||||
val currentAllergenConfig = AllergenPreferences.construct(
|
||||
viewModel.preferenceAllergenConfig
|
||||
@@ -73,7 +85,7 @@ class AllergenConfigSheet : AppSheet(R.layout.sheet_allergen_config) {
|
||||
parentFragment?.setFragmentResult("allergenConfig", Bundle())
|
||||
|
||||
// Tell the user that saving was successful
|
||||
showToast(context, getString(R.string.allergens_config_confirmation))
|
||||
parentFragment?.showSnackBar(getString(R.string.allergens_config_confirmation))
|
||||
|
||||
// Close the sheet
|
||||
dismiss()
|
||||
|
||||
@@ -84,20 +84,28 @@ class AllergenSheet : AppSheet(R.layout.sheet_allergen) {
|
||||
}
|
||||
}
|
||||
|
||||
// Allergen and additive notice
|
||||
// textContent.text = offer.allergens.compileAllergenString()
|
||||
val (a, b) = offer.allergens.compileStrings()
|
||||
// Retrieve allergen and additive strings
|
||||
val (allergens, additives) = offer.allergens.compileStrings()
|
||||
|
||||
if (a.isBlank() && b.isBlank()) {
|
||||
// Display notices for allergens and additives, if necessary
|
||||
if (allergens.isBlank() && additives.isBlank()) {
|
||||
// Tell the user that no allergens and no additives are present in the offer
|
||||
textAllergensTitle.text = getString(R.string.allergens_none)
|
||||
textAllergensContent.visibility = View.GONE
|
||||
textAdditivesTitle.visibility = View.GONE
|
||||
textAdditivesContent.visibility = View.GONE
|
||||
} else {
|
||||
// Set allergen and additives accordingly if any are present
|
||||
textAllergensTitle.text = getString(R.string.allergens_allergens_title)
|
||||
textAllergensContent.text = getString(R.string.allergens_content_template, a)
|
||||
textAllergensContent.text = getString(
|
||||
R.string.allergens_content_template,
|
||||
allergens,
|
||||
)
|
||||
textAdditivesTitle.text = getString(R.string.allergens_additives_title)
|
||||
textAdditivesContent.text = getString(R.string.allergens_content_template, b)
|
||||
textAdditivesContent.text = getString(
|
||||
R.string.allergens_content_template,
|
||||
additives,
|
||||
)
|
||||
}
|
||||
|
||||
// Show a price, if one is available
|
||||
@@ -124,22 +132,23 @@ class AllergenSheet : AppSheet(R.layout.sheet_allergen) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves localised strings for all allergens present in a given offer and compiles them into
|
||||
* a human-readable string, if any allergens are present.
|
||||
* Retrieves localised strings for all allergens and additives present in a given offer and
|
||||
* compiles them into human-readable strings, if any are present.
|
||||
*
|
||||
* @return a string of all allergens
|
||||
* @receiver string to parse allergens and additives from
|
||||
* @return allergens and additives formatted as strings
|
||||
*/
|
||||
private fun String.compileStrings(): Pair<String, String> {
|
||||
|
||||
// Let the user know if no allergens are present
|
||||
// Return empty values if the received string is blank
|
||||
if (this.isBlank()) return Pair("", "")
|
||||
|
||||
// Stores all localised additives
|
||||
val additiveList = mutableListOf<String>()
|
||||
|
||||
// Stores all localised allergens
|
||||
val allergenList = mutableListOf<String>()
|
||||
|
||||
// Stores all localised additives
|
||||
val additiveList = mutableListOf<String>()
|
||||
|
||||
// Split all allergens to iterate through them
|
||||
val allergens = this.replace(" ", "").split(",")
|
||||
|
||||
@@ -156,16 +165,10 @@ class AllergenSheet : AppSheet(R.layout.sheet_allergen) {
|
||||
}
|
||||
}
|
||||
|
||||
// Insert the items into a template string
|
||||
// return getString(
|
||||
// R.string.allergens_contains,
|
||||
// allergenList.joinToString(", ").ifBlank {
|
||||
// getString(R.string.allergens_single_none)
|
||||
// },
|
||||
// additiveList.joinToString(", ").ifBlank {
|
||||
// getString(R.string.allergens_single_none)
|
||||
// },
|
||||
// )
|
||||
/*
|
||||
* Join the lists to formatted strings, separated by commas. Put a localised "none" if
|
||||
* either no allergens or additives could be found respectively.
|
||||
*/
|
||||
return Pair(
|
||||
allergenList.joinToString(", ").ifBlank {
|
||||
getString(R.string.allergens_single_none)
|
||||
|
||||
@@ -6,6 +6,7 @@ import android.view.ViewGroup
|
||||
import androidx.appcompat.widget.PopupMenu
|
||||
import androidx.core.widget.addTextChangedListener
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.navigation.fragment.NavHostFragment
|
||||
import androidx.transition.TransitionManager
|
||||
import com.denizk0461.weserplaner.R
|
||||
import com.denizk0461.weserplaner.data.getParcelableCompat
|
||||
@@ -18,6 +19,7 @@ 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.fragment.EventFragment
|
||||
import com.denizk0461.weserplaner.model.StudIPEvent
|
||||
import com.denizk0461.weserplaner.viewmodel.ScheduleUpdateViewModel
|
||||
import com.google.android.material.timepicker.MaterialTimePicker
|
||||
@@ -51,6 +53,17 @@ class ScheduleUpdateSheet : AppSheet(R.layout.sheet_schedule_update) {
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
// Set up FAB behaviour for parent fragment's FAB if activity is not null
|
||||
val parentFragment = activity?.let { activity ->
|
||||
// Retrieve parent fragment to access its functions
|
||||
val navHostFragment = activity
|
||||
.supportFragmentManager
|
||||
.fragments[0] as NavHostFragment
|
||||
navHostFragment
|
||||
.childFragmentManager
|
||||
.primaryNavigationFragment as EventFragment
|
||||
}
|
||||
|
||||
if (arguments?.getBoolean("isEditing") == true) {
|
||||
|
||||
try {
|
||||
@@ -88,7 +101,15 @@ class ScheduleUpdateSheet : AppSheet(R.layout.sheet_schedule_update) {
|
||||
* accidentally deleting an event.
|
||||
*/
|
||||
if (hasClickedDelete) {
|
||||
|
||||
// Delete the event
|
||||
viewModel.delete(event)
|
||||
|
||||
// Tell the user that the event has been deleted
|
||||
parentFragment?.showSnackBar(
|
||||
getString(R.string.sheet_schedule_snack_delete)
|
||||
)
|
||||
|
||||
// Dismiss the sheet upon deletion
|
||||
dismiss()
|
||||
} else {
|
||||
@@ -133,6 +154,12 @@ class ScheduleUpdateSheet : AppSheet(R.layout.sheet_schedule_update) {
|
||||
colour = colour,
|
||||
)
|
||||
)
|
||||
|
||||
// Tell the user that the event has been updated
|
||||
parentFragment?.showSnackBar(
|
||||
getString(R.string.sheet_schedule_snack_update)
|
||||
)
|
||||
|
||||
// Dismiss the sheet upon update
|
||||
dismiss()
|
||||
}
|
||||
@@ -188,6 +215,11 @@ class ScheduleUpdateSheet : AppSheet(R.layout.sheet_schedule_update) {
|
||||
)
|
||||
)
|
||||
|
||||
// Tell the user that the event has been updated
|
||||
parentFragment?.showSnackBar(
|
||||
getString(R.string.sheet_schedule_snack_add)
|
||||
)
|
||||
|
||||
// Dismiss the sheet upon update
|
||||
dismiss()
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<vector android:height="24dp" android:tint="#000000"
|
||||
<vector android:height="24dp" android:tint="?attr/colorOnSurfaceVariant"
|
||||
android:viewportHeight="24" android:viewportWidth="24"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="@android:color/white" android:pathData="M16.24,11.51l1.57,-1.57l-3.75,-3.75l-1.57,1.57L8.35,3.63c-0.78,-0.78 -2.05,-0.78 -2.83,0l-1.9,1.9c-0.78,0.78 -0.78,2.05 0,2.83l4.13,4.13L3,17.25V21h3.75l4.76,-4.76l4.13,4.13c0.95,0.95 2.23,0.6 2.83,0l1.9,-1.9c0.78,-0.78 0.78,-2.05 0,-2.83L16.24,11.51zM9.18,11.07L5.04,6.94l1.89,-1.9c0,0 0,0 0,0l1.27,1.27L7.02,7.5l1.41,1.41l1.19,-1.19l1.45,1.45L9.18,11.07zM17.06,18.96l-4.13,-4.13l1.9,-1.9l1.45,1.45l-1.19,1.19l1.41,1.41l1.19,-1.19l1.27,1.27L17.06,18.96z"/>
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
<vector android:height="24dp" android:tint="#000000"
|
||||
android:viewportHeight="24" android:viewportWidth="24"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="@android:color/white" android:pathData="M12.126,8.125l1.937,-1.937 3.747,3.747 -1.937,1.938zM20.71,5.63l-2.34,-2.34a1,1 0,0 0,-1.41 0l-1.83,1.83 3.75,3.75L20.71,7a1,1 0,0 0,0 -1.37zM2,5l6.63,6.63L3,17.25V21h3.75l5.63,-5.62L18,21l2,-2L4,3 2,5z"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,5 @@
|
||||
<vector android:height="24dp" android:tint="#000000"
|
||||
android:viewportHeight="24" android:viewportWidth="24"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="@android:color/white" android:pathData="M12,7c2.76,0 5,2.24 5,5 0,0.65 -0.13,1.26 -0.36,1.83l2.92,2.92c1.51,-1.26 2.7,-2.89 3.43,-4.75 -1.73,-4.39 -6,-7.5 -11,-7.5 -1.4,0 -2.74,0.25 -3.98,0.7l2.16,2.16C10.74,7.13 11.35,7 12,7zM2,4.27l2.28,2.28 0.46,0.46C3.08,8.3 1.78,10.02 1,12c1.73,4.39 6,7.5 11,7.5 1.55,0 3.03,-0.3 4.38,-0.84l0.42,0.42L19.73,22 21,20.73 3.27,3 2,4.27zM7.53,9.8l1.55,1.55c-0.05,0.21 -0.08,0.43 -0.08,0.65 0,1.66 1.34,3 3,3 0.22,0 0.44,-0.03 0.65,-0.08l1.55,1.55c-0.67,0.33 -1.41,0.53 -2.2,0.53 -2.76,0 -5,-2.24 -5,-5 0,-0.79 0.2,-1.53 0.53,-2.2zM11.84,9.02l3.15,3.15 0.02,-0.16c0,-1.66 -1.34,-3 -3,-3l-0.17,0.01z"/>
|
||||
</vector>
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/root_view"
|
||||
android:id="@+id/coordinator_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:animateLayoutChanges="true">
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/coordinator_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".fragment.EventFragment">
|
||||
|
||||
@@ -47,10 +47,27 @@
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_difference"
|
||||
<androidx.appcompat.widget.LinearLayoutCompat
|
||||
android:id="@+id/difference_container"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"/>
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginTop="4dp">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
android:layout_marginHorizontal="4dp"
|
||||
android:scaleType="centerInside"
|
||||
app:tint="?attr/colorText"
|
||||
android:src="@drawable/visibility_off"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_difference"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"/>
|
||||
|
||||
</androidx.appcompat.widget.LinearLayoutCompat>
|
||||
|
||||
</androidx.appcompat.widget.LinearLayoutCompat>
|
||||
@@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.appcompat.widget.LinearLayoutCompat
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:paddingHorizontal="8dp"
|
||||
android:paddingVertical="4dp"
|
||||
android:orientation="vertical">
|
||||
@@ -55,4 +55,28 @@
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<androidx.appcompat.widget.LinearLayoutCompat
|
||||
android:id="@+id/no_events_container"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginTop="4dp">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
android:layout_marginHorizontal="4dp"
|
||||
android:scaleType="centerInside"
|
||||
app:tint="?attr/colorText"
|
||||
android:src="@drawable/edit_off"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_no_events"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:text="@string/schedule_no_events"/>
|
||||
|
||||
</androidx.appcompat.widget.LinearLayoutCompat>
|
||||
|
||||
</androidx.appcompat.widget.LinearLayoutCompat>
|
||||
@@ -4,19 +4,25 @@
|
||||
<item
|
||||
android:id="@+id/close"
|
||||
android:icon="@drawable/cross"
|
||||
android:title="@string/fetch_bar_close_title"
|
||||
android:title="@string/fetch_bar_close_desc"
|
||||
android:contentDescription="@string/fetch_bar_close_desc"
|
||||
app:showAsAction="ifRoom"/>
|
||||
app:showAsAction="always"/>
|
||||
<item
|
||||
android:id="@+id/refresh"
|
||||
android:icon="@drawable/refresh"
|
||||
android:title="@string/fetch_bar_refresh_title"
|
||||
android:title="@string/fetch_bar_refresh_desc"
|
||||
android:contentDescription="@string/fetch_bar_refresh_desc"
|
||||
app:showAsAction="ifRoom"/>
|
||||
app:showAsAction="always"/>
|
||||
<item
|
||||
android:id="@+id/help"
|
||||
android:icon="@drawable/info"
|
||||
android:title="@string/fetch_bar_help_title"
|
||||
android:title="@string/fetch_bar_help_desc"
|
||||
android:contentDescription="@string/fetch_bar_help_desc"
|
||||
app:showAsAction="ifRoom"/>
|
||||
app:showAsAction="always"/>
|
||||
<item
|
||||
android:id="@+id/schedule"
|
||||
android:icon="@drawable/design"
|
||||
android:title="@string/fetch_bar_schedule_desc"
|
||||
android:contentDescription="@string/fetch_bar_schedule_desc"
|
||||
app:showAsAction="always"/>
|
||||
</menu>
|
||||
@@ -34,24 +34,30 @@
|
||||
<string name="toast_fetch_finished_one">Dein Stundenplan wurde aktualisiert, doch eine Veranstaltung konnte nicht heruntergeladen werden.</string>
|
||||
<string name="toast_fetch_finished_other">Dein Stundenplan wurde aktualisiert, doch %d Veranstaltungen konnten nicht heruntergeladen werden.</string>
|
||||
|
||||
<string name="toast_info_reminder">Klick\' das Info-Icon unten, falls du Hilfe benötigst.</string>
|
||||
<string name="fetch_snack_info_reminder">Klick\' das Info-Icon unten, falls du Hilfe benötigst.</string>
|
||||
<string name="fetch_bar_close_title">Schließen</string>
|
||||
<string name="fetch_bar_close_desc">Schließe die Webseite, ohne etwas zu speichern</string>
|
||||
<string name="fetch_bar_refresh_title">Aktualisieren</string>
|
||||
<string name="fetch_bar_refresh_desc">Aktualisiere die Webseite</string>
|
||||
<string name="fetch_bar_help_title">Hilfe</string>
|
||||
<string name="fetch_bar_help_desc">Zeige Hilfe</string>
|
||||
<string name="fetch_bar_schedule_title">Stundenplan</string>
|
||||
<string name="fetch_bar_schedule_desc">Gehe zu deinem Stundenplan</string>
|
||||
<string name="fetch_bar_help_sheet_title">Wie du deinen Stundenplan in der App speichern kannst</string>
|
||||
<string name="fetch_bar_help_sheet_content"> • Logge dich mit deinem Stud.IP-Login ein\n • Öffne deinen Stundenplan (falls er sich nicht automatisch öffnet)\n • Klicke auf den \'Speichern\'-Knopf, der unten in der rechten Ecke auftauchen sollte\n • Fertig!</string>
|
||||
<string name="fetch_bar_help_sheet_content"> • Logge dich mit deinem Stud.IP-Login ein\n • Öffne deinen Stundenplan, falls er sich nicht automatisch öffnet, indem du in der unteren Leiste auf das rechte Logo klickst, das wie ein Stift und ein Lineal aussieht\n • Klicke auf den \'Speichern\'-Knopf, der unten in der rechten Ecke auftaucht\n • Fertig!</string>
|
||||
<string name="fetch_bar_save_desc">Speichere den Stundenplan in der App ab</string>
|
||||
|
||||
<string name="schedule_fab_add_text">Neue Veranstaltung</string>
|
||||
<string name="schedule_no_events">%ss hast du keine Veranstaltungen.</string>
|
||||
|
||||
<string name="save">Speichern</string>
|
||||
<string name="delete">Löschen</string>
|
||||
<string name="sheet_schedule_update_delete_confirm">Sicher?</string>
|
||||
<string name="cancel">Abbrechen</string>
|
||||
<string name="confirm">Bestätigen</string>
|
||||
<string name="sheet_schedule_snack_delete">Veranstaltung wurde gelöscht.</string>
|
||||
<string name="sheet_schedule_snack_add">Veranstaltung wurde hinzugefügt.</string>
|
||||
<string name="sheet_schedule_snack_update">Veranstaltung wurde aktualisiert.</string>
|
||||
<string name="sheet_schedule_update_header_edit">Bestehende Veranstaltung bearbeiten</string>
|
||||
<string name="sheet_schedule_update_header_add">Neue Veranstaltung hinzufügen</string>
|
||||
<string name="sheet_schedule_update_title_hint">Veranstaltungstitel</string>
|
||||
|
||||
@@ -35,24 +35,30 @@
|
||||
<string name="toast_fetch_finished_one">Your schedule has been refreshed, but one item could not be saved.</string>
|
||||
<string name="toast_fetch_finished_other">Your schedule has been refreshed, but %d items could not be saved.</string>
|
||||
|
||||
<string name="toast_info_reminder">Click the info icon at the bottom if you need any help here.</string>
|
||||
<string name="fetch_snack_info_reminder">Click the info icon at the bottom if you need any help here.</string>
|
||||
<string name="fetch_bar_close_title">Close</string>
|
||||
<string name="fetch_bar_close_desc">Close the website without saving anything</string>
|
||||
<string name="fetch_bar_refresh_title">Refresh</string>
|
||||
<string name="fetch_bar_refresh_desc">Refresh the page</string>
|
||||
<string name="fetch_bar_help_title">Help</string>
|
||||
<string name="fetch_bar_help_desc">Show help</string>
|
||||
<string name="fetch_bar_schedule_title">Schedule</string>
|
||||
<string name="fetch_bar_schedule_desc">Go to your schedule</string>
|
||||
<string name="fetch_bar_help_sheet_title">How to save your timetable in the app</string>
|
||||
<string name="fetch_bar_help_sheet_content"> • Log in with your Stud.IP login\n • Open your timetable view (in case it doesn\'t open automatically)\n • Click the \'save\' button that should appear in the bottom right corner\n • Done!</string>
|
||||
<string name="fetch_bar_help_sheet_content"> • Log in with your Stud.IP login\n • Open your timetable view, in case it doesn\'t open automatically, by clicking the rightmost icon in the bottom bar that looks like a pencil and a ruler\n • Click the \'save\' button that appears in the bottom right corner\n • Done!</string>
|
||||
<string name="fetch_bar_save_desc">Save the timetable in the app</string>
|
||||
|
||||
<string name="schedule_fab_add_text">New event</string>
|
||||
<string name="schedule_no_events">You don\'t have any events for %s.</string>
|
||||
|
||||
<string name="save">Save</string>
|
||||
<string name="delete">Delete</string>
|
||||
<string name="sheet_schedule_update_delete_confirm">Sure?</string>
|
||||
<string name="cancel">Cancel</string>
|
||||
<string name="confirm">Confirm</string>
|
||||
<string name="sheet_schedule_snack_delete">Event has been deleted.</string>
|
||||
<string name="sheet_schedule_snack_add">Event has been added.</string>
|
||||
<string name="sheet_schedule_snack_update">Event has been updated.</string>
|
||||
<string name="sheet_schedule_update_header_edit">Edit existing event</string>
|
||||
<string name="sheet_schedule_update_header_add">Add new event</string>
|
||||
<string name="sheet_schedule_update_title_hint">Event title</string>
|
||||
|
||||
Reference in New Issue
Block a user