forked from github/szkolny
[Event] Add new manual event dialog
This commit is contained in:
parent
472e768369
commit
16102de619
@ -4,11 +4,13 @@ import android.Manifest
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.pm.PackageManager
|
||||
import android.graphics.Typeface
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.text.*
|
||||
import android.text.style.ForegroundColorSpan
|
||||
import android.text.style.StrikethroughSpan
|
||||
import android.text.style.StyleSpan
|
||||
import android.util.LongSparseArray
|
||||
import android.util.SparseArray
|
||||
import android.view.View
|
||||
@ -16,6 +18,9 @@ import android.widget.TextView
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.core.util.forEach
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.Observer
|
||||
import com.google.gson.JsonArray
|
||||
import com.google.gson.JsonElement
|
||||
import com.google.gson.JsonObject
|
||||
@ -344,6 +349,11 @@ fun CharSequence?.asStrikethroughSpannable(): Spannable {
|
||||
spannable.setSpan(StrikethroughSpan(), 0, spannable.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
return spannable
|
||||
}
|
||||
fun CharSequence?.asItalicSpannable(): Spannable {
|
||||
val spannable = SpannableString(this)
|
||||
spannable.setSpan(StyleSpan(Typeface.ITALIC), 0, spannable.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
return spannable
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new read-only list only of those given elements, that are not empty.
|
||||
@ -416,4 +426,13 @@ inline fun <T : View> T.onClick(crossinline onClickListener: (v: T) -> Unit) {
|
||||
setOnClickListener { v: View ->
|
||||
onClickListener(v as T)
|
||||
}
|
||||
}
|
||||
|
||||
fun <T> LiveData<T>.observeOnce(lifecycleOwner: LifecycleOwner, observer: Observer<T>) {
|
||||
observe(lifecycleOwner, object : Observer<T> {
|
||||
override fun onChanged(t: T?) {
|
||||
observer.onChanged(t)
|
||||
removeObserver(this)
|
||||
}
|
||||
})
|
||||
}
|
@ -5,6 +5,7 @@ import androidx.room.ColumnInfo;
|
||||
import androidx.room.Entity;
|
||||
import androidx.room.Ignore;
|
||||
import androidx.room.Index;
|
||||
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date;
|
||||
import pl.szczodrzynski.edziennik.utils.models.Time;
|
||||
|
||||
@ -85,6 +86,23 @@ public class Event {
|
||||
this.teamId = teamId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Event clone() throws CloneNotSupportedException {
|
||||
return new Event(
|
||||
profileId,
|
||||
id,
|
||||
eventDate.clone(),
|
||||
startTime == null ? null : startTime.clone(),
|
||||
topic,
|
||||
color,
|
||||
type,
|
||||
addedManually,
|
||||
subjectId,
|
||||
teacherId,
|
||||
teamId
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Event{" +
|
||||
|
@ -62,6 +62,25 @@ class LessonFull(profileId: Int, id: Long) : Lesson(profileId, id) {
|
||||
return classroom ?: oldClassroom
|
||||
}
|
||||
|
||||
val displayTeamId: Long?
|
||||
get() {
|
||||
if (type == TYPE_SHIFTED_SOURCE)
|
||||
return oldTeamId
|
||||
return teamId ?: oldTeamId
|
||||
}
|
||||
val displaySubjectId: Long?
|
||||
get() {
|
||||
if (type == TYPE_SHIFTED_SOURCE)
|
||||
return oldSubjectId
|
||||
return subjectId ?: oldSubjectId
|
||||
}
|
||||
val displayTeacherId: Long?
|
||||
get() {
|
||||
if (type == TYPE_SHIFTED_SOURCE)
|
||||
return oldTeacherId
|
||||
return teacherId ?: oldTeacherId
|
||||
}
|
||||
|
||||
// metadata
|
||||
var seen: Boolean = false
|
||||
var notified: Boolean = false
|
||||
|
@ -43,7 +43,31 @@ interface TimetableDao {
|
||||
LEFT JOIN teams AS oldG ON timetable.profileId = oldG.profileId AND timetable.oldTeamId = oldG.teamId
|
||||
LEFT JOIN metadata ON id = thingId AND thingType = ${Metadata.TYPE_LESSON_CHANGE} AND metadata.profileId = timetable.profileId
|
||||
WHERE timetable.profileId = :profileId AND (type != 3 AND date = :date) OR ((type = 3 OR type = 1) AND oldDate = :date)
|
||||
ORDER BY type
|
||||
ORDER BY id, type
|
||||
""")
|
||||
fun getForDate(profileId: Int, date: Date) : LiveData<List<LessonFull>>
|
||||
|
||||
@Query("""
|
||||
SELECT
|
||||
timetable.*,
|
||||
subjects.subjectLongName AS subjectName,
|
||||
teachers.teacherName ||" "|| teachers.teacherSurname AS teacherName,
|
||||
teams.teamName AS teamName,
|
||||
oldS.subjectLongName AS oldSubjectName,
|
||||
oldT.teacherName ||" "|| oldT.teacherSurname AS oldTeacherName,
|
||||
oldG.teamName AS oldTeamName,
|
||||
metadata.seen, metadata.notified, metadata.addedDate
|
||||
FROM timetable
|
||||
LEFT JOIN subjects USING(profileId, subjectId)
|
||||
LEFT JOIN teachers USING(profileId, teacherId)
|
||||
LEFT JOIN teams USING(profileId, teamId)
|
||||
LEFT JOIN subjects AS oldS ON timetable.profileId = oldS.profileId AND timetable.oldSubjectId = oldS.subjectId
|
||||
LEFT JOIN teachers AS oldT ON timetable.profileId = oldT.profileId AND timetable.oldTeacherId = oldT.teacherId
|
||||
LEFT JOIN teams AS oldG ON timetable.profileId = oldG.profileId AND timetable.oldTeamId = oldG.teamId
|
||||
LEFT JOIN metadata ON id = thingId AND thingType = ${Metadata.TYPE_LESSON_CHANGE} AND metadata.profileId = timetable.profileId
|
||||
WHERE timetable.profileId = :profileId AND ((type != 3 AND date > :today) OR ((type = 3 OR type = 1) AND oldDate > :today)) AND timetable.subjectId = :subjectId
|
||||
ORDER BY id, type
|
||||
LIMIT 1
|
||||
""")
|
||||
fun getNextWithSubject(profileId: Int, today: Date, subjectId: Long) : LiveData<LessonFull>
|
||||
}
|
||||
|
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) Kuba Szczodrzyński 2019-11-12.
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.ui.dialogs.event
|
||||
|
||||
import android.app.Activity
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import pl.szczodrzynski.edziennik.App
|
||||
import pl.szczodrzynski.edziennik.R
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
import pl.szczodrzynski.edziennik.utils.models.Time
|
||||
|
||||
class EventAddTypeDialog(
|
||||
val activity: Activity,
|
||||
val profileId: Int,
|
||||
val date: Date? = null,
|
||||
val time: Time? = null
|
||||
) {
|
||||
companion object {
|
||||
private const val TAG = "EventAddTypeDialog"
|
||||
}
|
||||
|
||||
private lateinit var dialog: AlertDialog
|
||||
|
||||
init { run {
|
||||
dialog = MaterialAlertDialogBuilder(activity)
|
||||
.setItems(R.array.main_menu_add_options) { dialog, which ->
|
||||
dialog.dismiss()
|
||||
EventManualDialog(activity, profileId)
|
||||
.show(
|
||||
activity.application as App,
|
||||
null,
|
||||
date,
|
||||
time,
|
||||
when (which) {
|
||||
1 -> EventManualDialog.DIALOG_HOMEWORK
|
||||
else -> EventManualDialog.DIALOG_EVENT
|
||||
}
|
||||
)
|
||||
|
||||
}
|
||||
.setNegativeButton(R.string.cancel) { dialog, _ -> dialog.dismiss() }
|
||||
.show()
|
||||
}}
|
||||
}
|
@ -0,0 +1,379 @@
|
||||
/*
|
||||
* Copyright (c) Kuba Szczodrzyński 2019-11-12.
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.ui.dialogs.event
|
||||
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.lifecycle.Observer
|
||||
import com.google.android.material.datepicker.MaterialDatePicker
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import kotlinx.coroutines.*
|
||||
import pl.szczodrzynski.edziennik.*
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.events.Event
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.subjects.Subject
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.teams.Team
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.timetable.Lesson
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.timetable.LessonFull
|
||||
import pl.szczodrzynski.edziennik.databinding.DialogEventManualV2Binding
|
||||
import pl.szczodrzynski.edziennik.utils.TextInputDropDown
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
import pl.szczodrzynski.edziennik.utils.models.Time
|
||||
import pl.szczodrzynski.edziennik.utils.models.Week
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
class EventManualV2Dialog(
|
||||
val activity: AppCompatActivity,
|
||||
val profileId: Int,
|
||||
val defaultLesson: LessonFull? = null,
|
||||
val defaultDate: Date? = null,
|
||||
val defaultTime: Time? = null,
|
||||
val defaultType: Int? = null,
|
||||
val editingEvent: Event? = null
|
||||
) : CoroutineScope {
|
||||
|
||||
companion object {
|
||||
private const val TAG = "EventManualDialog"
|
||||
}
|
||||
|
||||
private lateinit var job: Job
|
||||
override val coroutineContext: CoroutineContext
|
||||
get() = job + Dispatchers.Main
|
||||
|
||||
private val app by lazy { activity.application as App }
|
||||
private lateinit var b: DialogEventManualV2Binding
|
||||
private lateinit var dialog: AlertDialog
|
||||
private lateinit var event: Event
|
||||
private var defaultLoaded = false
|
||||
|
||||
init { run {
|
||||
job = Job()
|
||||
|
||||
b = DialogEventManualV2Binding.inflate(activity.layoutInflater)
|
||||
dialog = MaterialAlertDialogBuilder(activity)
|
||||
.setTitle(R.string.dialog_event_manual_title)
|
||||
.setView(b.root)
|
||||
.setNegativeButton(R.string.cancel) { dialog, _ -> dialog.dismiss() }
|
||||
.setPositiveButton(R.string.save) { _, _ -> saveEvent() }
|
||||
.show()
|
||||
|
||||
event = editingEvent?.clone() ?: Event().also { event ->
|
||||
event.profileId = profileId
|
||||
/*defaultDate?.let {
|
||||
event.eventDate = it
|
||||
b.date = it
|
||||
}
|
||||
defaultTime?.let {
|
||||
event.startTime = it
|
||||
b.time = it
|
||||
}
|
||||
defaultType?.let {
|
||||
event.type = it
|
||||
}*/
|
||||
}
|
||||
|
||||
loadLists()
|
||||
}}
|
||||
|
||||
private fun loadLists() { launch {
|
||||
val deferred = async(Dispatchers.Default) {
|
||||
// get the team list
|
||||
val teams = app.db.teamDao().getAllNow(profileId)
|
||||
b.teamDropdown.clear()
|
||||
b.teamDropdown += TextInputDropDown.Item(
|
||||
-1,
|
||||
activity.getString(R.string.dialog_event_manual_no_team),
|
||||
""
|
||||
)
|
||||
b.teamDropdown += teams.map { TextInputDropDown.Item(it.id, it.name, tag = it) }
|
||||
|
||||
// get the subject list
|
||||
val subjects = app.db.subjectDao().getAllNow(profileId)
|
||||
b.subjectDropdown.clear()
|
||||
b.subjectDropdown += TextInputDropDown.Item(
|
||||
-1,
|
||||
activity.getString(R.string.dialog_event_manual_no_subject),
|
||||
""
|
||||
)
|
||||
b.subjectDropdown += subjects.map { TextInputDropDown.Item(it.id, it.longName, tag = it) }
|
||||
|
||||
// get the teacher list
|
||||
val teachers = app.db.teacherDao().getAllNow(profileId)
|
||||
b.teacherDropdown.clear()
|
||||
b.teacherDropdown += TextInputDropDown.Item(
|
||||
-1,
|
||||
activity.getString(R.string.dialog_event_manual_no_teacher),
|
||||
""
|
||||
)
|
||||
b.teacherDropdown += teachers.map { TextInputDropDown.Item(it.id, it.fullName, tag = it) }
|
||||
}
|
||||
deferred.await()
|
||||
|
||||
b.teamDropdown.isEnabled = true
|
||||
b.subjectDropdown.isEnabled = true
|
||||
b.teacherDropdown.isEnabled = true
|
||||
|
||||
// copy IDs from event being edited
|
||||
editingEvent?.let {
|
||||
b.teamDropdown.select(it.teamId)
|
||||
b.subjectDropdown.select(it.subjectId)
|
||||
b.teacherDropdown.select(it.teacherId)
|
||||
}
|
||||
|
||||
// copy IDs from the LessonFull
|
||||
defaultLesson?.let {
|
||||
b.teamDropdown.select(it.displayTeamId)
|
||||
b.subjectDropdown.select(it.displaySubjectId)
|
||||
b.teacherDropdown.select(it.displayTeacherId)
|
||||
}
|
||||
|
||||
loadDates()
|
||||
}}
|
||||
|
||||
private fun loadDates() { launch {
|
||||
val date = Date.getToday()
|
||||
val today = date.value
|
||||
var weekDay = date.weekDay
|
||||
|
||||
val deferred = async(Dispatchers.Default) {
|
||||
val dates = mutableListOf<TextInputDropDown.Item>()
|
||||
// item choosing the next lesson of specific subject
|
||||
b.subjectDropdown.selected?.let {
|
||||
if (it.tag is Subject) {
|
||||
dates += TextInputDropDown.Item(
|
||||
-it.id,
|
||||
activity.getString(R.string.dialog_event_manual_date_next_lesson, it.tag.longName)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// TODAY
|
||||
dates += TextInputDropDown.Item(
|
||||
date.value.toLong(),
|
||||
activity.getString(R.string.dialog_event_manual_date_today, date.formattedString),
|
||||
tag = date.clone()
|
||||
)
|
||||
|
||||
// TOMORROW
|
||||
if (weekDay < 4) {
|
||||
date.stepForward(0, 0, 1)
|
||||
weekDay++
|
||||
dates += TextInputDropDown.Item(
|
||||
date.value.toLong(),
|
||||
activity.getString(R.string.dialog_event_manual_date_tomorrow, date.formattedString),
|
||||
tag = date.clone()
|
||||
)
|
||||
}
|
||||
// REMAINING SCHOOL DAYS OF THE CURRENT WEEK
|
||||
while (weekDay < 4) {
|
||||
date.stepForward(0, 0, 1) // step one day forward
|
||||
weekDay++
|
||||
dates += TextInputDropDown.Item(
|
||||
date.value.toLong(),
|
||||
activity.getString(R.string.dialog_event_manual_date_this_week, Week.getFullDayName(weekDay), date.formattedString),
|
||||
tag = date.clone()
|
||||
)
|
||||
}
|
||||
// go to next week Monday
|
||||
date.stepForward(0, 0, -weekDay + 7)
|
||||
weekDay = 0
|
||||
// ALL SCHOOL DAYS OF THE NEXT WEEK
|
||||
while (weekDay < 4) {
|
||||
dates += TextInputDropDown.Item(
|
||||
date.value.toLong(),
|
||||
activity.getString(R.string.dialog_event_manual_date_next_week, Week.getFullDayName(weekDay), date.formattedString),
|
||||
tag = date.clone()
|
||||
)
|
||||
date.stepForward(0, 0, 1) // step one day forward
|
||||
weekDay++
|
||||
}
|
||||
dates += TextInputDropDown.Item(
|
||||
-1L,
|
||||
activity.getString(R.string.dialog_event_manual_date_other)
|
||||
)
|
||||
dates
|
||||
}
|
||||
|
||||
val dates = deferred.await()
|
||||
b.dateDropdown.clear().append(dates)
|
||||
|
||||
editingEvent?.let {
|
||||
b.dateDropdown.select(it.eventDate.value.toLong())
|
||||
}
|
||||
|
||||
defaultLesson?.let {
|
||||
b.dateDropdown.select(it.displayDate?.value?.toLong())
|
||||
}
|
||||
|
||||
if (b.dateDropdown.selected == null) {
|
||||
b.dateDropdown.select(today.toLong())
|
||||
}
|
||||
|
||||
b.dateDropdown.isEnabled = true
|
||||
|
||||
b.dateDropdown.setOnChangeListener { item ->
|
||||
when {
|
||||
// next lesson with specified subject
|
||||
item.id < -1 -> {
|
||||
app.db.timetableDao().getNextWithSubject(profileId, Date.getToday(), -item.id).observeOnce(activity, Observer {
|
||||
val lessonDate = it?.displayDate ?: return@Observer
|
||||
b.dateDropdown.selected = TextInputDropDown.Item(
|
||||
lessonDate.value.toLong(),
|
||||
lessonDate.formattedString,
|
||||
tag = lessonDate
|
||||
)
|
||||
// TODO load correct hour when selecting next lesson
|
||||
b.dateDropdown.updateText()
|
||||
it.let {
|
||||
b.teamDropdown.select(it.displayTeamId)
|
||||
b.subjectDropdown.select(it.displaySubjectId)
|
||||
b.teacherDropdown.select(it.displayTeacherId)
|
||||
}
|
||||
defaultLoaded = false
|
||||
loadHours()
|
||||
})
|
||||
return@setOnChangeListener false
|
||||
}
|
||||
// custom date
|
||||
item.id == -1L -> {
|
||||
MaterialDatePicker.Builder
|
||||
.datePicker()
|
||||
.setSelection((b.dateDropdown.selectedId?.let { Date.fromValue(it.toInt()) } ?: Date.getToday()).inMillis)
|
||||
.build()
|
||||
.apply {
|
||||
addOnPositiveButtonClickListener {
|
||||
val dateSelected = Date.fromMillis(it)
|
||||
b.dateDropdown.selected = TextInputDropDown.Item(
|
||||
dateSelected.value.toLong(),
|
||||
dateSelected.formattedString,
|
||||
tag = dateSelected
|
||||
)
|
||||
b.dateDropdown.updateText()
|
||||
loadHours()
|
||||
}
|
||||
show(this@EventManualV2Dialog.activity.supportFragmentManager, "MaterialDatePicker")
|
||||
}
|
||||
|
||||
return@setOnChangeListener false
|
||||
}
|
||||
// a specific date
|
||||
else -> {
|
||||
b.dateDropdown.select(item)
|
||||
loadHours()
|
||||
}
|
||||
}
|
||||
return@setOnChangeListener true
|
||||
}
|
||||
|
||||
loadHours()
|
||||
}}
|
||||
|
||||
private fun loadHours() {
|
||||
b.timeDropdown.isEnabled = false
|
||||
// get the selected date
|
||||
val date = b.dateDropdown.selectedId?.let { Date.fromValue(it.toInt()) } ?: return
|
||||
// get all lessons for selected date
|
||||
app.db.timetableDao().getForDate(profileId, date).observeOnce(activity, Observer { lessons ->
|
||||
val hours = mutableListOf<TextInputDropDown.Item>()
|
||||
// add All day time choice
|
||||
hours += TextInputDropDown.Item(
|
||||
0L,
|
||||
activity.getString(R.string.dialog_event_manual_all_day)
|
||||
)
|
||||
lessons.forEach { lesson ->
|
||||
if (lesson.type == Lesson.TYPE_NO_LESSONS) {
|
||||
// indicate there are no lessons this day
|
||||
hours += TextInputDropDown.Item(
|
||||
-2L,
|
||||
activity.getString(R.string.dialog_event_manual_no_lessons)
|
||||
)
|
||||
return@forEach
|
||||
}
|
||||
// create the lesson caption
|
||||
val text = listOfNotEmpty(
|
||||
lesson.displayStartTime?.stringHM ?: "",
|
||||
lesson.displaySubjectName?.let {
|
||||
when {
|
||||
lesson.type == Lesson.TYPE_CANCELLED -> it.asStrikethroughSpannable()
|
||||
lesson.type != Lesson.TYPE_NORMAL -> it.asItalicSpannable()
|
||||
else -> it
|
||||
}
|
||||
} ?: ""
|
||||
)
|
||||
// add an item with LessonFull as the tag
|
||||
hours += TextInputDropDown.Item(
|
||||
lesson.displayStartTime?.value?.toLong() ?: -1,
|
||||
text.concat(" "),
|
||||
tag = lesson
|
||||
)
|
||||
}
|
||||
b.timeDropdown.clear().append(hours)
|
||||
|
||||
if (defaultLoaded) {
|
||||
b.timeDropdown.deselect()
|
||||
// select the TEAM_CLASS if possible
|
||||
b.teamDropdown.items.singleOrNull {
|
||||
it.tag is Team && it.tag.type == Team.TYPE_CLASS
|
||||
}?.let {
|
||||
b.teamDropdown.select(it)
|
||||
} ?: b.teamDropdown.deselect()
|
||||
|
||||
// clear subject, teacher selection
|
||||
b.subjectDropdown.deselect()
|
||||
b.teacherDropdown.deselect()
|
||||
}
|
||||
else {
|
||||
editingEvent?.let {
|
||||
b.timeDropdown.select(it.startTime?.value?.toLong())
|
||||
}
|
||||
|
||||
defaultLesson?.let {
|
||||
b.timeDropdown.select(it.displayStartTime?.value?.toLong())
|
||||
}
|
||||
}
|
||||
defaultLoaded = true
|
||||
b.timeDropdown.isEnabled = true
|
||||
|
||||
// attach a listener to time dropdown
|
||||
b.timeDropdown.setOnChangeListener { item ->
|
||||
when {
|
||||
// custom start hour
|
||||
item.id == -1L -> {
|
||||
|
||||
return@setOnChangeListener false
|
||||
}
|
||||
// no lessons this day
|
||||
item.id == -2L -> {
|
||||
b.timeDropdown.deselect()
|
||||
return@setOnChangeListener false
|
||||
}
|
||||
// selected a specific lesson
|
||||
else -> {
|
||||
if (item.tag is LessonFull) {
|
||||
// update team, subject, teacher dropdowns,
|
||||
// using the LessonFull from item tag
|
||||
b.teamDropdown.deselect()
|
||||
b.subjectDropdown.deselect()
|
||||
b.teacherDropdown.deselect()
|
||||
item.tag.displayTeamId?.let {
|
||||
b.teamDropdown.select(it)
|
||||
}
|
||||
item.tag.displaySubjectId?.let {
|
||||
b.subjectDropdown.select(it)
|
||||
}
|
||||
item.tag.displayTeacherId?.let {
|
||||
b.teacherDropdown.select(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return@setOnChangeListener true
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun saveEvent() {
|
||||
|
||||
}
|
||||
}
|
@ -4,39 +4,43 @@
|
||||
|
||||
package pl.szczodrzynski.edziennik.ui.dialogs.timetable
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.view.View
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import pl.szczodrzynski.edziennik.App
|
||||
import pl.szczodrzynski.edziennik.R
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.timetable.Lesson
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.timetable.LessonFull
|
||||
import pl.szczodrzynski.edziennik.databinding.DialogLessonDetailsBinding
|
||||
import pl.szczodrzynski.edziennik.setText
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.event.EventManualDialog
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.event.EventManualV2Dialog
|
||||
import pl.szczodrzynski.edziennik.ui.modules.timetable.v2.TimetableFragment
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
import pl.szczodrzynski.edziennik.utils.models.Week
|
||||
|
||||
class LessonDetailsDialog(
|
||||
val activity: Activity,
|
||||
val activity: AppCompatActivity,
|
||||
val lesson: LessonFull
|
||||
) {
|
||||
companion object {
|
||||
private const val TAG = "LessonDetailsDialog"
|
||||
}
|
||||
|
||||
private lateinit var b: DialogLessonDetailsBinding
|
||||
private lateinit var dialog: AlertDialog
|
||||
|
||||
init { run {
|
||||
val b = DialogLessonDetailsBinding.inflate(activity.layoutInflater)
|
||||
val dialog = MaterialAlertDialogBuilder(activity)
|
||||
b = DialogLessonDetailsBinding.inflate(activity.layoutInflater)
|
||||
dialog = MaterialAlertDialogBuilder(activity)
|
||||
.setView(b.root)
|
||||
.setPositiveButton(R.string.close) { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
}
|
||||
.setNeutralButton(R.string.add) { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
MaterialAlertDialogBuilder(activity)
|
||||
EventManualV2Dialog(activity, lesson.profileId, lesson)
|
||||
/*MaterialAlertDialogBuilder(activity)
|
||||
.setItems(R.array.main_menu_add_options) { dialog2, which ->
|
||||
dialog2.dismiss()
|
||||
EventManualDialog(activity, lesson.profileId)
|
||||
@ -53,11 +57,15 @@ class LessonDetailsDialog(
|
||||
|
||||
}
|
||||
.setNegativeButton(R.string.cancel) { dialog2, _ -> dialog2.dismiss() }
|
||||
.show()
|
||||
.show()*/
|
||||
}
|
||||
.show()
|
||||
update()
|
||||
}}
|
||||
|
||||
private fun update() {
|
||||
b.lesson = lesson
|
||||
val lessonDate = lesson.displayDate ?: return@run
|
||||
val lessonDate = lesson.displayDate ?: return
|
||||
b.lessonDate.text = Week.getFullDayName(lessonDate.weekDay) + ", " + lessonDate.formattedString
|
||||
|
||||
if (lesson.type >= Lesson.TYPE_SHIFTED_SOURCE) {
|
||||
@ -135,5 +143,5 @@ class LessonDetailsDialog(
|
||||
if (lesson.type != Lesson.TYPE_CANCELLED && lesson.teamId != null) {
|
||||
b.teamName = lesson.teamName
|
||||
}
|
||||
}}
|
||||
}
|
||||
}
|
@ -1,55 +0,0 @@
|
||||
package pl.szczodrzynski.edziennik.utils;
|
||||
|
||||
import android.content.Context;
|
||||
import com.google.android.material.textfield.TextInputEditText;
|
||||
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import androidx.core.graphics.drawable.DrawableCompat;
|
||||
|
||||
import pl.szczodrzynski.edziennik.R;
|
||||
|
||||
public class TextInputDropDown extends TextInputEditText {
|
||||
public TextInputDropDown(Context context) {
|
||||
super(context);
|
||||
create(context);
|
||||
}
|
||||
|
||||
public TextInputDropDown(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
create(context);
|
||||
}
|
||||
|
||||
public TextInputDropDown(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
create(context);
|
||||
}
|
||||
|
||||
public void create(Context context) {
|
||||
Drawable drawable = context.getResources().getDrawable(R.drawable.dropdown_arrow);
|
||||
Drawable wrappedDrawable = DrawableCompat.wrap(drawable);
|
||||
DrawableCompat.setTint(wrappedDrawable, Themes.INSTANCE.getPrimaryTextColor(context));
|
||||
|
||||
setCompoundDrawablesWithIntrinsicBounds(null, null, wrappedDrawable, null);
|
||||
setFocusableInTouchMode(false);
|
||||
setCursorVisible(false);
|
||||
setLongClickable(false);
|
||||
setMaxLines(1);
|
||||
setInputType(0);
|
||||
setKeyListener(null);
|
||||
setOnFocusChangeListener((v, hasFocus) -> {
|
||||
if (!hasFocus) {
|
||||
v.setFocusableInTouchMode(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public final void setOnClickListener(OnClickListener onClickListener) {
|
||||
super.setOnClickListener(v -> {
|
||||
setFocusableInTouchMode(true);
|
||||
requestFocus();
|
||||
onClickListener.onClick(v);
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,142 @@
|
||||
package pl.szczodrzynski.edziennik.utils
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import androidx.appcompat.widget.PopupMenu
|
||||
import androidx.core.graphics.drawable.DrawableCompat
|
||||
import com.google.android.material.textfield.TextInputEditText
|
||||
import pl.szczodrzynski.edziennik.R
|
||||
|
||||
class TextInputDropDown : TextInputEditText {
|
||||
constructor(context: Context) : super(context) {
|
||||
create(context)
|
||||
}
|
||||
|
||||
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
|
||||
create(context)
|
||||
}
|
||||
|
||||
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
|
||||
create(context)
|
||||
}
|
||||
|
||||
var items = mutableListOf<Item>()
|
||||
private var onChangeListener: ((item: Item) -> Boolean)? = null
|
||||
|
||||
var selected: Item? = null
|
||||
val selectedId
|
||||
get() = selected?.id
|
||||
|
||||
fun updateText() {
|
||||
setText(selected?.displayText ?: selected?.text)
|
||||
}
|
||||
|
||||
fun create(context: Context) {
|
||||
val drawable = context.resources.getDrawable(R.drawable.dropdown_arrow)
|
||||
val wrappedDrawable = DrawableCompat.wrap(drawable)
|
||||
DrawableCompat.setTint(wrappedDrawable, Themes.getPrimaryTextColor(context))
|
||||
|
||||
setCompoundDrawablesWithIntrinsicBounds(null, null, wrappedDrawable, null)
|
||||
isFocusableInTouchMode = false
|
||||
isCursorVisible = false
|
||||
isLongClickable = false
|
||||
maxLines = 1
|
||||
inputType = 0
|
||||
keyListener = null
|
||||
setOnFocusChangeListener { v, hasFocus ->
|
||||
if (!hasFocus) {
|
||||
v.isFocusableInTouchMode = false
|
||||
}
|
||||
}
|
||||
|
||||
setOnClickListener {
|
||||
isFocusableInTouchMode = true
|
||||
requestFocus()
|
||||
val popup = PopupMenu(context, this)
|
||||
|
||||
items.forEachIndexed { index, item ->
|
||||
popup.menu.add(0, item.id.toInt(), index, item.text)
|
||||
}
|
||||
|
||||
popup.setOnMenuItemClickListener { menuItem ->
|
||||
val item = items[menuItem.order]
|
||||
if (onChangeListener?.invoke(item) != false) {
|
||||
select(item)
|
||||
}
|
||||
clearFocus()
|
||||
true
|
||||
}
|
||||
|
||||
popup.setOnDismissListener {
|
||||
clearFocus()
|
||||
}
|
||||
|
||||
popup.show()
|
||||
}
|
||||
}
|
||||
|
||||
fun select(item: Item) {
|
||||
selected = item
|
||||
updateText()
|
||||
}
|
||||
|
||||
fun select(id: Long?) {
|
||||
items.singleOrNull { it.id == id }?.let { select(it) }
|
||||
}
|
||||
|
||||
fun select(tag: Any?) {
|
||||
items.singleOrNull { it.tag == tag }?.let { select(it) }
|
||||
}
|
||||
|
||||
fun select(index: Int) {
|
||||
items.getOrNull(index)?.let { select(it) }
|
||||
}
|
||||
|
||||
fun deselect(): TextInputDropDown {
|
||||
selected = null
|
||||
text = null
|
||||
return this
|
||||
}
|
||||
|
||||
fun clear(): TextInputDropDown {
|
||||
items.clear()
|
||||
return this
|
||||
}
|
||||
|
||||
fun append(items: List<Item>): TextInputDropDown {
|
||||
this.items.addAll(items)
|
||||
return this
|
||||
}
|
||||
|
||||
fun prepend(items: List<Item>): TextInputDropDown{
|
||||
this.items.addAll(0, items)
|
||||
return this
|
||||
}
|
||||
|
||||
operator fun plusAssign(items: Item) {
|
||||
this.items.add(items)
|
||||
}
|
||||
operator fun plusAssign(items: List<Item>) {
|
||||
this.items.addAll(items)
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the listener called when other item is selected.
|
||||
*
|
||||
* The listener should return true to allow the item to be selected, false otherwise.
|
||||
*/
|
||||
fun setOnChangeListener(onChangeListener: ((item: Item) -> Boolean)? = null): TextInputDropDown {
|
||||
this.onChangeListener = onChangeListener
|
||||
return this
|
||||
}
|
||||
|
||||
override fun setOnClickListener(onClickListener: OnClickListener?) {
|
||||
super.setOnClickListener { v ->
|
||||
isFocusableInTouchMode = true
|
||||
requestFocus()
|
||||
onClickListener!!.onClick(v)
|
||||
}
|
||||
}
|
||||
|
||||
class Item(val id: Long, val text: CharSequence, val displayText: CharSequence? = null, val tag: Any? = null)
|
||||
}
|
@ -97,7 +97,8 @@
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:text="@string/dialog_event_manual_share_first_notice"
|
||||
android:visibility="gone" />
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
|
102
app/src/main/res/layout/dialog_event_manual_v2.xml
Normal file
102
app/src/main/res/layout/dialog_event_manual_v2.xml
Normal file
@ -0,0 +1,102 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (c) Kuba Szczodrzyński 2019-11-12.
|
||||
-->
|
||||
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
android:padding="24dp">
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.FilledBox.Dense"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/dialog_event_manual_date">
|
||||
<pl.szczodrzynski.edziennik.utils.TextInputDropDown
|
||||
android:id="@+id/dateDropdown"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:enabled="false"
|
||||
tools:text="13 listopada"/>
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.FilledBox.Dense"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:hint="@string/dialog_event_manual_time">
|
||||
<pl.szczodrzynski.edziennik.utils.TextInputDropDown
|
||||
android:id="@+id/timeDropdown"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:enabled="false"
|
||||
tools:text="8:10 - język polski"/>
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.Dense"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:hint="@string/dialog_event_manual_team">
|
||||
<pl.szczodrzynski.edziennik.utils.TextInputDropDown
|
||||
android:id="@+id/teamDropdown"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:enabled="false"
|
||||
tools:text="2b3T"/>
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.Dense"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:hint="@string/dialog_event_manual_subject">
|
||||
<pl.szczodrzynski.edziennik.utils.TextInputDropDown
|
||||
android:id="@+id/subjectDropdown"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:enabled="false"
|
||||
tools:text="2b3T"/>
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.Dense"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:hint="@string/dialog_event_manual_teacher">
|
||||
<pl.szczodrzynski.edziennik.utils.TextInputDropDown
|
||||
android:id="@+id/teacherDropdown"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:enabled="false"
|
||||
tools:text="2b3T"/>
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.Dense"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:hint="@string/dialog_event_manual_topic">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/topic"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="textLongMessage|textMultiLine|textImeMultiLine"
|
||||
android:minLines="2"
|
||||
tools:text="2b3T" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</layout>
|
@ -1013,4 +1013,13 @@
|
||||
<string name="dialog_lesson_details_number">Nr lekcji</string>
|
||||
<string name="dialog_lesson_details_shifted_to">Lekcja przeniesiona na %s</string>
|
||||
<string name="dialog_lesson_details_shifted_from">Lekcja przeniesiona z %s</string>
|
||||
<string name="dialog_event_manual_title">Dodaj wpis do terminarza</string>
|
||||
<string name="dialog_event_manual_time">Lekcja/godzina</string>
|
||||
<string name="dialog_event_manual_date_next_lesson">nast. lekcja %s</string>
|
||||
<string name="dialog_event_manual_date_tomorrow">jutro (%s)</string>
|
||||
<string name="dialog_event_manual_date_this_week">%s (%s)</string>
|
||||
<string name="dialog_event_manual_date_other">-- inna data --</string>
|
||||
<string name="dialog_event_manual_date_today">dzisiaj (%s)</string>
|
||||
<string name="dialog_event_manual_date_next_week">następny %s (%s)</string>
|
||||
<string name="dialog_event_manual_no_lessons">Nie ma lekcji tego dnia</string>
|
||||
</resources>
|
||||
|
Loading…
x
Reference in New Issue
Block a user