Added FormattedDate.kt to produce formatted strings more easily; TaskOverviewAdapter.kt now produces expandable items

This commit is contained in:
denizk0461
2023-05-23 12:39:43 +02:00
parent ce0667300d
commit e52a055cf1
17 changed files with 266 additions and 53 deletions
+2 -2
View File
@@ -7,11 +7,11 @@
<deviceKey> <deviceKey>
<Key> <Key>
<type value="VIRTUAL_DEVICE_PATH" /> <type value="VIRTUAL_DEVICE_PATH" />
<value value="C:\Users\kduez\.android\avd\Pixel_6_A13_.avd" /> <value value="C:\Users\kduez\.android\avd\Nexus_4_API_24.avd" />
</Key> </Key>
</deviceKey> </deviceKey>
</Target> </Target>
</targetSelectedWithDropDown> </targetSelectedWithDropDown>
<timeTargetWasSelectedWithDropDown value="2023-05-22T13:36:19.819030Z" /> <timeTargetWasSelectedWithDropDown value="2023-05-23T10:00:38.080775800Z" />
</component> </component>
</project> </project>
@@ -2,7 +2,7 @@
"formatVersion": 1, "formatVersion": 1,
"database": { "database": {
"version": 21, "version": 21,
"identityHash": "4ac175b58eab4b387bd1ceb98f39a913", "identityHash": "202a385ce4f79f957d41c8e4a2b8ab22",
"entities": [ "entities": [
{ {
"tableName": "studip_events", "tableName": "studip_events",
@@ -268,7 +268,7 @@
}, },
{ {
"tableName": "event_tasks", "tableName": "event_tasks",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`taskId` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `eventId` INTEGER NOT NULL, `dueDate` INTEGER NOT NULL, `title` TEXT NOT NULL, `notes` TEXT NOT NULL, `room` TEXT NOT NULL, FOREIGN KEY(`eventId`) REFERENCES `studip_events`(`eventId`) ON UPDATE NO ACTION ON DELETE CASCADE )", "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`taskId` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `eventId` INTEGER NOT NULL, `dueDate` INTEGER NOT NULL, `notifyDate` INTEGER NOT NULL, `title` TEXT NOT NULL, `notes` TEXT NOT NULL, `room` TEXT NOT NULL, FOREIGN KEY(`eventId`) REFERENCES `studip_events`(`eventId`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields": [ "fields": [
{ {
"fieldPath": "taskId", "fieldPath": "taskId",
@@ -288,6 +288,12 @@
"affinity": "INTEGER", "affinity": "INTEGER",
"notNull": true "notNull": true
}, },
{
"fieldPath": "notifyDate",
"columnName": "notifyDate",
"affinity": "INTEGER",
"notNull": true
},
{ {
"fieldPath": "title", "fieldPath": "title",
"columnName": "title", "columnName": "title",
@@ -332,7 +338,7 @@
"views": [], "views": [],
"setupQueries": [ "setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '4ac175b58eab4b387bd1ceb98f39a913')" "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '202a385ce4f79f957d41c8e4a2b8ab22')"
] ]
} }
} }
@@ -1,16 +1,18 @@
package com.denizk0461.weserplaner.adapter package com.denizk0461.weserplaner.adapter
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.appcompat.content.res.AppCompatResources
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.denizk0461.weserplaner.BuildConfig import androidx.transition.TransitionManager
import com.denizk0461.weserplaner.R
import com.denizk0461.weserplaner.data.AppDiffUtilCallback import com.denizk0461.weserplaner.data.AppDiffUtilCallback
import com.denizk0461.weserplaner.data.isInThePast
import com.denizk0461.weserplaner.databinding.ItemTaskBinding import com.denizk0461.weserplaner.databinding.ItemTaskBinding
import com.denizk0461.weserplaner.model.EventTask import com.denizk0461.weserplaner.model.EventTask
import java.text.SimpleDateFormat import com.denizk0461.weserplaner.model.FormattedDate
import java.util.Date
import java.util.Locale
class TaskOverviewAdapter( class TaskOverviewAdapter(
private val onClickListener: OnClickListener, private val onClickListener: OnClickListener,
@@ -46,16 +48,65 @@ class TaskOverviewAdapter(
// Retrieve item for current position // Retrieve item for current position
val currentItem = tasks[position] val currentItem = tasks[position]
// Determine whether this item's view is expanded
var isExpanded = false
holder.binding.layoutExpandedContainer.visibility = View.GONE
// Context for easier reference // Context for easier reference
val context = holder.binding.root.context val context = holder.binding.root.context
// view set-up // view set-up
SimpleDateFormat("yyyy-MM-dd, HH:mm:ss.SSS", Locale.GERMANY)
.format(Date(BuildConfig.BUILD_TIME_MILLIS)) // Set title text
holder.binding.textTitle.text = currentItem.title
// Set due date text to formatted date, TODO let user pick the date format
val dueDate = FormattedDate(currentItem.dueDate)
holder.binding.textDueDate.text = dueDate.localisedString(context)
if (currentItem.notifyDate == -1L) {
holder.binding.layoutDueDate.visibility = View.GONE
holder.binding.iconNotifyHeader.setImageResource(0)
} else {
val notificationDrawable = AppCompatResources.getDrawable(
context,
R.drawable.notifications,
)
holder.binding.layoutDueDate.visibility = View.VISIBLE
holder.binding.iconNotifyHeader.setImageDrawable(notificationDrawable)
holder.binding.iconNotifyDate.setImageDrawable(notificationDrawable)
// TODO let user pick date format
val notifyDate = FormattedDate(currentItem.notifyDate)
holder.binding.textNotifyDate.text = context.getString(if (notifyDate.date.isInThePast()) {
R.string.task_item_notification_active_past
} else {
R.string.task_item_notification_active_future
}, notifyDate.dateString, notifyDate.timeString)
}
// Set up single click listener // Set up single click listener
holder.binding.linearLayout.setOnClickListener { holder.binding.linearLayout.setOnClickListener {
onClickListener.onClick(currentItem) // Prepare layout animation
TransitionManager.beginDelayedTransition(holder.binding.root.parent as ViewGroup)
// Set visibility of further items
holder.binding.layoutExpandedContainer.visibility = if (isExpanded) {
View.GONE
} else {
View.VISIBLE
}
// Set value of isExpanded depending on whether the view is expanded
isExpanded = !isExpanded
} }
// Set up long press listener // Set up long press listener
@@ -89,14 +140,6 @@ class TaskOverviewAdapter(
*/ */
interface OnClickListener { interface OnClickListener {
/**
* Executed when an item has been clicked.
*
* @param task item that has been clicked
*/
fun onClick(task: EventTask)
/** /**
* Executed when an item has been long-pressed. * Executed when an item has been long-pressed.
* *
@@ -17,9 +17,8 @@ import com.denizk0461.weserplaner.exception.ParcelNotFoundException
import com.denizk0461.weserplaner.values.TextSheetContentId import com.denizk0461.weserplaner.values.TextSheetContentId
import com.denizk0461.weserplaner.sheet.TextSheet import com.denizk0461.weserplaner.sheet.TextSheet
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import java.text.SimpleDateFormat import java.util.Calendar
import java.util.Date import java.util.Date
import java.util.Locale
import kotlin.jvm.Throws import kotlin.jvm.Throws
/* /*
@@ -39,6 +38,25 @@ fun String.parseToMinutes(): Int = try {
0 0
} }
/**
* Retrieves the current date using a Calendar instance.
*
* @return date object containing the current time
*/
fun getCurrentTime(): Date = Calendar.getInstance().run {
Date((get(Calendar.MINUTE) + get(Calendar.HOUR_OF_DAY) * 60L))
}
/**
* Determines whether a given date lies in the past.
*
* @receiver date to check
* @param against date to check against, defaults to current date
* @return true if it is in the past, false if it is in the future or at this moment
*/
fun Date.isInThePast(against: Date = getCurrentTime()): Boolean =
this.time < against.time
/** /**
* Retrieves a specified colour customised to the currently applied theme. * Retrieves a specified colour customised to the currently applied theme.
* *
@@ -151,19 +169,6 @@ fun SwipeRefreshLayout.setRainbowProgressCircle() {
) )
} }
/**
* Formats a date object to a string in the ISO 8601 format. Example:
* 2023-05-21, 14:32:59.067
*
* @receiver date object to convert to string
* @param useHighPrecision determines whether seconds and milliseconds are shown
* @return date formatted as ISO 8601 string
*/
fun Date.formatToIso8601String(useHighPrecision: Boolean = false): String = SimpleDateFormat(
"yyyy-MM-dd, HH:mm${if (useHighPrecision) ":ss.SSS" else ""}",
Locale.GERMANY,
).format(this)
/** /**
* Timeslots for which a conversion to an academic quarter is applicable. * Timeslots for which a conversion to an academic quarter is applicable.
*/ */
@@ -76,6 +76,7 @@ interface AppDAO {
"SELECT event_tasks.taskId, " + "SELECT event_tasks.taskId, " +
"event_tasks.eventId, " + "event_tasks.eventId, " +
"event_tasks.dueDate, " + "event_tasks.dueDate, " +
"event_tasks.notifyDate, " +
"event_tasks.title AS taskTitle, " + "event_tasks.title AS taskTitle, " +
"studip_events.title AS eventTitle, " + "studip_events.title AS eventTitle, " +
"studip_events.lecturer, " + "studip_events.lecturer, " +
@@ -96,6 +97,7 @@ interface AppDAO {
"SELECT event_tasks.taskId, " + "SELECT event_tasks.taskId, " +
"event_tasks.eventId, " + "event_tasks.eventId, " +
"event_tasks.dueDate, " + "event_tasks.dueDate, " +
"event_tasks.notifyDate, " +
"event_tasks.title AS taskTitle, " + "event_tasks.title AS taskTitle, " +
"studip_events.title AS eventTitle, " + "studip_events.title AS eventTitle, " +
"studip_events.lecturer, " + "studip_events.lecturer, " +
@@ -115,6 +117,7 @@ interface AppDAO {
"SELECT event_tasks.taskId, " + "SELECT event_tasks.taskId, " +
"event_tasks.eventId, " + "event_tasks.eventId, " +
"event_tasks.dueDate, " + "event_tasks.dueDate, " +
"event_tasks.notifyDate, " +
"event_tasks.title AS taskTitle, " + "event_tasks.title AS taskTitle, " +
"studip_events.title AS eventTitle, " + "studip_events.title AS eventTitle, " +
"studip_events.lecturer, " + "studip_events.lecturer, " +
@@ -16,11 +16,11 @@ import com.denizk0461.weserplaner.BuildConfig
import com.denizk0461.weserplaner.R import com.denizk0461.weserplaner.R
import com.denizk0461.weserplaner.activity.FetcherActivity import com.denizk0461.weserplaner.activity.FetcherActivity
import com.denizk0461.weserplaner.activity.ImageActivity import com.denizk0461.weserplaner.activity.ImageActivity
import com.denizk0461.weserplaner.data.formatToIso8601String
import com.denizk0461.weserplaner.data.getTextSheet import com.denizk0461.weserplaner.data.getTextSheet
import com.denizk0461.weserplaner.data.showSnackBar import com.denizk0461.weserplaner.data.showSnackBar
import com.denizk0461.weserplaner.data.showToast import com.denizk0461.weserplaner.data.showToast
import com.denizk0461.weserplaner.databinding.FragmentSettingsBinding import com.denizk0461.weserplaner.databinding.FragmentSettingsBinding
import com.denizk0461.weserplaner.model.FormattedDate
import com.denizk0461.weserplaner.sheet.AllergenConfigSheet import com.denizk0461.weserplaner.sheet.AllergenConfigSheet
import com.denizk0461.weserplaner.viewmodel.SettingsViewModel import com.denizk0461.weserplaner.viewmodel.SettingsViewModel
import java.nio.charset.StandardCharsets import java.nio.charset.StandardCharsets
@@ -318,7 +318,7 @@ class SettingsFragment : AppFragment<FragmentSettingsBinding>() {
// Set build version code and time text // Set build version code and time text
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
binding.buildTimeText.text = "v${BuildConfig.VERSION_CODE} | ${ binding.buildTimeText.text = "v${BuildConfig.VERSION_CODE} | ${
Date(BuildConfig.BUILD_TIME_MILLIS).formatToIso8601String(useHighPrecision = true) FormattedDate(BuildConfig.BUILD_TIME_MILLIS).commaSeparatedString(context)
}" }"
// Set up switch for showing beta screens // Set up switch for showing beta screens
@@ -91,10 +91,6 @@ class TaskOverviewFragment : AppFragment<FragmentTaskOverviewBinding>(),
} }
} }
override fun onClick(task: EventTask) {
// TODO
}
override fun onLongClick(task: EventTask): Boolean { override fun onLongClick(task: EventTask): Boolean {
// TODO // TODO
return false return false
@@ -7,12 +7,14 @@ import androidx.room.PrimaryKey
/** /**
* Database entity used to store tasks assigned to specific [StudIPEvent] elements. * Database entity used to store tasks assigned to specific [StudIPEvent] elements.
* *
* @param taskId primary key for the entity * @param taskId primary key for the entity
* @param eventId foreign key referencing the event this task is assigned to * @param eventId foreign key referencing the event this task is assigned to
* @param dueDate time and date at which the task is due * @param dueDate time and date at which the task is due
* @param title title of the task * @param notifyDate time and date at which the user wants to be notified about this task; -1 if
* @param notes user-added notes for the task * the user doesn't want to be notified
* @param room room the task may take place in * @param title title of the task
* @param notes user-added notes for the task
* @param room room the task may take place in
*/ */
@Entity( @Entity(
tableName = "event_tasks", tableName = "event_tasks",
@@ -28,7 +30,8 @@ import androidx.room.PrimaryKey
data class EventTask( data class EventTask(
@PrimaryKey(autoGenerate = true) val taskId: Int = 0, @PrimaryKey(autoGenerate = true) val taskId: Int = 0,
val eventId: Int, val eventId: Int,
val dueDate: Int, val dueDate: Long,
val notifyDate: Long,
val title: String, val title: String,
val notes: String, val notes: String,
val room: String, val room: String,
@@ -7,6 +7,8 @@ package com.denizk0461.weserplaner.model
* @param taskId primary key for the entity * @param taskId primary key for the entity
* @param eventId foreign key referencing the event this task is assigned to * @param eventId foreign key referencing the event this task is assigned to
* @param dueDate time and date at which the task is due * @param dueDate time and date at which the task is due
* @param notifyDate time and date at which the user wants to be notified about this task; -1 if
* the user doesn't want to be notified
* @param eventTitle title of the event * @param eventTitle title of the event
* @param taskTitle title of the task * @param taskTitle title of the task
* @param lecturer lecturer(s) organising the event * @param lecturer lecturer(s) organising the event
@@ -17,6 +19,7 @@ data class EventTaskExtended(
val taskId: Int, val taskId: Int,
val eventId: Int, val eventId: Int,
val dueDate: Int, val dueDate: Int,
val notifyDate: Int,
val eventTitle: String, val eventTitle: String,
val taskTitle: String, val taskTitle: String,
val lecturer: String, val lecturer: String,
@@ -0,0 +1,49 @@
package com.denizk0461.weserplaner.model
import android.content.Context
import com.denizk0461.weserplaner.R
import com.denizk0461.weserplaner.values.DateFormat
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
/**
* Wrapper for Java's date object that exposes pre-formatted date and time strings.
*
* @param date date object to wrap
* @param format format the date should be presented in; see [com.denizk0461.weserplaner.values.DateFormat]
*/
class FormattedDate(val date: Date, format: DateFormat = DateFormat.ISO8601) {
constructor(time: Long, format: DateFormat = DateFormat.ISO8601) : this(Date(time), format)
var dateString: String = SimpleDateFormat(format.dateFormat, Locale.GERMANY).format(date)
var timeString: String = SimpleDateFormat(format.timeFormat, Locale.GERMANY).format(date)
/**
* Produces a string containing date and time of the object, separated by a comma. Example:
* 24.05.2023, 8:45
*
* @param context used to retrieve the string resource
* @return formatted string
*/
fun commaSeparatedString(context: Context): String = context.getString(
R.string.formatted_date_string_comma,
dateString,
timeString,
)
/**
* Produces a string containing date and time of the object, localised to the user's locale. Example:
* 24.05.2023 at 8:45 (English)
* 24.05.2023 um 8:45 (German)
*
* @param context used to retrieve the string resource
* @return formatted string
*/
fun localisedString(context: Context): String = context.getString(
R.string.formatted_date_string_localised,
dateString,
timeString,
)
}
@@ -0,0 +1,12 @@
package com.denizk0461.weserplaner.values
/**
* Determines the format a date should be put into.
*/
enum class DateFormat(val dateFormat: String, val timeFormat: String) {
EUROPEAN("dd.MM.yyyy", "H:mm"), // 24.05.2023, 8:45
ISO8601("yyyy-MM-dd", "HH:mm"), // 2023-05-24, 08:45
ISO8601_PRECISE("yyyy-MM-dd", "HH:mm:ss.SSS"), // 2023-05-24, 08:45:11.518
FUCKED_UP("MM/dd/yy", "h:mm a"), // 05/24/23, 8:45 AM
;
}
@@ -18,8 +18,8 @@ class TaskOverviewViewModel(application: Application) : AppViewModel(application
// fun getTasks(order: TaskOrder): LiveData<List<EventTask>> = repo.getTasks(order) // fun getTasks(order: TaskOrder): LiveData<List<EventTask>> = repo.getTasks(order)
fun getTasks(order: TaskOrder) = listOf( // dummy data fun getTasks(order: TaskOrder) = listOf( // dummy data
EventTask(0, 0, 1684758756, "title1", "user notes", "GW2 B-idk"), EventTask(0, 0, 1684758756L, -1L, "title1", "user notes", "GW2 B-idk"),
EventTask(1, 0, 1684798756, "title2", "user notes", "GW3 C-idk"), EventTask(1, 0, 1684798756L, -1L, "title2", "user notes", "GW3 C-idk"),
EventTask(2, 0, 1689758756, "title3", "user notes", "GW4 D-idk"), EventTask(2, 0, 1689758756L, 1689958756L, "title3", "user notes", "GW4 D-idk"),
) )
} }
@@ -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,22c1.1,0 2,-0.9 2,-2h-4c0,1.1 0.89,2 2,2zM18,16v-5c0,-3.07 -1.64,-5.64 -4.5,-6.32L13.5,4c0,-0.83 -0.67,-1.5 -1.5,-1.5s-1.5,0.67 -1.5,1.5v0.68C7.63,5.36 6,7.92 6,11v5l-2,2v1h16v-1l-2,-2z"/>
</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="M20,18.69L7.84,6.14 5.27,3.49 4,4.76l2.8,2.8v0.01c-0.52,0.99 -0.8,2.16 -0.8,3.42v5l-2,2v1h13.73l2,2L21,19.72l-1,-1.03zM12,22c1.11,0 2,-0.89 2,-2h-4c0,1.11 0.89,2 2,2zM18,14.68L18,11c0,-3.08 -1.64,-5.64 -4.5,-6.32L13.5,4c0,-0.83 -0.67,-1.5 -1.5,-1.5s-1.5,0.67 -1.5,1.5v0.68c-0.15,0.03 -0.29,0.08 -0.42,0.12 -0.1,0.03 -0.2,0.07 -0.3,0.11h-0.01c-0.01,0 -0.01,0 -0.02,0.01 -0.23,0.09 -0.46,0.2 -0.68,0.31 0,0 -0.01,0 -0.01,0.01L18,14.68z"/>
</vector>
+72 -2
View File
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat <androidx.appcompat.widget.LinearLayoutCompat
xmlns:android="http://schemas.android.com/apk/res/android" 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_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingHorizontal="8dp" android:paddingHorizontal="8dp"
@@ -17,12 +18,81 @@
android:id="@+id/linear_layout" android:id="@+id/linear_layout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical"
android:clickable="true" android:clickable="true"
android:focusable="true" android:focusable="true"
android:padding="16dp"> android:padding="16dp"
android:background="@drawable/selectable_item_background"
android:orientation="vertical">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/text_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textSize="22sp"
app:fontFamily="@font/lato_bolditalic"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@id/icon_notify_header"
android:layout_marginEnd="8dp"/>
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/icon_notify_header"
android:layout_width="20dp"
android:layout_height="20dp"
android:scaleType="centerInside"
android:tint="?attr/colorText"
android:importantForAccessibility="no"
app:layout_constraintTop_toTopOf="@id/text_title"
app:layout_constraintEnd_toEndOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/text_due_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16sp"/>
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/layout_expanded_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.google.android.material.divider.MaterialDivider
android:id="@+id/divider"
style="@style/DividerTheme"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="4dp"/>
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/layout_due_date"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/icon_notify_date"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_marginEnd="8dp"
android:scaleType="centerInside"
android:tint="?attr/colorText"
android:importantForAccessibility="no"/>
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/text_notify_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat> </androidx.appcompat.widget.LinearLayoutCompat>
+6
View File
@@ -90,6 +90,12 @@
<string name="task_order_menu_date_created">Erstellungszeit</string> <string name="task_order_menu_date_created">Erstellungszeit</string>
<string name="task_order_menu_date_due">Abgabezeit</string> <string name="task_order_menu_date_due">Abgabezeit</string>
<string name="formatted_date_string_localised">%s um %s</string>
<string name="task_item_notification_none">Du wirst nicht benachrichtigt.</string>
<string name="task_item_notification_active_future">Du wirst am %s um %s benachrichtigt.</string>
<string name="task_item_notification_active_past">Du wurdest am %s um %s benachrichtigt.</string>
<string name="task_overview_snack_unimplemented">Aufgaben sind noch nicht implementiert!</string> <string name="task_overview_snack_unimplemented">Aufgaben sind noch nicht implementiert!</string>
<string name="task_overview_fab_add_task">Aufgabe hinzufügen</string> <string name="task_overview_fab_add_task">Aufgabe hinzufügen</string>
+7
View File
@@ -91,6 +91,13 @@
<string name="task_order_menu_date_created">Date created</string> <string name="task_order_menu_date_created">Date created</string>
<string name="task_order_menu_date_due">Date due</string> <string name="task_order_menu_date_due">Date due</string>
<string name="formatted_date_string_comma" translatable="false">%s, %s</string>
<string name="formatted_date_string_localised">%s at %s</string>
<string name="task_item_notification_none">You won\'t be notified</string>
<string name="task_item_notification_active_future">You will be notified on %s at %s.</string>
<string name="task_item_notification_active_past">You were notified on %s at %s.</string>
<string name="task_overview_snack_unimplemented">Tasks are not yet implemented!</string> <string name="task_overview_snack_unimplemented">Tasks are not yet implemented!</string>
<string name="task_overview_fab_add_task">Add task</string> <string name="task_overview_fab_add_task">Add task</string>