Archived
Timetables can now be edited and deleted via sheet from SettingsFragment.kt
This commit is contained in:
@@ -6,12 +6,12 @@ plugins {
|
||||
|
||||
android {
|
||||
namespace = "com.denizk0461.weserplaner"
|
||||
compileSdk = 33
|
||||
compileSdk = 34
|
||||
|
||||
defaultConfig {
|
||||
applicationId = "com.denizk0461.weserplaner"
|
||||
minSdk = 24
|
||||
targetSdk = 33
|
||||
targetSdk = 34
|
||||
versionCode = 9
|
||||
versionName = "1.2.0"
|
||||
|
||||
|
||||
@@ -87,6 +87,15 @@ interface AppDAO {
|
||||
@Query("SELECT * FROM timetables ORDER BY id")
|
||||
fun getTimetables(): LiveData<List<Timetable>>
|
||||
|
||||
@Query("SELECT * FROM timetables WHERE id = :id LIMIT 1")
|
||||
fun getTimetableForId(id: Int): Timetable
|
||||
|
||||
@Update
|
||||
fun updateTimetable(timetable: Timetable)
|
||||
|
||||
@Query("DELETE FROM timetables WHERE id = :id")
|
||||
fun deleteTimetable(id: Int)
|
||||
|
||||
/* --- event tasks --- */
|
||||
|
||||
/**
|
||||
|
||||
@@ -81,7 +81,7 @@ class AppRepository(app: Application) {
|
||||
fun getEventsForDay(day: Int): LiveData<List<StudIPEvent>> = dao.getEventsForDay(day)
|
||||
|
||||
fun getEventsForDayAndTimetable(day: Int, timetable: Int): LiveData<List<StudIPEvent>> =
|
||||
dao.getEventsForDayAndTimetable(day, timetable + 1) // I'm not sure why I need +1 here but it works
|
||||
dao.getEventsForDayAndTimetable(day, timetable)
|
||||
|
||||
/**
|
||||
* Inserts a list of Stud.IP events into the database.
|
||||
@@ -166,10 +166,16 @@ class AppRepository(app: Application) {
|
||||
dao.insertTimetable(timetable)
|
||||
}
|
||||
|
||||
fun updateTimetable(timetable: Timetable) { dao.updateTimetable(timetable) }
|
||||
|
||||
fun getLargestTimetableId(): Int = dao.getLargestTimetableId() ?: 0
|
||||
|
||||
fun getTimetables(): LiveData<List<Timetable>> = dao.getTimetables()
|
||||
|
||||
fun getTimetableForId(id: Int): Timetable = dao.getTimetableForId(id)
|
||||
|
||||
fun deleteTimetable(id: Int) { dao.deleteTimetable(id) }
|
||||
|
||||
/**
|
||||
* Retrieves all canteen offer date objects.
|
||||
*
|
||||
|
||||
@@ -20,11 +20,14 @@ import com.denizk0461.weserplaner.activity.FetcherActivity
|
||||
import com.denizk0461.weserplaner.activity.ImageActivity
|
||||
import com.denizk0461.weserplaner.adapter.DropdownAdapter
|
||||
import com.denizk0461.weserplaner.data.getTextSheet
|
||||
import com.denizk0461.weserplaner.data.showErrorSnackBar
|
||||
import com.denizk0461.weserplaner.data.showSnackBar
|
||||
import com.denizk0461.weserplaner.data.showToast
|
||||
import com.denizk0461.weserplaner.databinding.FragmentSettingsBinding
|
||||
import com.denizk0461.weserplaner.model.FormattedDate
|
||||
import com.denizk0461.weserplaner.model.Timetable
|
||||
import com.denizk0461.weserplaner.sheet.AllergenConfigSheet
|
||||
import com.denizk0461.weserplaner.sheet.TimetableEditSheet
|
||||
import com.denizk0461.weserplaner.values.AppLayout
|
||||
import com.denizk0461.weserplaner.viewmodel.SettingsViewModel
|
||||
import java.nio.charset.StandardCharsets
|
||||
@@ -52,6 +55,8 @@ class SettingsFragment : AppFragment<FragmentSettingsBinding>() {
|
||||
|
||||
private lateinit var timetableAdapter: DropdownAdapter
|
||||
|
||||
private var savedTimetables: List<Timetable> = listOf()
|
||||
|
||||
// Instantiate the view binding
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
||||
_binding = FragmentSettingsBinding.inflate(inflater, container, false)
|
||||
@@ -92,18 +97,36 @@ class SettingsFragment : AppFragment<FragmentSettingsBinding>() {
|
||||
timetableAdapter.addAll(timetables.map { it.name })
|
||||
if (timetables.isNotEmpty()) {
|
||||
binding.autoCompleteTimetable.setText(
|
||||
timetableAdapter.getItem(viewModel.getSelectedTimetable()).toString(),
|
||||
timetableAdapter.getItem(timetables.map { it.id }.indexOf(viewModel.getSelectedTimetable())).toString(),//viewModel.getSelectedTimetable()).toString(),
|
||||
false,
|
||||
)
|
||||
} else {
|
||||
binding.autoCompleteTimetable.setText("")
|
||||
}
|
||||
savedTimetables = timetables
|
||||
}
|
||||
|
||||
binding.autoCompleteTimetable.setAdapter(timetableAdapter)
|
||||
binding.autoCompleteTimetable.setOnItemClickListener { _, _, position, _ ->
|
||||
viewModel.setSelectedTimetable(position)
|
||||
viewModel.setSelectedTimetable(savedTimetables[position].id)
|
||||
binding.autoCompleteTimetable.setText(timetableAdapter.getItem(position), false)
|
||||
}
|
||||
|
||||
binding.buttonEditTimetable.setOnClickListener {
|
||||
if (binding.autoCompleteTimetable.text.isBlank()) {
|
||||
context.theme.showErrorSnackBar(
|
||||
binding.coordinatorLayout,
|
||||
getString(R.string.settings_timetable_edit_fail),
|
||||
)
|
||||
} else {
|
||||
openBottomSheet(TimetableEditSheet().also { sheet ->
|
||||
val bundle = Bundle()
|
||||
bundle.putInt("timetableId", viewModel.getSelectedTimetable())
|
||||
sheet.arguments = bundle
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Set up switch for highlighting the next course in the schedule
|
||||
binding.switchCurrentDay.apply {
|
||||
isChecked = viewModel.preferenceCurrentDay
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
package com.denizk0461.weserplaner.sheet
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.navigation.fragment.NavHostFragment
|
||||
import androidx.transition.TransitionManager
|
||||
import com.denizk0461.weserplaner.R
|
||||
import com.denizk0461.weserplaner.data.viewBinding
|
||||
import com.denizk0461.weserplaner.databinding.SheetTimetableEditBinding
|
||||
import com.denizk0461.weserplaner.fragment.SettingsFragment
|
||||
import com.denizk0461.weserplaner.model.Timetable
|
||||
import com.denizk0461.weserplaner.viewmodel.SheetTimetableEditViewModel
|
||||
import java.io.IOException
|
||||
|
||||
class TimetableEditSheet : AppSheet(R.layout.sheet_timetable_edit) {
|
||||
|
||||
// View binding
|
||||
private val binding: SheetTimetableEditBinding by viewBinding(SheetTimetableEditBinding::bind)
|
||||
|
||||
// View model
|
||||
private val viewModel: SheetTimetableEditViewModel by viewModels()
|
||||
|
||||
private var hasClickedDelete = false
|
||||
|
||||
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 event from arguments
|
||||
val timetableId = arguments?.getInt("timetableId") ?: throw IOException("asdf wtf?") // TODO better error handling
|
||||
|
||||
val timetable = viewModel.getTimetableForId(timetableId)
|
||||
|
||||
binding.editTextTitle.setText(timetable.name)
|
||||
|
||||
binding.buttonCancel.setOnClickListener {
|
||||
dismiss()
|
||||
}
|
||||
|
||||
binding.buttonDelete.setOnClickListener {
|
||||
/*
|
||||
* Check if the user has already clicked the button before; this is done to prevent
|
||||
* accidentally deleting an event.
|
||||
*/
|
||||
if (hasClickedDelete) {
|
||||
viewModel.setSelectedTimetable(viewModel.getLargestTimetableId())
|
||||
|
||||
viewModel.deleteTimetable(timetableId)
|
||||
|
||||
// Tell the user that the event has been deleted
|
||||
parentFragment?.showSnackBar(
|
||||
getString(R.string.settings_timetable_sheet_confirm_delete)
|
||||
)
|
||||
|
||||
// Dismiss the sheet upon deletion
|
||||
dismiss()
|
||||
} else {
|
||||
// Update the text to show the user that they clicked the button once
|
||||
TransitionManager
|
||||
.beginDelayedTransition(binding.buttonContainer as ViewGroup)
|
||||
binding.buttonDelete.text =
|
||||
getString(R.string.settings_timetable_sheet_delete_confirm)
|
||||
hasClickedDelete = true
|
||||
}
|
||||
}
|
||||
|
||||
binding.buttonSave.setOnClickListener {
|
||||
viewModel.updateTimetable(Timetable(timetableId, binding.editTextTitle.text.toString().trim()))
|
||||
|
||||
// Tell the user that the event has been updated
|
||||
parentFragment?.showSnackBar(
|
||||
getString(R.string.settings_timetable_sheet_confirm_save)
|
||||
)
|
||||
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.denizk0461.weserplaner.viewmodel
|
||||
|
||||
import android.app.Application
|
||||
import com.denizk0461.weserplaner.model.Timetable
|
||||
|
||||
class SheetTimetableEditViewModel(application: Application) : AppViewModel(application) {
|
||||
|
||||
fun getTimetableForId(id: Int) = returnBlocking { repo.getTimetableForId(id) }
|
||||
|
||||
fun updateTimetable(timetable: Timetable) { doAsync { repo.updateTimetable(timetable) } }
|
||||
|
||||
fun deleteTimetable(id: Int) = doAsync { repo.deleteTimetable(id) }
|
||||
|
||||
fun setSelectedTimetable(newValue: Int) = repo.setPreferenceSelectedTimetable(newValue)
|
||||
|
||||
fun getLargestTimetableId(): Int = returnBlocking { repo.getLargestTimetableId() }
|
||||
}
|
||||
@@ -90,6 +90,7 @@ xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_marginBottom="24dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"/>
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:strokeColor="?attr/colorOutlineVariant"/>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -133,7 +133,6 @@
|
||||
<androidx.appcompat.widget.LinearLayoutCompat
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:orientation="vertical"
|
||||
android:paddingHorizontal="16dp"
|
||||
android:paddingVertical="8dp">
|
||||
@@ -145,23 +144,45 @@
|
||||
android:text="@string/settings_selected_timetable_header"
|
||||
android:textSize="16sp" />
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/text_layout_timetable"
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.ExposedDropdownMenu"
|
||||
<androidx.appcompat.widget.LinearLayoutCompat
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/settings_selected_timetable_hint"
|
||||
app:boxStrokeColor="@color/selector_text_input"
|
||||
app:hintTextColor="@color/selector_text_input">
|
||||
android:orientation="horizontal">
|
||||
|
||||
<com.google.android.material.textfield.MaterialAutoCompleteTextView
|
||||
android:id="@+id/auto_complete_timetable"
|
||||
android:layout_width="match_parent"
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/text_layout_timetable"
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.ExposedDropdownMenu"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="?attr/colorOnSurfaceVariant"
|
||||
android:inputType="none"/>
|
||||
android:layout_weight="1"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:hint="@string/settings_selected_timetable_hint"
|
||||
app:boxStrokeColor="@color/selector_text_input"
|
||||
app:hintTextColor="@color/selector_text_input">
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
<com.google.android.material.textfield.MaterialAutoCompleteTextView
|
||||
android:id="@+id/auto_complete_timetable"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="?attr/colorOnSurfaceVariant"
|
||||
android:inputType="none"/>
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
style="@style/Widget.Material3.Button.IconButton.Outlined"
|
||||
android:id="@+id/button_edit_timetable"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:minWidth="0dp"
|
||||
app:icon="@drawable/edit"
|
||||
app:iconPadding="0dp"
|
||||
app:strokeColor="?attr/colorOutlineVariant"
|
||||
app:iconTint="?attr/colorOnSurfaceVariant"
|
||||
tools:ignore="UnusedAttribute"
|
||||
android:tooltipText="@string/settings_selected_timetable_edit_button_hint"/>
|
||||
|
||||
</androidx.appcompat.widget.LinearLayoutCompat>
|
||||
|
||||
</androidx.appcompat.widget.LinearLayoutCompat>
|
||||
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/sheet"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.google.android.material.bottomsheet.BottomSheetDragHandleView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"/>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
style="@style/SheetCloseButton"
|
||||
android:id="@+id/button_cancel"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/sheet_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="22sp"
|
||||
android:paddingHorizontal="24dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
app:fontFamily="@font/lato_blackitalic"
|
||||
android:text="@string/settings_timetable_sheet_header"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/button_cancel"/>
|
||||
|
||||
<androidx.core.widget.NestedScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:scrollbars="vertical">
|
||||
|
||||
<androidx.appcompat.widget.LinearLayoutCompat
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:paddingBottom="16dp"
|
||||
android:paddingHorizontal="24dp">
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||
android:id="@+id/text_layout_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:hint="@string/settings_selected_timetable_hint"
|
||||
app:boxStrokeColor="@color/selector_text_input"
|
||||
app:hintTextColor="@color/selector_text_input">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
style="@style/ThemeOverlay.Material3.TextInputEditText.OutlinedBox"
|
||||
android:textColor="?attr/colorOnSurfaceVariant"
|
||||
android:id="@+id/edit_text_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<androidx.appcompat.widget.LinearLayoutCompat
|
||||
android:id="@+id/button_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="end"
|
||||
android:layout_marginVertical="8dp"
|
||||
android:animateLayoutChanges="true">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/button_delete"
|
||||
style="@style/Widget.Material3.Button.OutlinedButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:text="@string/delete"
|
||||
app:icon="@drawable/delete"
|
||||
app:strokeColor="?attr/colorOutlineVariant"/>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/button_save"
|
||||
style="@style/Widget.Material3.Button.TonalButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/save"
|
||||
app:icon="@drawable/save"/>
|
||||
|
||||
</androidx.appcompat.widget.LinearLayoutCompat>
|
||||
|
||||
</androidx.appcompat.widget.LinearLayoutCompat>
|
||||
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
</androidx.appcompat.widget.LinearLayoutCompat>
|
||||
@@ -248,6 +248,12 @@
|
||||
|
||||
<string name="settings_selected_timetable_header">Wähle, welchen Stundenplan einzusehen</string>
|
||||
<string name="settings_selected_timetable_hint">Stundenplan</string>
|
||||
<string name="settings_selected_timetable_edit_button_hint">Stundenplan bearbeiten</string>
|
||||
<string name="settings_timetable_sheet_header">Diesen Stundenplan bearbeiten</string>
|
||||
<string name="settings_timetable_edit_fail">Es gibt keinen Stundenplan zum bearbeiten!</string>
|
||||
<string name="settings_timetable_sheet_confirm_save">Stundenplan wurde aktualisiert.</string>
|
||||
<string name="settings_timetable_sheet_confirm_delete">Stundenplan wurde gelöscht.</string>
|
||||
<string name="settings_timetable_sheet_delete_confirm">Sicher?</string>
|
||||
|
||||
<string name="settings_current_day_title">Starte Stundenplan am heutigen Tag</string>
|
||||
<string name="settings_current_day_subtitle">Ansonsten wird Montag beim Start angezeigt</string>
|
||||
|
||||
@@ -253,6 +253,12 @@
|
||||
|
||||
<string name="settings_selected_timetable_header">Select which timetable to display</string>
|
||||
<string name="settings_selected_timetable_hint">Timetable</string>
|
||||
<string name="settings_selected_timetable_edit_button_hint">Edit timetable</string>
|
||||
<string name="settings_timetable_sheet_header">Edit this timetable</string>
|
||||
<string name="settings_timetable_edit_fail">There is no timetable to edit!</string>
|
||||
<string name="settings_timetable_sheet_confirm_save">Timetable has been updated.</string>
|
||||
<string name="settings_timetable_sheet_confirm_delete">Timetable has been deleted.</string>
|
||||
<string name="settings_timetable_sheet_delete_confirm">Sure?</string>
|
||||
|
||||
<string name="settings_current_day_title">Launch timetable on current day</string>
|
||||
<string name="settings_current_day_subtitle">If unselected, Monday will be shown on launch instead</string>
|
||||
|
||||
Reference in New Issue
Block a user