Added an options menu for events; moved delete option to the new options menu

This commit is contained in:
denizk0461
2023-05-21 22:16:20 +02:00
parent e99a58de54
commit 75724ace18
15 changed files with 519 additions and 51 deletions
@@ -11,6 +11,7 @@ import com.denizk0461.weserplaner.adapter.StudIPEventPageAdapter
import com.denizk0461.weserplaner.adapter.StudIPEventItemAdapter import com.denizk0461.weserplaner.adapter.StudIPEventItemAdapter
import com.denizk0461.weserplaner.databinding.RecyclerViewBinding import com.denizk0461.weserplaner.databinding.RecyclerViewBinding
import com.denizk0461.weserplaner.model.StudIPEvent import com.denizk0461.weserplaner.model.StudIPEvent
import com.denizk0461.weserplaner.sheet.EventActionSheet
import com.denizk0461.weserplaner.sheet.ScheduleUpdateSheet import com.denizk0461.weserplaner.sheet.ScheduleUpdateSheet
import com.denizk0461.weserplaner.viewmodel.EventPageViewModel import com.denizk0461.weserplaner.viewmodel.EventPageViewModel
@@ -105,8 +106,36 @@ class EventPageFragment : AppFragment<RecyclerViewBinding>(), StudIPEventItemAda
} }
} }
/**
* Creates and shows a snack bar.
*
* @param text content to display in the snack bar
*/
fun showSnackBar(text: String) {
// Retrieve parent fragment
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
}
// Show a snack bar in the parent fragment
parentFragment?.showSnackBar(text)
}
override fun onClick(event: StudIPEvent) { override fun onClick(event: StudIPEvent) {
// TODO implement functionality or delete // Open a bottom sheet to view options for the event
openBottomSheet(
EventActionSheet().also { sheet ->
val bundle = Bundle()
bundle.putParcelable("event", event)
sheet.arguments = bundle
}
)
} }
override fun onLongClick(event: StudIPEvent): Boolean { override fun onLongClick(event: StudIPEvent): Boolean {
@@ -31,4 +31,15 @@ open class AppSheet(@LayoutRes private val layoutId: Int) : BottomSheetDialogFra
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View = override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
LayoutInflater.from(context).inflate(layoutId, container, false) LayoutInflater.from(context).inflate(layoutId, container, false)
/**
* Opens a bottom sheet. Sheet will be attached to the fragment manager of the parent of the
* sheet that's calling this function. Sheet must be a subclass of
* [com.denizk0461.weserplaner.sheet.AppSheet].
*
* @param sheet element that will be displayed
*/
protected fun openBottomSheet(sheet: AppSheet) {
sheet.show(parentFragmentManager, sheet.javaClass.simpleName)
}
} }
@@ -0,0 +1,70 @@
package com.denizk0461.weserplaner.sheet
import android.os.Bundle
import android.view.View
import com.denizk0461.weserplaner.R
import com.denizk0461.weserplaner.data.getParcelableCompat
import com.denizk0461.weserplaner.data.viewBinding
import com.denizk0461.weserplaner.databinding.SheetEventActionBinding
import com.denizk0461.weserplaner.fragment.EventPageFragment
import com.denizk0461.weserplaner.model.StudIPEvent
/**
* Sheet used to display actions available for a given event to the user.
*/
class EventActionSheet : AppSheet(R.layout.sheet_event_action) {
// View binding
private val binding: SheetEventActionBinding by viewBinding(SheetEventActionBinding::bind)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// Retrieve event from arguments
val event = arguments.getParcelableCompat<StudIPEvent>("event")
// Set header text
binding.eventHeader.text = event.title
// Set up dismiss button
binding.buttonDismiss.setOnClickListener {
// Do nothing and dismiss the sheet
dismiss()
}
// Set up button to edit the event
binding.buttonEditEvent.setOnClickListener {
// Open editing sheet
openBottomSheet(
ScheduleUpdateSheet().also { sheet ->
val bundle = Bundle()
bundle.putBoolean("isEditing", true)
bundle.putParcelable("event", event)
sheet.arguments = bundle
}
)
// Close this sheet
dismiss()
}
// Set up button to delete the event
binding.buttonDeleteEvent.setOnClickListener {
// Open deletion confirm sheet
openBottomSheet(
EventConfirmDeletionSheet().also { sheet ->
val bundle = Bundle()
bundle.putParcelable("event", event)
sheet.arguments = bundle
}
)
// Show a snack bar in the parent fragment to tell the user that the action was successful
(parentFragment as EventPageFragment)
.showSnackBar(getString(R.string.sheet_event_confirm_deletion_snack))
// Close this sheet
dismiss()
}
}
}
@@ -0,0 +1,57 @@
package com.denizk0461.weserplaner.sheet
import android.os.Bundle
import android.view.View
import androidx.fragment.app.viewModels
import com.denizk0461.weserplaner.R
import com.denizk0461.weserplaner.data.getParcelableCompat
import com.denizk0461.weserplaner.data.viewBinding
import com.denizk0461.weserplaner.databinding.SheetEventConfirmDeletionBinding
import com.denizk0461.weserplaner.model.StudIPEvent
import com.denizk0461.weserplaner.viewmodel.EventConfirmDeletionViewModel
/**
* Sheet displayed to the user to confirm that they want to delete an event from their timetable.
*/
class EventConfirmDeletionSheet : AppSheet(R.layout.sheet_event_confirm_deletion) {
// View model
private val viewModel: EventConfirmDeletionViewModel by viewModels()
// View binding
private val binding: SheetEventConfirmDeletionBinding by viewBinding(SheetEventConfirmDeletionBinding::bind)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// Retrieve event from arguments
val event = arguments.getParcelableCompat<StudIPEvent>("event")
// Set up dismiss button
binding.buttonDismiss.setOnClickListener {
// Do nothing and dismiss the sheet
dismiss()
}
// Set up button to delete the event
binding.buttonDelete.setOnClickListener {
// Delete the event
viewModel.delete(event)
// Dismiss the sheet
dismiss()
}
// Set up cancel button
binding.buttonCancel.setOnClickListener {
// Do nothing and dismiss the sheet
dismiss()
}
// Set text content with the event's title inserted
binding.textConfirmDeletionContent.text = getString(
R.string.sheet_event_confirm_deletion_content,
event.title,
)
}
}
@@ -41,9 +41,6 @@ class ScheduleUpdateSheet : AppSheet(R.layout.sheet_schedule_update) {
// View model // View model
private val viewModel: ScheduleUpdateViewModel by viewModels() private val viewModel: ScheduleUpdateViewModel by viewModels()
// Whether the user has once clicked the delete button; used to prevent an accidental click
private var hasClickedDelete: Boolean = false
// Determines whether the user is editing an existing event or creating a new one // Determines whether the user is editing an existing event or creating a new one
private var isEditing: Boolean = false private var isEditing: Boolean = false
@@ -94,34 +91,6 @@ class ScheduleUpdateSheet : AppSheet(R.layout.sheet_schedule_update) {
binding.editTextLecturers.setText(event.lecturer) binding.editTextLecturers.setText(event.lecturer)
binding.editTextRoom.setText(event.room) binding.editTextRoom.setText(event.room)
// Prepare delete button
binding.buttonDelete.setOnClickListener {
/*
* Check if the user has already clicked the button before; this is done to prevent
* 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 {
// 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.sheet_schedule_update_delete_confirm)
hasClickedDelete = true
}
}
// Prepare update button // Prepare update button
binding.buttonSave.setOnClickListener { binding.buttonSave.setOnClickListener {
// Check if any of the text fields are empty // Check if any of the text fields are empty
@@ -181,9 +150,6 @@ class ScheduleUpdateSheet : AppSheet(R.layout.sheet_schedule_update) {
// Set the title to reflect that an event is being added // Set the title to reflect that an event is being added
binding.sheetTitle.text = getString(R.string.sheet_schedule_update_header_add) binding.sheetTitle.text = getString(R.string.sheet_schedule_update_header_add)
// Hide delete button, since there is nothing to delete
binding.buttonDelete.visibility = View.GONE
// Prepare save button // Prepare save button
binding.buttonSave.setOnClickListener { binding.buttonSave.setOnClickListener {
// Check if any of the text fields are empty // Check if any of the text fields are empty
@@ -0,0 +1,14 @@
package com.denizk0461.weserplaner.viewmodel
import android.app.Application
import com.denizk0461.weserplaner.model.StudIPEvent
class EventConfirmDeletionViewModel(application: Application) : AppViewModel(application) {
/**
* Deletes a schedule element.
*
* @param event the event to delete
*/
fun delete(event: StudIPEvent) { doAsync { repo.delete(event) } }
}
@@ -18,11 +18,4 @@ class ScheduleUpdateViewModel(application: Application) : AppViewModel(applicati
* @param event the event to update * @param event the event to update
*/ */
fun update(event: StudIPEvent) { doAsync { repo.update(event) } } fun update(event: StudIPEvent) { doAsync { repo.update(event) } }
/**
* Deletes a schedule element.
*
* @param event the event to delete
*/
fun delete(event: StudIPEvent) { doAsync { repo.delete(event) } }
} }
+5
View File
@@ -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="M22,5.18L10.59,16.6l-4.24,-4.24l1.41,-1.41l2.83,2.83l10,-10L22,5.18zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8c1.57,0 3.04,0.46 4.28,1.25l1.45,-1.45C16.1,2.67 14.13,2 12,2C6.48,2 2,6.48 2,12s4.48,10 10,10c1.73,0 3.36,-0.44 4.78,-1.22l-1.5,-1.5C14.28,19.74 13.17,20 12,20zM19,15h-3v2h3v3h2v-3h3v-2h-3v-3h-2V15z"/>
</vector>
+5
View File
@@ -0,0 +1,5 @@
<vector android:autoMirrored="true" 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="M20,11H7.83l5.59,-5.59L12,4l-8,8 8,8 1.41,-1.41L7.83,13H20v-2z"/>
</vector>
+5
View File
@@ -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="M3,17.25V21h3.75L17.81,9.94l-3.75,-3.75L3,17.25zM20.71,7.04c0.39,-0.39 0.39,-1.02 0,-1.41l-2.34,-2.34c-0.39,-0.39 -1.02,-0.39 -1.41,0l-1.83,1.83 3.75,3.75 1.83,-1.83z"/>
</vector>
@@ -0,0 +1,206 @@
<?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:layout_width="match_parent"
android:layout_height="wrap_content"
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_dismiss"
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>
<TextView
android:id="@+id/event_header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="22sp"
android:paddingHorizontal="24dp"
android:layout_marginBottom="8dp"
android:fontFamily="@font/lato_bolditalic"
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">
<!-- Edit event -->
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/button_edit_event"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/selectable_item_background"
android:clickable="true"
android:focusable="true"
android:orientation="horizontal"
android:paddingHorizontal="20dp"
android:paddingVertical="16dp">
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_marginHorizontal="8dp"
android:scaleType="centerInside"
android:tint="?attr/colorText"
android:src="@drawable/edit"
android:importantForAccessibility="no"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/sheet_event_action_edit_event_title"
android:textSize="16sp"/>
</androidx.appcompat.widget.LinearLayoutCompat>
<!-- Add task -->
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/button_add_task"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/selectable_item_background"
android:clickable="true"
android:focusable="true"
android:orientation="horizontal"
android:paddingHorizontal="20dp"
android:paddingVertical="16dp">
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_marginHorizontal="8dp"
android:scaleType="centerInside"
android:tint="?attr/colorText"
android:src="@drawable/add_task"
android:importantForAccessibility="no"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/sheet_event_action_add_task_title"
android:textSize="16sp"/>
</androidx.appcompat.widget.LinearLayoutCompat>
<!-- View tasks -->
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/button_view_tasks"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/selectable_item_background"
android:clickable="true"
android:focusable="true"
android:orientation="horizontal"
android:paddingHorizontal="20dp"
android:paddingVertical="16dp">
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_marginHorizontal="8dp"
android:scaleType="centerInside"
android:tint="?attr/colorText"
android:src="@drawable/task"
android:importantForAccessibility="no"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/sheet_event_action_view_tasks_title"
android:textSize="16sp"/>
</androidx.appcompat.widget.LinearLayoutCompat>
<!-- Find room -->
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/button_find_room"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/selectable_item_background"
android:clickable="true"
android:focusable="true"
android:orientation="horizontal"
android:paddingHorizontal="20dp"
android:paddingVertical="16dp">
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_marginHorizontal="8dp"
android:scaleType="centerInside"
android:tint="?attr/colorText"
android:src="@drawable/location"
android:importantForAccessibility="no"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/sheet_event_action_find_room_title"
android:textSize="16sp"/>
</androidx.appcompat.widget.LinearLayoutCompat>
<!-- Delete event -->
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/button_delete_event"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/selectable_item_background"
android:clickable="true"
android:focusable="true"
android:orientation="horizontal"
android:paddingHorizontal="20dp"
android:paddingVertical="16dp">
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_marginHorizontal="8dp"
android:scaleType="centerInside"
android:tint="?attr/colorError"
android:src="@drawable/delete"
android:importantForAccessibility="no"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/sheet_event_action_delete_event_title"
android:textSize="16sp"
android:textColor="?attr/colorError"/>
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.core.widget.NestedScrollView>
</androidx.appcompat.widget.LinearLayoutCompat>
@@ -0,0 +1,96 @@
<?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_dismiss"
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>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="22sp"
android:paddingHorizontal="24dp"
android:layout_marginBottom="8dp"
android:fontFamily="@font/lato_blackitalic"
android:text="@string/sheet_event_confirm_deletion_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">
<TextView
android:id="@+id/text_confirm_deletion_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="24dp"/>
<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_marginBottom="8dp"
android:animateLayoutChanges="true">
<com.google.android.material.button.MaterialButton
android:id="@+id/button_delete"
style="@style/Widget.Material3.Button.TonalButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/delete"
app:icon="@drawable/delete"
android:layout_marginEnd="8dp"/>
<com.google.android.material.button.MaterialButton
android:id="@+id/button_cancel"
style="@style/Widget.Material3.Button.TonalButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/cancel"
app:icon="@drawable/arrow_back"/>
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.core.widget.NestedScrollView>
</androidx.appcompat.widget.LinearLayoutCompat>
@@ -187,15 +187,6 @@
android:layout_marginBottom="8dp" android:layout_marginBottom="8dp"
android:animateLayoutChanges="true"> android:animateLayoutChanges="true">
<com.google.android.material.button.MaterialButton
android:id="@+id/button_delete"
style="@style/Widget.Material3.Button.TonalButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/delete"
app:icon="@drawable/delete"
android:layout_marginEnd="8dp"/>
<com.google.android.material.button.MaterialButton <com.google.android.material.button.MaterialButton
android:id="@+id/button_save" android:id="@+id/button_save"
style="@style/Widget.Material3.Button.TonalButton" style="@style/Widget.Material3.Button.TonalButton"
+10
View File
@@ -51,6 +51,16 @@
<string name="schedule_fab_add_text">Neue Veranstaltung</string> <string name="schedule_fab_add_text">Neue Veranstaltung</string>
<string name="schedule_no_events">%ss hast du keine Veranstaltungen.</string> <string name="schedule_no_events">%ss hast du keine Veranstaltungen.</string>
<string name="sheet_event_action_edit_event_title">Veranstaltung bearbeiten</string>
<string name="sheet_event_action_add_task_title">Aufgabe oder Prüfung hinzufügen</string>
<string name="sheet_event_action_view_tasks_title">Siehe Aufgaben und Prüfungen für diese Veranstaltung</string>
<string name="sheet_event_action_find_room_title">Raum für diese Veranstaltung finden</string>
<string name="sheet_event_action_delete_event_title">Veranstaltung löschen</string>
<string name="sheet_event_confirm_deletion_header">Bestätige Löschvorgang</string>
<string name="sheet_event_confirm_deletion_content">Bist du dir sicher, dass du diese Veranstaltung \'%s\' löschen möchtest?</string>
<string name="sheet_event_confirm_deletion_snack">Die Veranstaltung wurde gelöscht.</string>
<string name="save">Speichern</string> <string name="save">Speichern</string>
<string name="delete">Löschen</string> <string name="delete">Löschen</string>
<string name="sheet_schedule_update_delete_confirm">Sicher?</string> <string name="sheet_schedule_update_delete_confirm">Sicher?</string>
+10
View File
@@ -52,6 +52,16 @@
<string name="schedule_fab_add_text">New event</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="schedule_no_events">You don\'t have any events for %s.</string>
<string name="sheet_event_action_edit_event_title">Edit this event</string>
<string name="sheet_event_action_add_task_title">Add a task or exam</string>
<string name="sheet_event_action_view_tasks_title">View tasks and exams for this event</string>
<string name="sheet_event_action_find_room_title">Find this event\'s room</string>
<string name="sheet_event_action_delete_event_title">Delete this event</string>
<string name="sheet_event_confirm_deletion_header">Confirm delete action</string>
<string name="sheet_event_confirm_deletion_content">Are you sure that you want to delete the event \'%s\'?</string>
<string name="sheet_event_confirm_deletion_snack">The event has been deleted.</string>
<string name="save">Save</string> <string name="save">Save</string>
<string name="delete">Delete</string> <string name="delete">Delete</string>
<string name="sheet_schedule_update_delete_confirm">Sure?</string> <string name="sheet_schedule_update_delete_confirm">Sure?</string>