mirror of
https://github.com/szkolny-eu/szkolny-android.git
synced 2025-01-18 12:56:45 -06:00
[UI] Refactor app dialogs. (#103)
* [UI] Add new base dialog classes. * [UI] Migrate dialogs to the new base classes.
This commit is contained in:
parent
fd62653d79
commit
f3e2d21b89
@ -420,7 +420,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
App.db.profileDao().getByIdNow(profile.identifier.toInt())
|
||||
} ?: return@launch
|
||||
drawer.close()
|
||||
ProfileConfigDialog(this@MainActivity, appProfile)
|
||||
ProfileConfigDialog(this@MainActivity, appProfile).show()
|
||||
}
|
||||
true
|
||||
} else {
|
||||
@ -529,7 +529,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
if (app.config.appVersion < BuildConfig.VERSION_CODE) {
|
||||
// force an AppSync after update
|
||||
app.config.sync.lastAppSync = 0L
|
||||
ChangelogDialog(this)
|
||||
ChangelogDialog(this).show()
|
||||
if (app.config.appVersion < 170) {
|
||||
//Intent intent = new Intent(this, ChangelogIntroActivity.class);
|
||||
//startActivity(intent);
|
||||
@ -587,7 +587,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
.withIcon(CommunityMaterial.Icon.cmd_download_outline)
|
||||
.withOnClickListener {
|
||||
bottomSheet.close()
|
||||
SyncViewListDialog(this, navTargetId)
|
||||
SyncViewListDialog(this, navTargetId).show()
|
||||
},
|
||||
BottomSheetSeparatorItem(false),
|
||||
BottomSheetPrimaryItem(false)
|
||||
@ -690,7 +690,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
Type.NOT_AVAILABLE -> {
|
||||
swipeRefreshLayout.isRefreshing = false
|
||||
loadTarget(DRAWER_ITEM_HOME)
|
||||
RegisterUnavailableDialog(this, error.status!!)
|
||||
RegisterUnavailableDialog(this, error.status!!).show()
|
||||
return
|
||||
}
|
||||
Type.API_ERROR -> {
|
||||
@ -722,7 +722,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
|
||||
fun onUpdateEvent(event: Update) {
|
||||
EventBus.getDefault().removeStickyEvent(event)
|
||||
UpdateAvailableDialog(this, event)
|
||||
UpdateAvailableDialog(this, event).show()
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
|
||||
@ -730,7 +730,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
EventBus.getDefault().removeStickyEvent(event)
|
||||
val error = app.availabilityManager.check(app.profile, cacheOnly = true)
|
||||
if (error != null) {
|
||||
RegisterUnavailableDialog(this, error.status!!)
|
||||
RegisterUnavailableDialog(this, error.status!!).show()
|
||||
}
|
||||
}
|
||||
|
||||
@ -797,7 +797,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
if (event.error.errorCode == ERROR_VULCAN_API_DEPRECATED) {
|
||||
if (event.error.profileId != App.profileId)
|
||||
return
|
||||
ErrorDetailsDialog(this, listOf(event.error))
|
||||
ErrorDetailsDialog(this, listOf(event.error)).show()
|
||||
}
|
||||
navView.toolbar.apply {
|
||||
subtitleFormat = R.string.toolbar_subtitle
|
||||
@ -894,7 +894,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
this,
|
||||
extras.getString("serverMessageTitle") ?: getString(R.string.app_name),
|
||||
extras.getString("serverMessageText") ?: ""
|
||||
)
|
||||
).show()
|
||||
true
|
||||
}
|
||||
"feedbackMessage" -> {
|
||||
@ -917,7 +917,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
this,
|
||||
App.profileId,
|
||||
defaultDate = date
|
||||
)
|
||||
).show()
|
||||
true
|
||||
}
|
||||
else -> false
|
||||
|
@ -103,7 +103,7 @@ class SzkolnyApi(val app: App) : CoroutineScope {
|
||||
activity,
|
||||
listOf(apiError),
|
||||
R.string.error_occured
|
||||
)
|
||||
).show()
|
||||
null
|
||||
}
|
||||
null
|
||||
|
@ -77,14 +77,14 @@ class AgendaFragment : Fragment(), CoroutineScope {
|
||||
activity,
|
||||
app.profileId,
|
||||
defaultDate = AgendaFragmentDefault.selectedDate
|
||||
)
|
||||
).show()
|
||||
},
|
||||
BottomSheetPrimaryItem(true)
|
||||
.withTitle(R.string.menu_agenda_config)
|
||||
.withIcon(CommunityMaterial.Icon.cmd_cog_outline)
|
||||
.withOnClickListener {
|
||||
activity.bottomSheet.close()
|
||||
AgendaConfigDialog(activity, true, null, null)
|
||||
AgendaConfigDialog(activity, true, null, null).show()
|
||||
},
|
||||
BottomSheetPrimaryItem(true)
|
||||
.withTitle(R.string.menu_agenda_change_view)
|
||||
@ -124,7 +124,7 @@ class AgendaFragment : Fragment(), CoroutineScope {
|
||||
activity,
|
||||
app.profileId,
|
||||
defaultDate = AgendaFragmentDefault.selectedDate
|
||||
)
|
||||
).show()
|
||||
}
|
||||
|
||||
activity.gainAttention()
|
||||
@ -188,7 +188,7 @@ class AgendaFragment : Fragment(), CoroutineScope {
|
||||
unreadEventDates.remove(date.value)
|
||||
}
|
||||
|
||||
DayDialog(activity, app.profileId, date)
|
||||
DayDialog(activity, app.profileId, date).show()
|
||||
}}
|
||||
|
||||
b.progressBar.visibility = View.GONE
|
||||
|
@ -139,7 +139,7 @@ class AgendaFragmentDefault(
|
||||
val c = Calendar.getInstance()
|
||||
c.time = dayItem.date
|
||||
if (c.timeInMillis == selectedDate.inMillis) {
|
||||
DayDialog(activity, app.profileId, selectedDate)
|
||||
DayDialog(activity, app.profileId, selectedDate).show()
|
||||
}
|
||||
}
|
||||
|
||||
@ -147,16 +147,25 @@ class AgendaFragmentDefault(
|
||||
val date = Date.fromCalendar(event.instanceDay)
|
||||
|
||||
when (event) {
|
||||
is AgendaEvent -> EventDetailsDialog(activity, event.event)
|
||||
is LessonChangesEvent -> LessonChangesDialog(activity, app.profileId, date)
|
||||
is AgendaEvent -> EventDetailsDialog(activity, event.event).show()
|
||||
is LessonChangesEvent -> LessonChangesDialog(
|
||||
activity = activity,
|
||||
profileId = app.profileId,
|
||||
defaultDate = date
|
||||
).show()
|
||||
is TeacherAbsenceEvent -> TeacherAbsenceDialog(
|
||||
activity,
|
||||
app.profileId,
|
||||
date
|
||||
)
|
||||
is AgendaEventGroup -> DayDialog(activity, app.profileId, date, eventTypeId = event.typeId)
|
||||
activity = activity,
|
||||
profileId = app.profileId,
|
||||
date = date
|
||||
).show()
|
||||
is AgendaEventGroup -> DayDialog(
|
||||
activity = activity,
|
||||
profileId = app.profileId,
|
||||
date = date,
|
||||
eventTypeId = event.typeId,
|
||||
).show()
|
||||
is BaseCalendarEvent -> if (event.isPlaceHolder)
|
||||
DayDialog(activity, app.profileId, date)
|
||||
DayDialog(activity, app.profileId, date).show()
|
||||
}
|
||||
|
||||
if (event is BaseEvent && event.showItemBadge) {
|
||||
|
@ -4,12 +4,11 @@
|
||||
|
||||
package pl.szczodrzynski.edziennik.ui.agenda
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import kotlinx.coroutines.*
|
||||
import pl.szczodrzynski.edziennik.*
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Lesson
|
||||
@ -23,6 +22,7 @@ import pl.szczodrzynski.edziennik.ui.agenda.lessonchanges.LessonChangesEventRend
|
||||
import pl.szczodrzynski.edziennik.ui.agenda.teacherabsence.TeacherAbsenceDialog
|
||||
import pl.szczodrzynski.edziennik.ui.agenda.teacherabsence.TeacherAbsenceEvent
|
||||
import pl.szczodrzynski.edziennik.ui.agenda.teacherabsence.TeacherAbsenceEventRenderer
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.base.BindingDialog
|
||||
import pl.szczodrzynski.edziennik.ui.event.EventDetailsDialog
|
||||
import pl.szczodrzynski.edziennik.ui.event.EventListAdapter
|
||||
import pl.szczodrzynski.edziennik.ui.event.EventManualDialog
|
||||
@ -30,61 +30,39 @@ import pl.szczodrzynski.edziennik.utils.SimpleDividerItemDecoration
|
||||
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 DayDialog(
|
||||
val activity: AppCompatActivity,
|
||||
val profileId: Int,
|
||||
val date: Date,
|
||||
val eventTypeId: Long? = null,
|
||||
val onShowListener: ((tag: String) -> Unit)? = null,
|
||||
val onDismissListener: ((tag: String) -> Unit)? = null
|
||||
) : CoroutineScope {
|
||||
companion object {
|
||||
private const val TAG = "DayDialog"
|
||||
}
|
||||
activity: AppCompatActivity,
|
||||
private val profileId: Int,
|
||||
private val date: Date,
|
||||
private val eventTypeId: Long? = null,
|
||||
onShowListener: ((tag: String) -> Unit)? = null,
|
||||
onDismissListener: ((tag: String) -> Unit)? = null,
|
||||
) : BindingDialog<DialogDayBinding>(activity, onShowListener, onDismissListener) {
|
||||
|
||||
private lateinit var app: App
|
||||
private lateinit var b: DialogDayBinding
|
||||
private lateinit var dialog: AlertDialog
|
||||
override val TAG = "DayDialog"
|
||||
|
||||
private val job = Job()
|
||||
override val coroutineContext: CoroutineContext
|
||||
get() = job + Dispatchers.Main
|
||||
override fun getTitleRes(): Int? = null
|
||||
override fun inflate(layoutInflater: LayoutInflater) =
|
||||
DialogDayBinding.inflate(layoutInflater)
|
||||
|
||||
override fun getPositiveButtonText() = R.string.close
|
||||
override fun getNeutralButtonText() = R.string.add
|
||||
|
||||
private lateinit var adapter: EventListAdapter
|
||||
|
||||
init { run {
|
||||
if (activity.isFinishing)
|
||||
return@run
|
||||
onShowListener?.invoke(TAG)
|
||||
app = activity.applicationContext as App
|
||||
b = DialogDayBinding.inflate(activity.layoutInflater)
|
||||
dialog = MaterialAlertDialogBuilder(activity)
|
||||
.setView(b.root)
|
||||
.setPositiveButton(R.string.close) { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
}
|
||||
.setNeutralButton(R.string.add, null)
|
||||
.setOnDismissListener {
|
||||
onDismissListener?.invoke(TAG)
|
||||
}
|
||||
.show()
|
||||
|
||||
dialog.getButton(AlertDialog.BUTTON_NEUTRAL)?.onClick {
|
||||
override suspend fun onNeutralClick(): Boolean {
|
||||
EventManualDialog(
|
||||
activity,
|
||||
profileId,
|
||||
defaultDate = date,
|
||||
onShowListener = onShowListener,
|
||||
onDismissListener = onDismissListener
|
||||
)
|
||||
).show()
|
||||
return NO_DISMISS
|
||||
}
|
||||
|
||||
update()
|
||||
}}
|
||||
|
||||
private fun update() { launch {
|
||||
override suspend fun onShow() {
|
||||
b.dayDate.setText(
|
||||
R.string.dialog_day_date_format,
|
||||
Week.getFullDayName(date.weekDay),
|
||||
@ -95,7 +73,8 @@ class DayDialog(
|
||||
app.db.timetableDao().getAllForDateNow(profileId, date)
|
||||
}.filter { it.type != Lesson.TYPE_NO_LESSONS }
|
||||
|
||||
if (lessons.isNotEmpty()) { run {
|
||||
if (lessons.isNotEmpty()) {
|
||||
run {
|
||||
val startTime = lessons.first().startTime ?: return@run
|
||||
val endTime = lessons.last().endTime ?: return@run
|
||||
val diff = Time.diff(startTime, endTime)
|
||||
@ -110,7 +89,8 @@ class DayDialog(
|
||||
)
|
||||
|
||||
b.lessonsInfo.visibility = View.VISIBLE
|
||||
}}
|
||||
}
|
||||
}
|
||||
|
||||
val lessonChanges = withContext(Dispatchers.Default) {
|
||||
app.db.timetableDao().getChangesForDateNow(profileId, date)
|
||||
@ -133,7 +113,7 @@ class DayDialog(
|
||||
date,
|
||||
onShowListener = onShowListener,
|
||||
onDismissListener = onDismissListener
|
||||
)
|
||||
).show()
|
||||
}
|
||||
}
|
||||
b.lessonChangesFrame.isVisible = lessonChanges.isNotEmpty()
|
||||
@ -158,7 +138,7 @@ class DayDialog(
|
||||
date,
|
||||
onShowListener = onShowListener,
|
||||
onDismissListener = onDismissListener
|
||||
)
|
||||
).show()
|
||||
}
|
||||
}
|
||||
b.teacherAbsenceFrame.isVisible = teacherAbsences.isNotEmpty()
|
||||
@ -177,7 +157,7 @@ class DayDialog(
|
||||
it,
|
||||
onShowListener = onShowListener,
|
||||
onDismissListener = onDismissListener
|
||||
)
|
||||
).show()
|
||||
},
|
||||
onEventEditClick = {
|
||||
EventManualDialog(
|
||||
@ -186,7 +166,7 @@ class DayDialog(
|
||||
editingEvent = it,
|
||||
onShowListener = onShowListener,
|
||||
onDismissListener = onDismissListener
|
||||
)
|
||||
).show()
|
||||
}
|
||||
)
|
||||
|
||||
@ -217,5 +197,5 @@ class DayDialog(
|
||||
b.eventsNoData.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
}}
|
||||
}
|
||||
}
|
||||
|
@ -1,55 +1,34 @@
|
||||
package pl.szczodrzynski.edziennik.ui.agenda.lessonchanges
|
||||
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import android.view.LayoutInflater
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import kotlinx.coroutines.*
|
||||
import pl.szczodrzynski.edziennik.App
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import pl.szczodrzynski.edziennik.R
|
||||
import pl.szczodrzynski.edziennik.databinding.DialogLessonChangeListBinding
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.base.BindingDialog
|
||||
import pl.szczodrzynski.edziennik.ui.timetable.LessonDetailsDialog
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
class LessonChangesDialog(
|
||||
val activity: AppCompatActivity,
|
||||
val profileId: Int,
|
||||
activity: AppCompatActivity,
|
||||
private val profileId: Int,
|
||||
private val defaultDate: Date,
|
||||
val onShowListener: ((tag: String) -> Unit)? = null,
|
||||
val onDismissListener: ((tag: String) -> Unit)? = null
|
||||
) : CoroutineScope {
|
||||
companion object {
|
||||
const val TAG = "LessonChangeDialog"
|
||||
}
|
||||
onShowListener: ((tag: String) -> Unit)? = null,
|
||||
onDismissListener: ((tag: String) -> Unit)? = null,
|
||||
) : BindingDialog<DialogLessonChangeListBinding>(activity, onShowListener, onDismissListener) {
|
||||
|
||||
private val app by lazy { activity.application as App }
|
||||
override val TAG = "LessonChangesDialog"
|
||||
|
||||
private lateinit var job: Job
|
||||
override val coroutineContext: CoroutineContext
|
||||
get() = job + Dispatchers.Main
|
||||
override fun getTitle(): String = defaultDate.formattedString
|
||||
override fun getTitleRes(): Int? = null
|
||||
override fun inflate(layoutInflater: LayoutInflater) =
|
||||
DialogLessonChangeListBinding.inflate(layoutInflater)
|
||||
|
||||
private lateinit var b: DialogLessonChangeListBinding
|
||||
private lateinit var dialog: AlertDialog
|
||||
override fun getPositiveButtonText() = R.string.close
|
||||
|
||||
init { run {
|
||||
if (activity.isFinishing)
|
||||
return@run
|
||||
job = Job()
|
||||
onShowListener?.invoke(TAG)
|
||||
b = DialogLessonChangeListBinding.inflate(activity.layoutInflater)
|
||||
dialog = MaterialAlertDialogBuilder(activity)
|
||||
.setTitle(defaultDate.formattedString)
|
||||
.setView(b.root)
|
||||
.setPositiveButton(R.string.close) { dialog, _ -> dialog.dismiss() }
|
||||
.setOnDismissListener {
|
||||
onDismissListener?.invoke(TAG)
|
||||
}
|
||||
.create()
|
||||
loadLessonChanges()
|
||||
}}
|
||||
|
||||
private fun loadLessonChanges() { launch {
|
||||
override suspend fun onShow() {
|
||||
val lessonChanges = withContext(Dispatchers.Default) {
|
||||
app.db.timetableDao().getChangesForDateNow(profileId, defaultDate)
|
||||
}
|
||||
@ -62,7 +41,7 @@ class LessonChangesDialog(
|
||||
it,
|
||||
onShowListener = onShowListener,
|
||||
onDismissListener = onDismissListener
|
||||
)
|
||||
).show()
|
||||
}
|
||||
).apply {
|
||||
items = lessonChanges
|
||||
@ -70,7 +49,5 @@ class LessonChangesDialog(
|
||||
|
||||
b.lessonChangeView.adapter = adapter
|
||||
b.lessonChangeView.layoutManager = LinearLayoutManager(activity)
|
||||
|
||||
dialog.show()
|
||||
}}
|
||||
}
|
||||
}
|
||||
|
@ -1,57 +1,42 @@
|
||||
package pl.szczodrzynski.edziennik.ui.agenda.teacherabsence
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import pl.szczodrzynski.edziennik.App
|
||||
import pl.szczodrzynski.edziennik.R
|
||||
import pl.szczodrzynski.edziennik.databinding.DialogTeacherAbsenceListBinding
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.base.BindingDialog
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
|
||||
class TeacherAbsenceDialog(
|
||||
val activity: AppCompatActivity,
|
||||
val profileId: Int,
|
||||
val date: Date,
|
||||
val onShowListener: ((tag: String) -> Unit)? = null,
|
||||
val onDismissListener: ((tag: String) -> Unit)? = null
|
||||
) {
|
||||
companion object {
|
||||
private const val TAG = "TeacherAbsenceDialog"
|
||||
}
|
||||
activity: AppCompatActivity,
|
||||
private val profileId: Int,
|
||||
private val date: Date,
|
||||
onShowListener: ((tag: String) -> Unit)? = null,
|
||||
onDismissListener: ((tag: String) -> Unit)? = null,
|
||||
) : BindingDialog<DialogTeacherAbsenceListBinding>(activity, onShowListener, onDismissListener) {
|
||||
|
||||
private val app by lazy { activity.application as App }
|
||||
override val TAG = "TeacherAbsenceDialog"
|
||||
|
||||
private lateinit var b: DialogTeacherAbsenceListBinding
|
||||
private lateinit var dialog: AlertDialog
|
||||
override fun getTitle(): String = date.formattedString
|
||||
override fun getTitleRes(): Int? = null
|
||||
override fun inflate(layoutInflater: LayoutInflater) =
|
||||
DialogTeacherAbsenceListBinding.inflate(layoutInflater)
|
||||
|
||||
init { run {
|
||||
if (activity.isFinishing)
|
||||
return@run
|
||||
|
||||
b = DialogTeacherAbsenceListBinding.inflate(activity.layoutInflater)
|
||||
|
||||
dialog = MaterialAlertDialogBuilder(activity)
|
||||
.setTitle(date.formattedString)
|
||||
.setView(b.root)
|
||||
.setPositiveButton(R.string.close) { dialog, _ -> dialog.dismiss() }
|
||||
.setOnDismissListener {
|
||||
onDismissListener?.invoke(TAG)
|
||||
}
|
||||
.create()
|
||||
override fun getPositiveButtonText() = R.string.close
|
||||
|
||||
override suspend fun onShow() {
|
||||
b.teacherAbsenceView.setHasFixedSize(true)
|
||||
b.teacherAbsenceView.layoutManager = LinearLayoutManager(activity)
|
||||
|
||||
app.db.teacherAbsenceDao().getAllByDate(profileId, date).observe(activity as LifecycleOwner, Observer { absenceList ->
|
||||
app.db.teacherAbsenceDao().getAllByDate(profileId, date).observe(
|
||||
activity as LifecycleOwner
|
||||
) { absenceList ->
|
||||
val adapter = TeacherAbsenceAdapter(activity, date, absenceList)
|
||||
b.teacherAbsenceView.adapter = adapter
|
||||
b.teacherAbsenceView.visibility = View.VISIBLE
|
||||
})
|
||||
|
||||
dialog.show()
|
||||
}}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,54 +4,33 @@
|
||||
|
||||
package pl.szczodrzynski.edziennik.ui.attendance
|
||||
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import android.view.LayoutInflater
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.graphics.ColorUtils
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import pl.szczodrzynski.edziennik.App
|
||||
import pl.szczodrzynski.edziennik.R
|
||||
import pl.szczodrzynski.edziennik.data.db.full.AttendanceFull
|
||||
import pl.szczodrzynski.edziennik.databinding.AttendanceDetailsDialogBinding
|
||||
import pl.szczodrzynski.edziennik.ext.setTintColor
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.base.BindingDialog
|
||||
import pl.szczodrzynski.edziennik.utils.BetterLink
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
class AttendanceDetailsDialog(
|
||||
val activity: AppCompatActivity,
|
||||
val attendance: AttendanceFull,
|
||||
val onShowListener: ((tag: String) -> Unit)? = null,
|
||||
val onDismissListener: ((tag: String) -> Unit)? = null
|
||||
) : CoroutineScope {
|
||||
companion object {
|
||||
private const val TAG = "AttendanceDetailsDialog"
|
||||
}
|
||||
activity: AppCompatActivity,
|
||||
private val attendance: AttendanceFull,
|
||||
onShowListener: ((tag: String) -> Unit)? = null,
|
||||
onDismissListener: ((tag: String) -> Unit)? = null,
|
||||
) : BindingDialog<AttendanceDetailsDialogBinding>(activity, onShowListener, onDismissListener) {
|
||||
|
||||
private lateinit var app: App
|
||||
private lateinit var b: AttendanceDetailsDialogBinding
|
||||
private lateinit var dialog: AlertDialog
|
||||
override val TAG = "AttendanceDetailsDialog"
|
||||
|
||||
private val job = Job()
|
||||
override val coroutineContext: CoroutineContext
|
||||
get() = job + Dispatchers.Main
|
||||
override fun getTitleRes(): Int? = null
|
||||
override fun inflate(layoutInflater: LayoutInflater) =
|
||||
AttendanceDetailsDialogBinding.inflate(layoutInflater)
|
||||
|
||||
// local variables go here
|
||||
override fun getPositiveButtonText() = R.string.close
|
||||
|
||||
init { run {
|
||||
if (activity.isFinishing)
|
||||
return@run
|
||||
onShowListener?.invoke(TAG)
|
||||
app = activity.applicationContext as App
|
||||
b = AttendanceDetailsDialogBinding.inflate(activity.layoutInflater)
|
||||
dialog = MaterialAlertDialogBuilder(activity)
|
||||
.setView(b.root)
|
||||
.setPositiveButton(R.string.close, null)
|
||||
.setOnDismissListener {
|
||||
onDismissListener?.invoke(TAG)
|
||||
}
|
||||
.show()
|
||||
override suspend fun onShow() {
|
||||
val manager = app.attendanceManager
|
||||
|
||||
val attendanceColor = manager.getAttendanceColor(attendance)
|
||||
@ -69,5 +48,5 @@ class AttendanceDetailsDialog(
|
||||
onActionSelected = dialog::dismiss
|
||||
)
|
||||
}
|
||||
}}
|
||||
}
|
||||
}
|
||||
|
@ -67,7 +67,7 @@ class AttendanceFragment : Fragment(), CoroutineScope {
|
||||
.withIcon(CommunityMaterial.Icon.cmd_cog_outline)
|
||||
.withOnClickListener(View.OnClickListener {
|
||||
activity.bottomSheet.close()
|
||||
AttendanceConfigDialog(activity, true, null, null)
|
||||
AttendanceConfigDialog(activity, true, null, null).show()
|
||||
}),
|
||||
BottomSheetSeparatorItem(true),
|
||||
BottomSheetPrimaryItem(true)
|
||||
|
@ -96,7 +96,7 @@ class AttendanceListFragment : LazyFragment(), CoroutineScope {
|
||||
}})
|
||||
|
||||
adapter.onAttendanceClick = {
|
||||
AttendanceDetailsDialog(activity, it)
|
||||
AttendanceDetailsDialog(activity, it).show()
|
||||
}
|
||||
}; return true}
|
||||
|
||||
|
@ -108,7 +108,7 @@ class AttendanceSummaryFragment : LazyFragment(), CoroutineScope {
|
||||
}})
|
||||
|
||||
adapter.onAttendanceClick = {
|
||||
AttendanceDetailsDialog(activity, it)
|
||||
AttendanceDetailsDialog(activity, it).show()
|
||||
}
|
||||
|
||||
b.toggleGroup.check(when (periodSelection) {
|
||||
|
@ -5,58 +5,34 @@
|
||||
package pl.szczodrzynski.edziennik.ui.captcha
|
||||
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import pl.szczodrzynski.edziennik.App
|
||||
import pl.szczodrzynski.edziennik.R
|
||||
import pl.szczodrzynski.edziennik.databinding.RecaptchaViewBinding
|
||||
import pl.szczodrzynski.edziennik.ext.onClick
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.base.BindingDialog
|
||||
|
||||
class LibrusCaptchaDialog(
|
||||
val activity: AppCompatActivity,
|
||||
val onSuccess: (recaptchaCode: String) -> Unit,
|
||||
val onFailure: (() -> Unit)?,
|
||||
val onShowListener: ((tag: String) -> Unit)? = null,
|
||||
val onDismissListener: ((tag: String) -> Unit)? = null
|
||||
) : CoroutineScope {
|
||||
companion object {
|
||||
private const val TAG = "LibrusCaptchaDialog"
|
||||
}
|
||||
activity: AppCompatActivity,
|
||||
private val onSuccess: (recaptchaCode: String) -> Unit,
|
||||
private val onFailure: (() -> Unit)?,
|
||||
onShowListener: ((tag: String) -> Unit)? = null,
|
||||
onDismissListener: ((tag: String) -> Unit)? = null,
|
||||
) : BindingDialog<RecaptchaViewBinding>(activity, onShowListener, onDismissListener) {
|
||||
override val TAG = "LibrusCaptchaDialog"
|
||||
|
||||
private lateinit var app: App
|
||||
private lateinit var b: RecaptchaViewBinding
|
||||
private lateinit var dialog: AlertDialog
|
||||
override fun getTitleRes(): Int? = null
|
||||
override fun inflate(layoutInflater: LayoutInflater) =
|
||||
RecaptchaViewBinding.inflate(layoutInflater)
|
||||
|
||||
private val job = Job()
|
||||
override val coroutineContext: CoroutineContext
|
||||
get() = job + Dispatchers.Main
|
||||
override fun getNegativeButtonText() = R.string.cancel
|
||||
|
||||
private lateinit var checkboxBackground: Drawable
|
||||
private lateinit var checkboxForeground: Drawable
|
||||
private var success = false
|
||||
|
||||
init { run {
|
||||
if (activity.isFinishing)
|
||||
return@run
|
||||
onShowListener?.invoke(TAG)
|
||||
app = activity.applicationContext as App
|
||||
b = RecaptchaViewBinding.inflate(activity.layoutInflater)
|
||||
dialog = MaterialAlertDialogBuilder(activity)
|
||||
.setView(b.root)
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.setOnDismissListener {
|
||||
if (!success)
|
||||
onFailure?.invoke()
|
||||
onDismissListener?.invoke(TAG)
|
||||
}
|
||||
.show()
|
||||
|
||||
override suspend fun onShow() {
|
||||
checkboxBackground = b.checkbox.background
|
||||
checkboxForeground = b.checkbox.foreground
|
||||
success = false
|
||||
@ -85,7 +61,12 @@ class LibrusCaptchaDialog(
|
||||
b.checkbox.foreground = checkboxForeground
|
||||
b.progress.visibility = View.GONE
|
||||
}
|
||||
)
|
||||
).show()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDismiss() {
|
||||
if (!success)
|
||||
onFailure?.invoke()
|
||||
}
|
||||
}}
|
||||
}
|
||||
|
@ -6,129 +6,56 @@ package pl.szczodrzynski.edziennik.ui.captcha
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.BitmapFactory
|
||||
import android.os.Handler
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import kotlinx.coroutines.*
|
||||
import okhttp3.*
|
||||
import pl.szczodrzynski.edziennik.App
|
||||
import pl.szczodrzynski.edziennik.R
|
||||
import pl.szczodrzynski.edziennik.databinding.RecaptchaDialogBinding
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.base.BindingDialog
|
||||
import java.io.IOException
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import kotlin.coroutines.resume
|
||||
import kotlin.coroutines.suspendCoroutine
|
||||
|
||||
class RecaptchaDialog(
|
||||
val activity: AppCompatActivity,
|
||||
val siteKey: String,
|
||||
val referer: String,
|
||||
val autoRetry: Boolean = true,
|
||||
val onSuccess: (recaptchaCode: String) -> Unit,
|
||||
val onFailure: (() -> Unit)? = null,
|
||||
val onShowListener: ((tag: String) -> Unit)? = null,
|
||||
val onDismissListener: ((tag: String) -> Unit)? = null
|
||||
) : CoroutineScope {
|
||||
companion object {
|
||||
private const val TAG = "RecaptchaDialog"
|
||||
}
|
||||
activity: AppCompatActivity,
|
||||
private val siteKey: String,
|
||||
private val referer: String,
|
||||
private val autoRetry: Boolean = true,
|
||||
private val onSuccess: (recaptchaCode: String) -> Unit,
|
||||
private val onFailure: (() -> Unit)? = null,
|
||||
onShowListener: ((tag: String) -> Unit)? = null,
|
||||
onDismissListener: ((tag: String) -> Unit)? = null,
|
||||
) : BindingDialog<RecaptchaDialogBinding>(activity, onShowListener, onDismissListener) {
|
||||
|
||||
private lateinit var app: App
|
||||
private val b by lazy { RecaptchaDialogBinding.inflate(LayoutInflater.from(activity)) }
|
||||
private var dialog: AlertDialog? = null
|
||||
override val TAG = "RecaptchaDialog"
|
||||
|
||||
override fun getTitleRes(): Int? = null
|
||||
override fun inflate(layoutInflater: LayoutInflater) =
|
||||
RecaptchaDialogBinding.inflate(layoutInflater)
|
||||
|
||||
override fun getPositiveButtonText() = R.string.ok
|
||||
|
||||
private val captchaUrl = "https://www.google.com/recaptcha/api/fallback?k=$siteKey"
|
||||
private var success = false
|
||||
|
||||
private val job = Job()
|
||||
override val coroutineContext: CoroutineContext
|
||||
get() = job + Dispatchers.Main
|
||||
|
||||
private var code = ""
|
||||
private var payload = ""
|
||||
|
||||
init { run {
|
||||
if (activity.isFinishing)
|
||||
return@run
|
||||
app = activity.applicationContext as App
|
||||
onShowListener?.invoke(TAG)
|
||||
success = false
|
||||
|
||||
launch { initCaptcha() }
|
||||
}}
|
||||
|
||||
private suspend fun initCaptcha() {
|
||||
withContext(Dispatchers.Default) {
|
||||
val request = Request.Builder()
|
||||
.url(captchaUrl)
|
||||
.addHeader("Referer", referer)
|
||||
.addHeader("Accept-Language", "pl")
|
||||
.build()
|
||||
app.http.newCall(request).enqueue(object : Callback {
|
||||
override fun onResponse(call: Call, response: Response) {
|
||||
val html = response.body()?.string() ?: return
|
||||
Log.d(TAG, html)
|
||||
parseHtml(html)
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call, e: IOException) {
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private fun parseHtml(html: String) {
|
||||
launch {
|
||||
"class=\"rc-imageselect-desc(?:-no-canonical)?\">(.+?) <strong>(.+?)</strong>".toRegex().find(html)?.let {
|
||||
b.descTitle.text = it.groupValues[1]
|
||||
b.descText.text = it.groupValues[2]
|
||||
}
|
||||
code = "name=\"c\" value=\"([A-z0-9-_]+)\"".toRegex().find(html)?.let { it.groupValues[1] } ?: return@launch
|
||||
payload = "https://www.google.com/recaptcha/api2/payload?c=$code&k=$siteKey"
|
||||
withContext(Dispatchers.Default) {
|
||||
val request = Request.Builder()
|
||||
.url(payload)
|
||||
.addHeader("Referer", captchaUrl)
|
||||
.addHeader("Accept-Language", "pl")
|
||||
.build()
|
||||
app.http.newCall(request).enqueue(object : Callback {
|
||||
override fun onResponse(call: Call, response: Response) {
|
||||
val bitmap: Bitmap? = BitmapFactory.decodeStream(response.body()?.byteStream())
|
||||
Handler(activity.mainLooper).post {
|
||||
if (bitmap == null) {
|
||||
override suspend fun onBeforeShow(): Boolean {
|
||||
val (title, text, bitmap) = withContext(Dispatchers.Default) {
|
||||
val html = loadCaptchaHtml() ?: return@withContext null
|
||||
return@withContext loadCaptchaData(html)
|
||||
} ?: run {
|
||||
onFailure?.invoke()
|
||||
Toast.makeText(activity, "Nie udało się załadować reCAPTCHA.", Toast.LENGTH_SHORT).show()
|
||||
return@post
|
||||
}
|
||||
b.payload.setImageBitmap(bitmap)
|
||||
showDialog()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call, e: IOException) {
|
||||
onFailure?.invoke()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
initViews(title, text, bitmap)
|
||||
return true
|
||||
}
|
||||
|
||||
private fun showDialog() {
|
||||
if (dialog == null) {
|
||||
dialog = MaterialAlertDialogBuilder(activity)
|
||||
.setView(b.root)
|
||||
.setPositiveButton("OK") { _, _ ->
|
||||
validateAnswer()
|
||||
}
|
||||
.setOnDismissListener {
|
||||
if (!success)
|
||||
onFailure?.invoke()
|
||||
onDismissListener?.invoke(TAG)
|
||||
}
|
||||
.create()
|
||||
}
|
||||
override suspend fun onShow() {
|
||||
b.image0.isChecked = false
|
||||
b.image1.isChecked = false
|
||||
b.image2.isChecked = false
|
||||
@ -138,11 +65,88 @@ class RecaptchaDialog(
|
||||
b.image6.isChecked = false
|
||||
b.image7.isChecked = false
|
||||
b.image8.isChecked = false
|
||||
dialog!!.show()
|
||||
}
|
||||
|
||||
private fun validateAnswer() {
|
||||
launch {
|
||||
override fun onDismiss() {
|
||||
if (!success)
|
||||
onFailure?.invoke()
|
||||
}
|
||||
|
||||
private fun initViews(title: String, text: String, bitmap: Bitmap) {
|
||||
b.descTitle.text = title
|
||||
b.descText.text = text
|
||||
b.payload.setImageBitmap(bitmap)
|
||||
}
|
||||
|
||||
private suspend fun loadCaptchaHtml(): String? {
|
||||
val request = Request.Builder()
|
||||
.url(captchaUrl)
|
||||
.addHeader("Referer", referer)
|
||||
.addHeader("Accept-Language", "pl")
|
||||
.build()
|
||||
|
||||
return suspendCoroutine { cont ->
|
||||
app.http.newCall(request).enqueue(object : Callback {
|
||||
override fun onResponse(call: Call, response: Response) {
|
||||
val html = response.body()?.string()
|
||||
cont.resume(html)
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call, e: IOException) {
|
||||
cont.resume(null)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun loadCaptchaData(html: String): Triple<String, String, Bitmap>? {
|
||||
var title = ""
|
||||
var text = ""
|
||||
"class=\"rc-imageselect-desc(?:-no-canonical)?\">(.+?) <strong>(.+?)</strong>"
|
||||
.toRegex()
|
||||
.find(html)
|
||||
?.let {
|
||||
title = it.groupValues[1]
|
||||
text = it.groupValues[2]
|
||||
}
|
||||
|
||||
code = "name=\"c\" value=\"([A-z0-9-_]+)\""
|
||||
.toRegex()
|
||||
.find(html)
|
||||
?.let { it.groupValues[1] }
|
||||
?: return null
|
||||
|
||||
payload = "https://www.google.com/recaptcha/api2/payload?c=$code&k=$siteKey"
|
||||
val request = Request.Builder()
|
||||
.url(payload)
|
||||
.addHeader("Referer", captchaUrl)
|
||||
.addHeader("Accept-Language", "pl")
|
||||
.build()
|
||||
|
||||
val bitmap = suspendCoroutine<Bitmap?> { cont ->
|
||||
app.http.newCall(request).enqueue(object : Callback {
|
||||
override fun onResponse(call: Call, response: Response) {
|
||||
val bitmap: Bitmap? = BitmapFactory.decodeStream(response.body()?.byteStream())
|
||||
if (bitmap == null) {
|
||||
Toast.makeText(
|
||||
activity,
|
||||
"Nie udało się załadować reCAPTCHA.",
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
cont.resume(bitmap)
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call, e: IOException) {
|
||||
cont.resume(null)
|
||||
}
|
||||
})
|
||||
} ?: return null
|
||||
|
||||
return Triple(title, text, bitmap)
|
||||
}
|
||||
|
||||
override suspend fun onPositiveClick(): Boolean {
|
||||
val list = mutableListOf(
|
||||
"c=$code"
|
||||
)
|
||||
@ -155,34 +159,62 @@ class RecaptchaDialog(
|
||||
if (b.image6.isChecked) list += "response=6"
|
||||
if (b.image7.isChecked) list += "response=7"
|
||||
if (b.image8.isChecked) list += "response=8"
|
||||
|
||||
val request = Request.Builder()
|
||||
.url(captchaUrl)
|
||||
.addHeader("Referer", captchaUrl)
|
||||
.addHeader("Accept-Language", "pl")
|
||||
.addHeader("Origin", "https://www.google.com")
|
||||
.addHeader("Content-Type", "application/x-www-form-urlencoded")
|
||||
.post(RequestBody.create(MediaType.parse("application/x-www-form-urlencoded"), list.joinToString("&")))
|
||||
.post(RequestBody.create(
|
||||
MediaType.parse("application/x-www-form-urlencoded"),
|
||||
list.joinToString("&"),
|
||||
))
|
||||
.build()
|
||||
withContext(Dispatchers.Default) {
|
||||
|
||||
val (code, html) = withContext(Dispatchers.Default) {
|
||||
return@withContext suspendCoroutine<Pair<String?, String?>> { cont ->
|
||||
app.http.newCall(request).enqueue(object : Callback {
|
||||
override fun onResponse(call: Call, response: Response) {
|
||||
val html = response.body()?.string() ?: return
|
||||
val match = "<textarea.+?>([A-z0-9-_]+)</textarea>".toRegex().find(html)
|
||||
if (match == null) {
|
||||
parseHtml(html)
|
||||
val html = response.body()?.string() ?: run {
|
||||
cont.resume(null to null)
|
||||
return
|
||||
}
|
||||
Handler(activity.mainLooper).post {
|
||||
success = true
|
||||
onSuccess(match.groupValues[1])
|
||||
val match = "<textarea.+?>([A-z0-9-_]+)</textarea>".toRegex().find(html)
|
||||
if (match == null) {
|
||||
cont.resume(null to html)
|
||||
} else {
|
||||
cont.resume(match.groupValues[1] to null)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call, e: IOException) {
|
||||
|
||||
cont.resume(null to null)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
when {
|
||||
code != null -> {
|
||||
success = true
|
||||
onSuccess(code)
|
||||
return DISMISS
|
||||
}
|
||||
html != null -> {
|
||||
val (title, text, bitmap) = withContext(Dispatchers.Default) {
|
||||
return@withContext loadCaptchaData(html)
|
||||
} ?: run {
|
||||
onFailure?.invoke()
|
||||
return DISMISS
|
||||
}
|
||||
initViews(title, text, bitmap)
|
||||
return NO_DISMISS
|
||||
}
|
||||
else -> {
|
||||
onFailure?.invoke()
|
||||
return DISMISS
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ class LabPageFragment : LazyFragment(), CoroutineScope {
|
||||
}
|
||||
|
||||
b.clearProfile.onClick {
|
||||
ProfileRemoveDialog(activity, App.profileId, "FAKE", noProfileRemoval = true)
|
||||
ProfileRemoveDialog(activity, App.profileId, "FAKE", noProfileRemoval = true).show()
|
||||
}
|
||||
|
||||
b.removeHomework.onClick {
|
||||
|
@ -4,41 +4,32 @@
|
||||
|
||||
package pl.szczodrzynski.edziennik.ui.dialogs
|
||||
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import android.view.LayoutInflater
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.launch
|
||||
import pl.szczodrzynski.edziennik.App
|
||||
import pl.szczodrzynski.edziennik.MainActivity
|
||||
import pl.szczodrzynski.edziennik.R
|
||||
import pl.szczodrzynski.edziennik.databinding.DialogBellSyncBinding
|
||||
import pl.szczodrzynski.edziennik.ext.resolveDrawable
|
||||
import pl.szczodrzynski.edziennik.ext.startCoroutineTimer
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.base.BindingDialog
|
||||
import pl.szczodrzynski.edziennik.utils.models.Time
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
class BellSyncDialog(
|
||||
val activity: AppCompatActivity,
|
||||
activity: AppCompatActivity,
|
||||
private val bellTime: Time,
|
||||
val onShowListener: ((tag: String) -> Unit)? = null,
|
||||
val onDismissListener: ((tag: String) -> Unit)? = null
|
||||
) : CoroutineScope {
|
||||
onShowListener: ((tag: String) -> Unit)? = null,
|
||||
onDismissListener: ((tag: String) -> Unit)? = null,
|
||||
) : BindingDialog<DialogBellSyncBinding>(activity, onShowListener, onDismissListener) {
|
||||
|
||||
companion object {
|
||||
const val TAG = "BellSyncDialog"
|
||||
}
|
||||
override val TAG = "BellSyncDialog"
|
||||
|
||||
private lateinit var job: Job
|
||||
override val coroutineContext: CoroutineContext
|
||||
get() = job + Dispatchers.Main
|
||||
override fun getTitleRes() = R.string.bell_sync_title
|
||||
override fun inflate(layoutInflater: LayoutInflater) =
|
||||
DialogBellSyncBinding.inflate(layoutInflater)
|
||||
|
||||
private lateinit var dialog: AlertDialog
|
||||
private lateinit var b: DialogBellSyncBinding
|
||||
|
||||
private val app by lazy { activity.application as App }
|
||||
override fun getNeutralButtonText() = R.string.cancel
|
||||
|
||||
private var counterJob: Job? = null
|
||||
|
||||
@ -50,25 +41,7 @@ class BellSyncDialog(
|
||||
return Pair(bellDiff, multiplier)
|
||||
}
|
||||
|
||||
init { apply {
|
||||
if (activity.isFinishing)
|
||||
return@apply
|
||||
job = Job()
|
||||
b = DialogBellSyncBinding.inflate(activity.layoutInflater)
|
||||
onShowListener?.invoke(TAG)
|
||||
dialog = MaterialAlertDialogBuilder(activity)
|
||||
.setTitle(R.string.bell_sync_title)
|
||||
.setView(b.root)
|
||||
.setNeutralButton(R.string.cancel) { dialog, _ -> dialog.dismiss() }
|
||||
.setOnDismissListener {
|
||||
counterJob?.cancel()
|
||||
onDismissListener?.invoke(TAG)
|
||||
}
|
||||
.show()
|
||||
initView()
|
||||
}}
|
||||
|
||||
private fun initView() {
|
||||
override suspend fun onShow() {
|
||||
b.bellSyncButton.setOnClickListener {
|
||||
val (bellDiff, multiplier) = actualBellDiff
|
||||
val bellDiffText = (if (multiplier == -1) '-' else '+') + bellDiff.stringHMS
|
||||
@ -90,12 +63,15 @@ class BellSyncDialog(
|
||||
b.bellSyncButton.setImageDrawable(R.drawable.ic_bell_wtf.resolveDrawable(app)) // wtf
|
||||
}
|
||||
|
||||
launch {
|
||||
counterJob = startCoroutineTimer(repeatMillis = 500) {
|
||||
val (bellDiff, multiplier) = actualBellDiff
|
||||
val bellDiffText = (if (multiplier == -1) '-' else '+') + bellDiff.stringHMS
|
||||
b.bellSyncHowto.text = app.getString(R.string.bell_sync_howto, bellTime.stringHM, bellDiffText)
|
||||
b.bellSyncHowto.text =
|
||||
app.getString(R.string.bell_sync_howto, bellTime.stringHM, bellDiffText)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDismiss() {
|
||||
counterJob?.cancel()
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
package pl.szczodrzynski.edziennik.ui.dialogs
|
||||
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import android.view.LayoutInflater
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import kotlinx.coroutines.*
|
||||
@ -13,66 +13,62 @@ import pl.szczodrzynski.edziennik.MainActivity
|
||||
import pl.szczodrzynski.edziennik.R
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Lesson
|
||||
import pl.szczodrzynski.edziennik.databinding.DialogBellSyncTimeChooseBinding
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.base.BindingDialog
|
||||
import pl.szczodrzynski.edziennik.utils.TextInputDropDown
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
import pl.szczodrzynski.edziennik.utils.models.Time
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
class BellSyncTimeChooseDialog(
|
||||
val activity: AppCompatActivity,
|
||||
val onShowListener: ((tag: String) -> Unit)? = null,
|
||||
val onDismissListener: ((tag: String) -> Unit)? = null
|
||||
) : CoroutineScope {
|
||||
|
||||
activity: AppCompatActivity,
|
||||
onShowListener: ((tag: String) -> Unit)? = null,
|
||||
onDismissListener: ((tag: String) -> Unit)? = null,
|
||||
) : BindingDialog<DialogBellSyncTimeChooseBinding>(activity, onShowListener, onDismissListener) {
|
||||
companion object {
|
||||
const val TAG = "BellSyncTimeChooseDialog"
|
||||
|
||||
private const val MAX_DIFF_MINUTES = 10
|
||||
}
|
||||
|
||||
private lateinit var job: Job
|
||||
override val coroutineContext: CoroutineContext
|
||||
get() = job + Dispatchers.Main
|
||||
override val TAG = "BellSyncTimeChooseDialog"
|
||||
|
||||
private lateinit var dialog: AlertDialog
|
||||
private lateinit var b: DialogBellSyncTimeChooseBinding
|
||||
override fun getTitleRes() = R.string.bell_sync_title
|
||||
override fun inflate(layoutInflater: LayoutInflater) =
|
||||
DialogBellSyncTimeChooseBinding.inflate(layoutInflater)
|
||||
|
||||
private val app by lazy { activity.application as App }
|
||||
override fun getPositiveButtonText() = R.string.ok
|
||||
override fun getNeutralButtonText() = R.string.reset
|
||||
override fun getNegativeButtonText() = R.string.cancel
|
||||
|
||||
override suspend fun onShow() = Unit
|
||||
|
||||
private val today = Date.getToday()
|
||||
private val selectedTime: Time?
|
||||
get() = b.timeDropdown.selected?.tag as Time?
|
||||
|
||||
init { apply {
|
||||
if (activity.isFinishing)
|
||||
return@apply
|
||||
job = Job()
|
||||
b = DialogBellSyncTimeChooseBinding.inflate(activity.layoutInflater)
|
||||
onShowListener?.invoke(TAG)
|
||||
dialog = MaterialAlertDialogBuilder(activity)
|
||||
.setTitle(R.string.bell_sync_title)
|
||||
.setView(b.root)
|
||||
.setPositiveButton(R.string.ok) { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
override suspend fun onPositiveClick(): Boolean {
|
||||
selectedTime?.let {
|
||||
BellSyncDialog(activity, it)
|
||||
}
|
||||
}
|
||||
.setNegativeButton(R.string.cancel) { dialog, _ -> dialog.dismiss() }
|
||||
.setOnDismissListener {
|
||||
onDismissListener?.invoke(TAG)
|
||||
}
|
||||
.create()
|
||||
.apply {
|
||||
setButton(AlertDialog.BUTTON_NEUTRAL, app.getString(R.string.reset)) { _, _ ->
|
||||
showResetDialog()
|
||||
BellSyncDialog(activity, it).show()
|
||||
}
|
||||
return DISMISS
|
||||
}
|
||||
|
||||
initView()
|
||||
}}
|
||||
override suspend fun onNeutralClick(): Boolean {
|
||||
MaterialAlertDialogBuilder(activity)
|
||||
.setTitle(R.string.bell_sync_title)
|
||||
.setMessage(R.string.bell_sync_reset_confirm)
|
||||
.setPositiveButton(R.string.yes) { dialog, _ ->
|
||||
app.config.timetable.bellSyncDiff = null
|
||||
app.config.timetable.bellSyncMultiplier = 0
|
||||
|
||||
private fun initView() {
|
||||
dialog.dismiss()
|
||||
reload()
|
||||
if (activity is MainActivity)
|
||||
activity.reloadTarget()
|
||||
}
|
||||
.setNegativeButton(R.string.no, null)
|
||||
.show()
|
||||
return NO_DISMISS
|
||||
}
|
||||
|
||||
override suspend fun onBeforeShow(): Boolean {
|
||||
b.bellSyncHowto.text = app.getString(R.string.bell_sync_choose_howto)
|
||||
|
||||
app.config.timetable.bellSyncDiff?.let { bellDiff ->
|
||||
@ -84,7 +80,7 @@ class BellSyncTimeChooseDialog(
|
||||
)
|
||||
}
|
||||
|
||||
loadTimeList()
|
||||
return loadTimeList()
|
||||
}
|
||||
|
||||
private fun checkForLessons(timeList: List<Time>): Boolean {
|
||||
@ -98,7 +94,7 @@ class BellSyncTimeChooseDialog(
|
||||
} else false
|
||||
}
|
||||
|
||||
private fun loadTimeList() { launch {
|
||||
private suspend fun loadTimeList(): Boolean {
|
||||
val timeItems = withContext(Dispatchers.Default) {
|
||||
val lessons = app.db.timetableDao().getAllForDateNow(App.profileId, today)
|
||||
val items = mutableListOf<TextInputDropDown.Item>()
|
||||
@ -106,17 +102,21 @@ class BellSyncTimeChooseDialog(
|
||||
lessons.forEach {
|
||||
if (it.type != Lesson.TYPE_NO_LESSONS &&
|
||||
it.type != Lesson.TYPE_CANCELLED &&
|
||||
it.type != Lesson.TYPE_SHIFTED_SOURCE) {
|
||||
it.type != Lesson.TYPE_SHIFTED_SOURCE
|
||||
) {
|
||||
|
||||
items += TextInputDropDown.Item(
|
||||
it.displayStartTime?.value?.toLong() ?: return@forEach,
|
||||
app.getString(R.string.bell_sync_lesson_item, it.displaySubjectName, it.displayStartTime?.stringHM),
|
||||
app.getString(R.string.bell_sync_lesson_item,
|
||||
it.displaySubjectName,
|
||||
it.displayStartTime?.stringHM),
|
||||
tag = it.displayStartTime
|
||||
)
|
||||
|
||||
items += TextInputDropDown.Item(
|
||||
it.displayEndTime?.value?.toLong() ?: return@forEach,
|
||||
app.getString(R.string.bell_sync_break_item, it.displayEndTime?.stringHM),
|
||||
app.getString(R.string.bell_sync_break_item,
|
||||
it.displayEndTime?.stringHM),
|
||||
tag = it.displayEndTime
|
||||
)
|
||||
}
|
||||
@ -130,8 +130,9 @@ class BellSyncTimeChooseDialog(
|
||||
MaterialAlertDialogBuilder(activity)
|
||||
.setTitle(R.string.bell_sync_title)
|
||||
.setMessage(R.string.bell_sync_cannot_now)
|
||||
.setPositiveButton(R.string.ok) { dialog, _ -> dialog.dismiss() }
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.show()
|
||||
return false
|
||||
} else {
|
||||
b.timeDropdown.clear()
|
||||
b.timeDropdown.append(timeItems)
|
||||
@ -144,24 +145,7 @@ class BellSyncTimeChooseDialog(
|
||||
|
||||
b.timeDropdown.isEnabled = true
|
||||
// TODO Fix popup cutting off
|
||||
|
||||
dialog.show()
|
||||
}
|
||||
}}
|
||||
|
||||
private fun showResetDialog() {
|
||||
MaterialAlertDialogBuilder(activity)
|
||||
.setTitle(R.string.bell_sync_title)
|
||||
.setMessage(R.string.bell_sync_reset_confirm)
|
||||
.setPositiveButton(R.string.yes) { confirmDialog, _ ->
|
||||
app.config.timetable.bellSyncDiff = null
|
||||
app.config.timetable.bellSyncMultiplier = 0
|
||||
|
||||
confirmDialog.dismiss()
|
||||
initView()
|
||||
if (activity is MainActivity) activity.reloadTarget()
|
||||
}
|
||||
.setNegativeButton(R.string.no) { dialog, _ -> dialog.dismiss() }
|
||||
.show()
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
@ -4,43 +4,29 @@
|
||||
|
||||
package pl.szczodrzynski.edziennik.ui.dialogs
|
||||
|
||||
import android.os.Build
|
||||
import android.widget.ScrollView
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import pl.szczodrzynski.edziennik.App
|
||||
import pl.szczodrzynski.edziennik.R
|
||||
import pl.szczodrzynski.edziennik.ext.dp
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.base.ViewDialog
|
||||
import pl.szczodrzynski.edziennik.utils.BetterLinkMovementMethod
|
||||
import pl.szczodrzynski.edziennik.utils.html.BetterHtml
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
class ChangelogDialog(
|
||||
val activity: AppCompatActivity,
|
||||
val onShowListener: ((tag: String) -> Unit)? = null,
|
||||
val onDismissListener: ((tag: String) -> Unit)? = null
|
||||
) : CoroutineScope {
|
||||
companion object {
|
||||
private const val TAG = "ChangelogDialog"
|
||||
}
|
||||
activity: AppCompatActivity,
|
||||
onShowListener: ((tag: String) -> Unit)? = null,
|
||||
onDismissListener: ((tag: String) -> Unit)? = null,
|
||||
) : ViewDialog<ScrollView>(activity, onShowListener, onDismissListener) {
|
||||
|
||||
private lateinit var app: App
|
||||
private lateinit var dialog: AlertDialog
|
||||
override val TAG = "ChangelogDialog"
|
||||
|
||||
private val job = Job()
|
||||
override val coroutineContext: CoroutineContext
|
||||
get() = job + Dispatchers.Main
|
||||
override fun getTitleRes() = R.string.whats_new
|
||||
override fun getPositiveButtonText() = R.string.close
|
||||
|
||||
init { run {
|
||||
if (activity.isFinishing)
|
||||
return@run
|
||||
onShowListener?.invoke(TAG)
|
||||
app = activity.applicationContext as App
|
||||
override suspend fun onShow() = Unit
|
||||
|
||||
override fun getRootView(): ScrollView {
|
||||
val textView = TextView(activity)
|
||||
textView.setPadding(24.dp, 24.dp, 24.dp, 0)
|
||||
|
||||
@ -49,29 +35,22 @@ class ChangelogDialog(
|
||||
}
|
||||
|
||||
val commitsUrlPrefix = "https://github.com/szkolny-eu/szkolny-android/commits?author="
|
||||
text = text.replace("""\[(.+?)]\(@([A-z0-9-]+)\)""".toRegex(), "<a href=\"$commitsUrlPrefix$2\">$1</a>")
|
||||
text = text.replace("""\s@([A-z0-9-]+)""".toRegex(), " <a href=\"$commitsUrlPrefix$1\">@$1</a>")
|
||||
text = text.replace(
|
||||
regex = """\[(.+?)]\(@([A-z0-9-]+)\)""".toRegex(),
|
||||
replacement = "<a href=\"$commitsUrlPrefix$2\">$1</a>"
|
||||
)
|
||||
text = text.replace(
|
||||
regex = """\s@([A-z0-9-]+)""".toRegex(),
|
||||
replacement = " <a href=\"$commitsUrlPrefix$1\">@$1</a>"
|
||||
)
|
||||
|
||||
val html = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
|
||||
text
|
||||
else
|
||||
text.replace("<li>", "<br><li> - ")
|
||||
textView.text = BetterHtml.fromHtml(activity, html)
|
||||
textView.text = BetterHtml.fromHtml(activity, text)
|
||||
|
||||
textView.movementMethod = BetterLinkMovementMethod.getInstance()
|
||||
|
||||
val scrollView = ScrollView(activity)
|
||||
scrollView.addView(textView)
|
||||
|
||||
dialog = MaterialAlertDialogBuilder(activity)
|
||||
.setTitle(R.string.whats_new)
|
||||
.setView(scrollView)
|
||||
.setPositiveButton(R.string.close) { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
return scrollView
|
||||
}
|
||||
.setOnDismissListener {
|
||||
onDismissListener?.invoke(TAG)
|
||||
}
|
||||
.show()
|
||||
}}
|
||||
}
|
||||
|
@ -5,51 +5,41 @@
|
||||
package pl.szczodrzynski.edziennik.ui.dialogs
|
||||
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import kotlinx.coroutines.*
|
||||
import pl.szczodrzynski.edziennik.App
|
||||
import pl.szczodrzynski.edziennik.MainActivity
|
||||
import pl.szczodrzynski.edziennik.R
|
||||
import pl.szczodrzynski.edziennik.databinding.DialogLessonDetailsBinding
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.base.BaseDialog
|
||||
|
||||
class ProfileRemoveDialog(
|
||||
val activity: MainActivity,
|
||||
activity: AppCompatActivity,
|
||||
val profileId: Int,
|
||||
val profileName: String,
|
||||
val noProfileRemoval: Boolean = false,
|
||||
val onRemove: (() -> Unit)? = null
|
||||
) : CoroutineScope {
|
||||
companion object {
|
||||
private const val TAG = "ProfileRemoveDialog"
|
||||
}
|
||||
val onRemove: (() -> Unit)? = null,
|
||||
onShowListener: ((tag: String) -> Unit)? = null,
|
||||
onDismissListener: ((tag: String) -> Unit)? = null,
|
||||
) : BaseDialog(activity, onShowListener, onDismissListener) {
|
||||
|
||||
private lateinit var job: Job
|
||||
override val coroutineContext: CoroutineContext
|
||||
get() = job + Dispatchers.Main
|
||||
override val TAG = "ProfileRemoveDialog"
|
||||
|
||||
private val app by lazy { activity.application as App }
|
||||
private lateinit var b: DialogLessonDetailsBinding
|
||||
private lateinit var dialog: AlertDialog
|
||||
override fun getTitleRes() = R.string.profile_menu_remove_confirm
|
||||
override fun getMessageFormat() =
|
||||
R.string.profile_menu_remove_confirm_text_format to listOf(
|
||||
profileName,
|
||||
profileName
|
||||
)
|
||||
|
||||
init { run {
|
||||
job = Job()
|
||||
override fun isCancelable() = false
|
||||
override fun getPositiveButtonText() = R.string.remove
|
||||
override fun getNeutralButtonText() = R.string.cancel
|
||||
|
||||
dialog = MaterialAlertDialogBuilder(activity)
|
||||
.setTitle(R.string.profile_menu_remove_confirm)
|
||||
.setMessage(activity.getString(R.string.profile_menu_remove_confirm_text_format, profileName, profileName))
|
||||
.setPositiveButton(R.string.remove) { _, _ ->
|
||||
removeProfile()
|
||||
}
|
||||
.setNeutralButton(R.string.cancel) { dialog, _ -> dialog.dismiss() }
|
||||
.setCancelable(false)
|
||||
.show()
|
||||
}}
|
||||
override suspend fun onShow() = Unit
|
||||
|
||||
private fun removeProfile() { launch {
|
||||
val deferred = async(Dispatchers.Default) {
|
||||
val profileObject = app.db.profileDao().getByIdNow(profileId) ?: return@async
|
||||
override suspend fun onPositiveClick(): Boolean {
|
||||
withContext(Dispatchers.Default) {
|
||||
val profileObject = app.db.profileDao().getByIdNow(profileId) ?: return@withContext
|
||||
app.db.announcementDao().clear(profileId)
|
||||
app.db.attendanceDao().clear(profileId)
|
||||
app.db.attendanceTypeDao().clear(profileId)
|
||||
@ -77,12 +67,13 @@ class ProfileRemoveDialog(
|
||||
app.db.metadataDao().deleteAll(profileId)
|
||||
|
||||
if (noProfileRemoval)
|
||||
return@async
|
||||
return@withContext
|
||||
|
||||
app.db.configDao().clear(profileId)
|
||||
|
||||
val loginStoreId = profileObject.loginStoreId
|
||||
val profilesUsingLoginStore = app.db.profileDao().getIdsByLoginStoreIdNow(loginStoreId)
|
||||
val profilesUsingLoginStore =
|
||||
app.db.profileDao().getIdsByLoginStoreIdNow(loginStoreId)
|
||||
if (profilesUsingLoginStore.size == 1) {
|
||||
app.db.loginStoreDao().remove(loginStoreId)
|
||||
}
|
||||
@ -92,10 +83,13 @@ class ProfileRemoveDialog(
|
||||
app.profileLoadLast { }
|
||||
}
|
||||
}
|
||||
deferred.await()
|
||||
dialog.dismiss()
|
||||
|
||||
if (activity is MainActivity)
|
||||
activity.reloadTarget()
|
||||
|
||||
Toast.makeText(activity, R.string.dialog_profile_remove_success, Toast.LENGTH_LONG).show()
|
||||
onRemove?.invoke()
|
||||
}}
|
||||
|
||||
return DISMISS
|
||||
}
|
||||
}
|
||||
|
@ -4,59 +4,36 @@
|
||||
|
||||
package pl.szczodrzynski.edziennik.ui.dialogs
|
||||
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import me.dm7.barcodescanner.zxing.ZXingScannerView
|
||||
import pl.szczodrzynski.edziennik.App
|
||||
import pl.szczodrzynski.edziennik.R
|
||||
import pl.szczodrzynski.edziennik.ext.dp
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.base.ViewDialog
|
||||
|
||||
class QrScannerDialog(
|
||||
val activity: AppCompatActivity,
|
||||
activity: AppCompatActivity,
|
||||
val onCodeScanned: (text: String) -> Unit,
|
||||
val onShowListener: ((tag: String) -> Unit)? = null,
|
||||
val onDismissListener: ((tag: String) -> Unit)? = null
|
||||
) : CoroutineScope {
|
||||
companion object {
|
||||
private const val TAG = "QrScannerDialog"
|
||||
}
|
||||
onShowListener: ((tag: String) -> Unit)? = null,
|
||||
onDismissListener: ((tag: String) -> Unit)? = null,
|
||||
) : ViewDialog<ZXingScannerView>(activity, onShowListener, onDismissListener) {
|
||||
|
||||
private lateinit var app: App
|
||||
private lateinit var scannerView: ZXingScannerView
|
||||
private lateinit var dialog: AlertDialog
|
||||
override val TAG = "QrScannerDialog"
|
||||
|
||||
private val job = Job()
|
||||
override val coroutineContext: CoroutineContext
|
||||
get() = job + Dispatchers.Main
|
||||
override fun getTitleRes() = R.string.qr_scanner_dialog_title
|
||||
override fun getPositiveButtonText() = R.string.close
|
||||
|
||||
init { run {
|
||||
if (activity.isFinishing)
|
||||
return@run
|
||||
onShowListener?.invoke(TAG)
|
||||
app = activity.applicationContext as App
|
||||
scannerView = ZXingScannerView(activity)
|
||||
override fun getRootView(): ZXingScannerView {
|
||||
val scannerView = ZXingScannerView(activity)
|
||||
scannerView.setPadding(0, 16.dp, 2.dp, 0)
|
||||
dialog = MaterialAlertDialogBuilder(activity)
|
||||
.setTitle(R.string.qr_scanner_dialog_title)
|
||||
.setView(scannerView)
|
||||
.setPositiveButton(R.string.close) { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
return scannerView
|
||||
}
|
||||
.setOnDismissListener {
|
||||
onDismissListener?.invoke(TAG)
|
||||
}
|
||||
.show()
|
||||
|
||||
scannerView.setResultHandler {
|
||||
scannerView.stopCamera()
|
||||
override suspend fun onShow() {
|
||||
root.setResultHandler {
|
||||
root.stopCamera()
|
||||
dialog.dismiss()
|
||||
onCodeScanned(it.text)
|
||||
}
|
||||
scannerView.startCamera()
|
||||
}}
|
||||
root.startCamera()
|
||||
}
|
||||
}
|
||||
|
@ -7,59 +7,45 @@ package pl.szczodrzynski.edziennik.ui.dialogs
|
||||
import android.content.res.ColorStateList
|
||||
import android.text.Editable
|
||||
import android.text.SpannableStringBuilder
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import android.view.LayoutInflater
|
||||
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.databinding.StyledTextDialogBinding
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.base.BindingDialog
|
||||
import pl.szczodrzynski.edziennik.utils.DefaultTextStyles
|
||||
import pl.szczodrzynski.edziennik.utils.Themes
|
||||
import pl.szczodrzynski.edziennik.utils.managers.TextStylingManager.HtmlMode.SIMPLE
|
||||
import pl.szczodrzynski.edziennik.utils.managers.TextStylingManager.StylingConfig
|
||||
|
||||
class StyledTextDialog(
|
||||
val activity: AppCompatActivity,
|
||||
activity: AppCompatActivity,
|
||||
val initialText: Editable?,
|
||||
val onSuccess: (text: Editable) -> Unit,
|
||||
val onShowListener: ((tag: String) -> Unit)? = null,
|
||||
val onDismissListener: ((tag: String) -> Unit)? = null
|
||||
) {
|
||||
companion object {
|
||||
private const val TAG = "StyledTextDialog"
|
||||
}
|
||||
onShowListener: ((tag: String) -> Unit)? = null,
|
||||
onDismissListener: ((tag: String) -> Unit)? = null,
|
||||
) : BindingDialog<StyledTextDialogBinding>(activity, onShowListener, onDismissListener) {
|
||||
|
||||
override val TAG = "StyledTextDialog"
|
||||
|
||||
private lateinit var app: App
|
||||
private lateinit var b: StyledTextDialogBinding
|
||||
private lateinit var dialog: AlertDialog
|
||||
private lateinit var config: StylingConfig
|
||||
|
||||
private val manager
|
||||
get() = app.textStylingManager
|
||||
|
||||
init {
|
||||
show()
|
||||
}
|
||||
override fun getTitleRes() = R.string.styled_text_dialog_title
|
||||
override fun inflate(layoutInflater: LayoutInflater) =
|
||||
StyledTextDialogBinding.inflate(layoutInflater)
|
||||
|
||||
fun show() {
|
||||
if (activity.isFinishing)
|
||||
return
|
||||
onShowListener?.invoke(TAG)
|
||||
app = activity.applicationContext as App
|
||||
b = StyledTextDialogBinding.inflate(activity.layoutInflater)
|
||||
override fun getPositiveButtonText() = R.string.save
|
||||
override fun getNeutralButtonText() = R.string.cancel
|
||||
|
||||
dialog = MaterialAlertDialogBuilder(activity)
|
||||
.setTitle(R.string.styled_text_dialog_title)
|
||||
.setView(b.root)
|
||||
.setPositiveButton(R.string.save) { _, _ ->
|
||||
override suspend fun onPositiveClick(): Boolean {
|
||||
onSuccess(b.editText.text ?: SpannableStringBuilder(""))
|
||||
return DISMISS
|
||||
}
|
||||
.setNeutralButton(R.string.cancel, null)
|
||||
.setOnDismissListener {
|
||||
onDismissListener?.invoke(TAG)
|
||||
}
|
||||
.show()
|
||||
|
||||
override suspend fun onShow() {
|
||||
config = StylingConfig(
|
||||
editText = b.editText,
|
||||
fontStyleGroup = b.fontStyle.styles,
|
||||
|
@ -0,0 +1,199 @@
|
||||
/*
|
||||
* Copyright (c) Kuba Szczodrzyński 2021-10-18.
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.ui.dialogs.base
|
||||
|
||||
import android.view.View
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.app.AlertDialog.*
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.launch
|
||||
import pl.szczodrzynski.edziennik.App
|
||||
import pl.szczodrzynski.edziennik.ext.onClick
|
||||
import pl.szczodrzynski.edziennik.ext.setMessage
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
abstract class BaseDialog(
|
||||
protected val activity: AppCompatActivity,
|
||||
protected val onShowListener: ((tag: String) -> Unit)? = null,
|
||||
protected val onDismissListener: ((tag: String) -> Unit)? = null,
|
||||
) : CoroutineScope {
|
||||
companion object {
|
||||
const val DISMISS = true
|
||||
const val NO_DISMISS = false
|
||||
}
|
||||
|
||||
@Suppress("PropertyName")
|
||||
abstract val TAG: String
|
||||
|
||||
protected lateinit var app: App
|
||||
protected lateinit var dialog: AlertDialog
|
||||
|
||||
private val job = Job()
|
||||
override val coroutineContext: CoroutineContext
|
||||
get() = job + Dispatchers.Main
|
||||
|
||||
private var items = emptyList<Any>()
|
||||
private var itemSelected: Any? = null
|
||||
private var itemStates = BooleanArray(0)
|
||||
|
||||
protected open fun getTitle(): CharSequence? = null
|
||||
protected abstract fun getTitleRes(): Int?
|
||||
protected open fun getMessage(): CharSequence? = null
|
||||
protected open fun getMessageRes(): Int? = null
|
||||
protected open fun getMessageFormat(): Pair<Int, List<CharSequence>>? = null
|
||||
protected open fun getView(): View? = null
|
||||
open fun isCancelable() = true
|
||||
open fun getPositiveButtonText(): Int? = null
|
||||
open fun getNeutralButtonText(): Int? = null
|
||||
open fun getNegativeButtonText(): Int? = null
|
||||
|
||||
protected open fun getSingleChoiceItems(): Map<CharSequence, Any>? = null
|
||||
protected open fun getMultiChoiceItems(): Map<CharSequence, Any>? = null
|
||||
protected open fun getDefaultSelectedItem(): Any? = null
|
||||
protected open fun getDefaultSelectedItems(): Set<Any> = emptySet()
|
||||
|
||||
open suspend fun onPositiveClick() = true
|
||||
open suspend fun onNeutralClick() = true
|
||||
open suspend fun onNegativeClick() = true
|
||||
open suspend fun onSingleSelectionChanged(item: Any?) = Unit
|
||||
open suspend fun onMultiSelectionChanged(items: Set<Any>) = Unit
|
||||
|
||||
protected open suspend fun onBeforeShow() = true
|
||||
protected abstract suspend fun onShow()
|
||||
protected open fun onDismiss() = Unit
|
||||
|
||||
fun show() {
|
||||
if (activity.isFinishing)
|
||||
return
|
||||
onShowListener?.invoke(TAG)
|
||||
app = activity.applicationContext as App
|
||||
dialog = MaterialAlertDialogBuilder(activity)
|
||||
.also(this::configure)
|
||||
.setCancelable(isCancelable())
|
||||
.setOnDismissListener {
|
||||
onDismiss()
|
||||
onDismissListener?.invoke(TAG)
|
||||
}
|
||||
.create()
|
||||
|
||||
reload()
|
||||
}
|
||||
|
||||
protected fun reload() {
|
||||
launch {
|
||||
if (activity.isFinishing)
|
||||
return@launch
|
||||
if (!onBeforeShow()) {
|
||||
dialog.dismiss()
|
||||
return@launch
|
||||
}
|
||||
dialog.show()
|
||||
setButtons()
|
||||
onShow()
|
||||
}
|
||||
}
|
||||
|
||||
private fun configure(md: MaterialAlertDialogBuilder) {
|
||||
getTitle()?.let {
|
||||
md.setTitle(it)
|
||||
}
|
||||
getTitleRes()?.let {
|
||||
md.setTitle(it)
|
||||
}
|
||||
getPositiveButtonText()?.let {
|
||||
md.setPositiveButton(it, null)
|
||||
}
|
||||
getNeutralButtonText()?.let {
|
||||
md.setNeutralButton(it, null)
|
||||
}
|
||||
getNegativeButtonText()?.let {
|
||||
md.setNegativeButton(it, null)
|
||||
}
|
||||
|
||||
getMessage()?.let {
|
||||
md.setMessage(it)
|
||||
}
|
||||
getMessageRes()?.let {
|
||||
md.setMessage(it)
|
||||
}
|
||||
getMessageFormat()?.let { (stringId, formatArgs) ->
|
||||
md.setMessage(stringId, *formatArgs.toTypedArray())
|
||||
}
|
||||
getView()?.let {
|
||||
md.setView(it)
|
||||
}
|
||||
|
||||
getSingleChoiceItems()?.let { map ->
|
||||
val default = getDefaultSelectedItem()
|
||||
val defaultIndex = map.values.indexOf(default)
|
||||
md.setSingleChoiceItems(map.keys.toTypedArray(), defaultIndex) { _, which ->
|
||||
launch {
|
||||
itemSelected = items[which]
|
||||
onSingleSelectionChanged(getSingleSelection())
|
||||
}
|
||||
}
|
||||
items = map.values.toList()
|
||||
itemSelected = default
|
||||
md.setMessage(null)
|
||||
}
|
||||
getMultiChoiceItems()?.let { map ->
|
||||
val default = getDefaultSelectedItems()
|
||||
val defaultStates = map.values.map {
|
||||
it in default
|
||||
}.toBooleanArray()
|
||||
md.setMultiChoiceItems(map.keys.toTypedArray(),
|
||||
defaultStates) { _, position, isChecked ->
|
||||
launch {
|
||||
itemStates[position] = isChecked
|
||||
onMultiSelectionChanged(getMultiSelection())
|
||||
}
|
||||
}
|
||||
items = map.values.toList()
|
||||
itemStates = defaultStates
|
||||
md.setMessage(null)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setButtons() {
|
||||
dialog.getButton(BUTTON_POSITIVE)?.onClick {
|
||||
launch {
|
||||
if (onPositiveClick())
|
||||
dialog.dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
dialog.getButton(BUTTON_NEUTRAL)?.onClick {
|
||||
launch {
|
||||
if (onNeutralClick())
|
||||
dialog.dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
dialog.getButton(BUTTON_NEGATIVE)?.onClick {
|
||||
launch {
|
||||
if (onNegativeClick())
|
||||
dialog.dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected fun getSingleSelection() = itemSelected
|
||||
protected fun getMultiSelection(): Set<Any> {
|
||||
return itemStates.mapIndexed { position, isChecked ->
|
||||
if (isChecked)
|
||||
items[position]
|
||||
else
|
||||
null
|
||||
}.filterNotNull().toSet()
|
||||
}
|
||||
|
||||
protected fun dismiss() {
|
||||
dialog.dismiss()
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (c) Kuba Szczodrzyński 2021-10-18.
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.ui.dialogs.base
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.viewbinding.ViewBinding
|
||||
|
||||
abstract class BindingDialog<B : ViewBinding>(
|
||||
activity: AppCompatActivity,
|
||||
onShowListener: ((tag: String) -> Unit)? = null,
|
||||
onDismissListener: ((tag: String) -> Unit)? = null,
|
||||
) : ViewDialog<View>(activity, onShowListener, onDismissListener) {
|
||||
|
||||
protected lateinit var b: B
|
||||
protected abstract fun inflate(layoutInflater: LayoutInflater): B
|
||||
|
||||
final override fun getRootView(): View {
|
||||
b = inflate(activity.layoutInflater)
|
||||
return b.root
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) Kuba Szczodrzyński 2021-10-18.
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.ui.dialogs.base
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.viewbinding.ViewBinding
|
||||
import kotlinx.coroutines.launch
|
||||
import pl.szczodrzynski.edziennik.MainActivity
|
||||
import pl.szczodrzynski.edziennik.R
|
||||
|
||||
abstract class ConfigDialog<B : ViewBinding>(
|
||||
activity: AppCompatActivity,
|
||||
private val reloadOnDismiss: Boolean = true,
|
||||
onShowListener: ((tag: String) -> Unit)? = null,
|
||||
onDismissListener: ((tag: String) -> Unit)? = null,
|
||||
) : BindingDialog<B>(activity, onShowListener, onDismissListener) {
|
||||
|
||||
final override fun getPositiveButtonText() = R.string.ok
|
||||
final override suspend fun onShow() = Unit
|
||||
|
||||
protected val config by lazy { app.config.grades }
|
||||
|
||||
protected open suspend fun loadConfig() = Unit
|
||||
protected open suspend fun saveConfig() = Unit
|
||||
protected open fun initView() = Unit
|
||||
|
||||
final override suspend fun onBeforeShow(): Boolean {
|
||||
initView()
|
||||
loadConfig()
|
||||
return true
|
||||
}
|
||||
|
||||
final override fun onDismiss() {
|
||||
launch {
|
||||
saveConfig()
|
||||
}
|
||||
if (reloadOnDismiss && activity is MainActivity)
|
||||
activity.reloadTarget()
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (c) Kuba Szczodrzyński 2021-10-18.
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.ui.dialogs.base
|
||||
|
||||
import android.view.View
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
|
||||
abstract class ViewDialog<V : View>(
|
||||
activity: AppCompatActivity,
|
||||
onShowListener: ((tag: String) -> Unit)? = null,
|
||||
onDismissListener: ((tag: String) -> Unit)? = null
|
||||
) : BaseDialog(activity, onShowListener, onDismissListener) {
|
||||
|
||||
protected lateinit var root: V
|
||||
protected abstract fun getRootView(): V
|
||||
|
||||
final override fun getMessage() = null
|
||||
final override fun getMessageFormat() = null
|
||||
final override fun getView(): View {
|
||||
root = getRootView()
|
||||
return root
|
||||
}
|
||||
}
|
@ -4,7 +4,7 @@
|
||||
|
||||
package pl.szczodrzynski.edziennik.ui.dialogs.settings
|
||||
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import android.view.LayoutInflater
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import pl.szczodrzynski.edziennik.*
|
||||
@ -12,57 +12,48 @@ import pl.szczodrzynski.edziennik.data.db.entity.Profile
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Profile.Companion.REGISTRATION_ENABLED
|
||||
import pl.szczodrzynski.edziennik.databinding.DialogConfigAgendaBinding
|
||||
import pl.szczodrzynski.edziennik.ext.onChange
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.base.ConfigDialog
|
||||
import java.util.*
|
||||
|
||||
class AgendaConfigDialog(
|
||||
private val activity: AppCompatActivity,
|
||||
private val reloadOnDismiss: Boolean = true,
|
||||
private val onShowListener: ((tag: String) -> Unit)? = null,
|
||||
private val onDismissListener: ((tag: String) -> Unit)? = null
|
||||
activity: AppCompatActivity,
|
||||
reloadOnDismiss: Boolean = true,
|
||||
onShowListener: ((tag: String) -> Unit)? = null,
|
||||
onDismissListener: ((tag: String) -> Unit)? = null,
|
||||
) : ConfigDialog<DialogConfigAgendaBinding>(
|
||||
activity,
|
||||
reloadOnDismiss,
|
||||
onShowListener,
|
||||
onDismissListener,
|
||||
) {
|
||||
companion object {
|
||||
const val TAG = "AgendaConfigDialog"
|
||||
}
|
||||
|
||||
private val app by lazy { activity.application as App }
|
||||
private val config by lazy { app.config.ui }
|
||||
override val TAG = "AgendaConfigDialog"
|
||||
|
||||
override fun getTitleRes() = R.string.menu_agenda_config
|
||||
override fun inflate(layoutInflater: LayoutInflater) =
|
||||
DialogConfigAgendaBinding.inflate(layoutInflater)
|
||||
|
||||
private val profileConfig by lazy { app.config.forProfile().ui }
|
||||
|
||||
private lateinit var b: DialogConfigAgendaBinding
|
||||
private lateinit var dialog: AlertDialog
|
||||
|
||||
init { run {
|
||||
if (activity.isFinishing)
|
||||
return@run
|
||||
b = DialogConfigAgendaBinding.inflate(activity.layoutInflater)
|
||||
onShowListener?.invoke(TAG)
|
||||
dialog = MaterialAlertDialogBuilder(activity)
|
||||
.setTitle(R.string.menu_agenda_config)
|
||||
.setView(b.root)
|
||||
.setPositiveButton(R.string.ok) { dialog, _ -> dialog.dismiss() }
|
||||
.setOnDismissListener {
|
||||
saveConfig()
|
||||
onDismissListener?.invoke(TAG)
|
||||
if (reloadOnDismiss) (activity as? MainActivity)?.reloadTarget()
|
||||
}
|
||||
.create()
|
||||
loadConfig()
|
||||
dialog.show()
|
||||
}}
|
||||
|
||||
private fun loadConfig() {
|
||||
override suspend fun loadConfig() {
|
||||
b.config = profileConfig
|
||||
b.isAgendaMode = profileConfig.agendaViewType == Profile.AGENDA_DEFAULT
|
||||
|
||||
b.eventSharingEnabled.isChecked = app.profile.enableSharedEvents
|
||||
&& app.profile.registration == REGISTRATION_ENABLED
|
||||
b.eventSharingEnabled.isChecked =
|
||||
app.profile.enableSharedEvents && app.profile.registration == REGISTRATION_ENABLED
|
||||
b.eventSharingEnabled.onChange { _, isChecked ->
|
||||
if (isChecked && app.profile.registration != REGISTRATION_ENABLED) {
|
||||
b.eventSharingEnabled.isChecked = false
|
||||
val dialog = RegistrationConfigDialog(activity, app.profile, onChangeListener = { enabled ->
|
||||
val dialog = RegistrationConfigDialog(
|
||||
activity,
|
||||
app.profile,
|
||||
onChangeListener = { enabled ->
|
||||
b.eventSharingEnabled.isChecked = enabled
|
||||
setEventSharingEnabled(enabled)
|
||||
}, onShowListener, onDismissListener)
|
||||
},
|
||||
onShowListener,
|
||||
onDismissListener,
|
||||
)
|
||||
dialog.showEnableDialog()
|
||||
return@onChange
|
||||
}
|
||||
@ -86,8 +77,4 @@ class AgendaConfigDialog(
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.show()
|
||||
}
|
||||
|
||||
private fun saveConfig() {
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -4,68 +4,40 @@
|
||||
|
||||
package pl.szczodrzynski.edziennik.ui.dialogs.settings
|
||||
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import pl.szczodrzynski.edziennik.*
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import pl.szczodrzynski.edziennik.R
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.base.BaseDialog
|
||||
|
||||
class AppLanguageDialog(
|
||||
val activity: AppCompatActivity,
|
||||
val onShowListener: ((tag: String) -> Unit)? = null,
|
||||
val onDismissListener: ((tag: String) -> Unit)? = null
|
||||
) : CoroutineScope {
|
||||
companion object {
|
||||
private const val TAG = "AppLanguageDialog"
|
||||
}
|
||||
activity: AppCompatActivity,
|
||||
onShowListener: ((tag: String) -> Unit)? = null,
|
||||
onDismissListener: ((tag: String) -> Unit)? = null,
|
||||
) : BaseDialog(activity, onShowListener, onDismissListener) {
|
||||
override val TAG = "AppLanguageDialog"
|
||||
|
||||
private lateinit var app: App
|
||||
private lateinit var dialog: AlertDialog
|
||||
override fun getTitleRes() = R.string.app_language_dialog_title
|
||||
override fun getMessage() = activity.getString(R.string.app_language_dialog_text)
|
||||
override fun getPositiveButtonText() = R.string.ok
|
||||
override fun getNegativeButtonText() = R.string.cancel
|
||||
|
||||
private val job = Job()
|
||||
override val coroutineContext: CoroutineContext
|
||||
get() = job + Dispatchers.Main
|
||||
override fun getSingleChoiceItems(): Map<CharSequence, Any> = mapOf(
|
||||
R.string.language_system to "",
|
||||
R.string.language_polish to "pl",
|
||||
R.string.language_english to "en",
|
||||
R.string.language_german to "de",
|
||||
).mapKeys { (resId, _) -> activity.getString(resId) }
|
||||
|
||||
// local variables go here
|
||||
override fun getDefaultSelectedItem() = app.config.ui.language
|
||||
|
||||
init { run {
|
||||
if (activity.isFinishing)
|
||||
return@run
|
||||
onShowListener?.invoke(TAG)
|
||||
app = activity.applicationContext as App
|
||||
override suspend fun onShow() = Unit
|
||||
|
||||
val languages = mapOf(
|
||||
null to R.string.language_system,
|
||||
"pl" to R.string.language_polish,
|
||||
"en" to R.string.language_english,
|
||||
"de" to R.string.language_german
|
||||
)
|
||||
val languageIds = languages.map { it.key }
|
||||
val languageNames = languages.map {
|
||||
activity.getString(it.value)
|
||||
}
|
||||
|
||||
dialog = MaterialAlertDialogBuilder(activity)
|
||||
.setTitle(R.string.app_language_dialog_title)
|
||||
//.setMessage(R.string.settings_about_language_dialog_text)
|
||||
.setSingleChoiceItems(
|
||||
languageNames.toTypedArray(),
|
||||
languageIds.indexOf(app.config.ui.language),
|
||||
null
|
||||
)
|
||||
.setPositiveButton(R.string.ok) { _, _ ->
|
||||
val which = dialog.listView.checkedItemPosition
|
||||
|
||||
app.config.ui.language = languageIds[which]
|
||||
override suspend fun onPositiveClick(): Boolean {
|
||||
val language = getSingleSelection() as? String ?: return DISMISS
|
||||
if (language.isEmpty())
|
||||
app.config.ui.language = null
|
||||
else
|
||||
app.config.ui.language = language
|
||||
activity.recreate()
|
||||
return NO_DISMISS
|
||||
}
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.setOnDismissListener {
|
||||
onDismissListener?.invoke(TAG)
|
||||
}
|
||||
.show()
|
||||
}}
|
||||
}
|
||||
|
@ -4,64 +4,40 @@
|
||||
|
||||
package pl.szczodrzynski.edziennik.ui.dialogs.settings
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import android.view.LayoutInflater
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import pl.szczodrzynski.edziennik.App
|
||||
import pl.szczodrzynski.edziennik.MainActivity
|
||||
import pl.szczodrzynski.edziennik.R
|
||||
import pl.szczodrzynski.edziennik.databinding.AttendanceConfigDialogBinding
|
||||
import pl.szczodrzynski.edziennik.ext.onChange
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.base.ConfigDialog
|
||||
|
||||
class AttendanceConfigDialog(
|
||||
val activity: AppCompatActivity,
|
||||
private val reloadOnDismiss: Boolean = true,
|
||||
val onShowListener: ((tag: String) -> Unit)? = null,
|
||||
val onDismissListener: ((tag: String) -> Unit)? = null
|
||||
activity: AppCompatActivity,
|
||||
reloadOnDismiss: Boolean = true,
|
||||
onShowListener: ((tag: String) -> Unit)? = null,
|
||||
onDismissListener: ((tag: String) -> Unit)? = null,
|
||||
) : ConfigDialog<AttendanceConfigDialogBinding>(
|
||||
activity,
|
||||
reloadOnDismiss,
|
||||
onShowListener,
|
||||
onDismissListener,
|
||||
) {
|
||||
companion object {
|
||||
const val TAG = "GradesConfigDialog"
|
||||
}
|
||||
|
||||
private val app by lazy { activity.application as App }
|
||||
override val TAG = "AttendanceConfigDialog"
|
||||
|
||||
override fun getTitleRes() = R.string.menu_attendance_config
|
||||
override fun inflate(layoutInflater: LayoutInflater) =
|
||||
AttendanceConfigDialogBinding.inflate(layoutInflater)
|
||||
|
||||
private val profileConfig by lazy { app.config.getFor(app.profileId).attendance }
|
||||
|
||||
private lateinit var b: AttendanceConfigDialogBinding
|
||||
private lateinit var dialog: AlertDialog
|
||||
|
||||
init { run {
|
||||
if (activity.isFinishing)
|
||||
return@run
|
||||
b = AttendanceConfigDialogBinding.inflate(activity.layoutInflater)
|
||||
onShowListener?.invoke(TAG)
|
||||
dialog = MaterialAlertDialogBuilder(activity)
|
||||
.setTitle(R.string.menu_attendance_config)
|
||||
.setView(b.root)
|
||||
.setPositiveButton(R.string.ok) { dialog, _ -> dialog.dismiss() }
|
||||
.setOnDismissListener {
|
||||
saveConfig()
|
||||
onDismissListener?.invoke(TAG)
|
||||
if (reloadOnDismiss) (activity as? MainActivity)?.reloadTarget()
|
||||
}
|
||||
.create()
|
||||
initView()
|
||||
loadConfig()
|
||||
dialog.show()
|
||||
}}
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
private fun loadConfig() {
|
||||
override suspend fun loadConfig() {
|
||||
b.useSymbols.isChecked = profileConfig.useSymbols
|
||||
b.groupConsecutiveDays.isChecked = profileConfig.groupConsecutiveDays
|
||||
b.showPresenceInMonth.isChecked = profileConfig.showPresenceInMonth
|
||||
}
|
||||
|
||||
private fun saveConfig() {
|
||||
// nothing to do here, yet
|
||||
}
|
||||
|
||||
private fun initView() {
|
||||
override fun initView() {
|
||||
b.useSymbols.onChange { _, isChecked ->
|
||||
profileConfig.useSymbols = isChecked
|
||||
}
|
||||
|
@ -4,40 +4,31 @@
|
||||
|
||||
package pl.szczodrzynski.edziennik.ui.dialogs.settings
|
||||
|
||||
import android.widget.TextView
|
||||
import android.view.LayoutInflater
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.widget.addTextChangedListener
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.google.android.material.textfield.TextInputEditText
|
||||
import com.google.android.material.textfield.TextInputLayout
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import pl.szczodrzynski.edziennik.*
|
||||
import pl.szczodrzynski.edziennik.ext.onClick
|
||||
import pl.szczodrzynski.edziennik.R
|
||||
import pl.szczodrzynski.edziennik.databinding.DialogEditTextBinding
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.base.BindingDialog
|
||||
import pl.szczodrzynski.edziennik.utils.models.Time
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
class BellSyncConfigDialog(
|
||||
val activity: AppCompatActivity,
|
||||
val onChangeListener: (() -> Unit)? = null,
|
||||
val onShowListener: ((tag: String) -> Unit)? = null,
|
||||
val onDismissListener: ((tag: String) -> Unit)? = null
|
||||
) : CoroutineScope {
|
||||
companion object {
|
||||
private const val TAG = "BellSyncConfigDialog"
|
||||
}
|
||||
activity: AppCompatActivity,
|
||||
private val onChangeListener: (() -> Unit)? = null,
|
||||
onShowListener: ((tag: String) -> Unit)? = null,
|
||||
onDismissListener: ((tag: String) -> Unit)? = null,
|
||||
) : BindingDialog<DialogEditTextBinding>(activity, onShowListener, onDismissListener) {
|
||||
|
||||
private lateinit var app: App
|
||||
private lateinit var dialog: AlertDialog
|
||||
override val TAG = "BellSyncConfigDialog"
|
||||
|
||||
private val job = Job()
|
||||
override val coroutineContext: CoroutineContext
|
||||
get() = job + Dispatchers.Main
|
||||
override fun getTitleRes() = R.string.bell_sync_title
|
||||
override fun inflate(layoutInflater: LayoutInflater) =
|
||||
DialogEditTextBinding.inflate(layoutInflater)
|
||||
|
||||
// local variables go here
|
||||
override fun getPositiveButtonText() = R.string.ok
|
||||
override fun getNeutralButtonText() = R.string.reset
|
||||
override fun getNegativeButtonText() = R.string.cancel
|
||||
|
||||
private fun parse(input: String): Pair<Time, Int>? {
|
||||
if (input.length < 8) {
|
||||
@ -56,51 +47,28 @@ class BellSyncConfigDialog(
|
||||
return time to multiplier
|
||||
}
|
||||
|
||||
init { run {
|
||||
if (activity.isFinishing)
|
||||
return@run
|
||||
onShowListener?.invoke(TAG)
|
||||
app = activity.applicationContext as App
|
||||
|
||||
dialog = MaterialAlertDialogBuilder(activity)
|
||||
.setTitle(R.string.bell_sync_title)
|
||||
.setView(R.layout.dialog_edit_text)
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.setNeutralButton(R.string.reset) { _, _ ->
|
||||
app.config.timetable.bellSyncDiff = null
|
||||
app.config.timetable.bellSyncMultiplier = 0
|
||||
onChangeListener?.invoke()
|
||||
}
|
||||
.setOnDismissListener {
|
||||
onDismissListener?.invoke(TAG)
|
||||
}
|
||||
.show()
|
||||
|
||||
val message = dialog.findViewById<TextView>(android.R.id.title)
|
||||
val editText = dialog.findViewById<TextInputEditText>(android.R.id.text1)
|
||||
val textLayout = dialog.findViewById<TextInputLayout>(R.id.text_input_layout)
|
||||
|
||||
message?.setText(R.string.bell_sync_adjust_content)
|
||||
editText?.hint = "±H:MM:SS"
|
||||
editText?.setText(app.config.timetable.bellSyncDiff?.let {
|
||||
override suspend fun onShow() {
|
||||
b.title.setText(R.string.bell_sync_adjust_content)
|
||||
b.text1.hint = "±H:MM:SS"
|
||||
b.text1.setText(app.config.timetable.bellSyncDiff?.let {
|
||||
(if (app.config.timetable.bellSyncMultiplier == -1) "-" else "+") + it.stringHMS
|
||||
} ?: "+0:00:00")
|
||||
editText?.addTextChangedListener { text ->
|
||||
b.text1.addTextChangedListener { text ->
|
||||
val input = text?.toString()
|
||||
textLayout?.error =
|
||||
b.textInputLayout.error =
|
||||
if (input != null && parse(input) == null)
|
||||
activity.getString(R.string.bell_sync_adjust_error)
|
||||
else
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
dialog.getButton(AlertDialog.BUTTON_POSITIVE)?.onClick {
|
||||
val input = editText?.text?.toString() ?: return@onClick
|
||||
override suspend fun onPositiveClick(): Boolean {
|
||||
val input = b.text1.text?.toString() ?: return NO_DISMISS
|
||||
val parsed = parse(input)
|
||||
if (parsed == null) {
|
||||
Toast.makeText(activity, R.string.bell_sync_adjust_error, Toast.LENGTH_SHORT).show()
|
||||
return@onClick
|
||||
return NO_DISMISS
|
||||
}
|
||||
|
||||
val (time, multiplier) = parsed
|
||||
@ -112,7 +80,13 @@ class BellSyncConfigDialog(
|
||||
app.config.timetable.bellSyncMultiplier = multiplier
|
||||
|
||||
onChangeListener?.invoke()
|
||||
dialog.dismiss()
|
||||
return DISMISS
|
||||
}
|
||||
|
||||
override suspend fun onNeutralClick(): Boolean {
|
||||
app.config.timetable.bellSyncDiff = null
|
||||
app.config.timetable.bellSyncMultiplier = 0
|
||||
onChangeListener?.invoke()
|
||||
return DISMISS
|
||||
}
|
||||
}}
|
||||
}
|
||||
|
@ -5,17 +5,18 @@
|
||||
package pl.szczodrzynski.edziennik.ui.dialogs.settings
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import android.view.LayoutInflater
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.view.isVisible
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import it.sephiroth.android.library.numberpicker.doOnStopTrackingTouch
|
||||
import pl.szczodrzynski.edziennik.*
|
||||
import pl.szczodrzynski.edziennik.R
|
||||
import pl.szczodrzynski.edziennik.databinding.DialogConfigGradesBinding
|
||||
import pl.szczodrzynski.edziennik.ext.join
|
||||
import pl.szczodrzynski.edziennik.ext.onChange
|
||||
import pl.szczodrzynski.edziennik.ext.onClick
|
||||
import pl.szczodrzynski.edziennik.ext.setOnSelectedListener
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.base.ConfigDialog
|
||||
import pl.szczodrzynski.edziennik.utils.managers.GradesManager.Companion.COLOR_MODE_DEFAULT
|
||||
import pl.szczodrzynski.edziennik.utils.managers.GradesManager.Companion.COLOR_MODE_WEIGHTED
|
||||
import pl.szczodrzynski.edziennik.utils.managers.GradesManager.Companion.ORDER_BY_DATE_DESC
|
||||
@ -25,47 +26,29 @@ import pl.szczodrzynski.edziennik.utils.managers.GradesManager.Companion.YEAR_1_
|
||||
import pl.szczodrzynski.edziennik.utils.managers.GradesManager.Companion.YEAR_1_SEM_2_AVG
|
||||
import pl.szczodrzynski.edziennik.utils.managers.GradesManager.Companion.YEAR_1_SEM_2_SEM
|
||||
import pl.szczodrzynski.edziennik.utils.managers.GradesManager.Companion.YEAR_ALL_GRADES
|
||||
import java.util.*
|
||||
|
||||
class GradesConfigDialog(
|
||||
val activity: AppCompatActivity,
|
||||
private val reloadOnDismiss: Boolean = true,
|
||||
val onShowListener: ((tag: String) -> Unit)? = null,
|
||||
val onDismissListener: ((tag: String) -> Unit)? = null
|
||||
activity: AppCompatActivity,
|
||||
reloadOnDismiss: Boolean = true,
|
||||
onShowListener: ((tag: String) -> Unit)? = null,
|
||||
onDismissListener: ((tag: String) -> Unit)? = null,
|
||||
) : ConfigDialog<DialogConfigGradesBinding>(
|
||||
activity,
|
||||
reloadOnDismiss,
|
||||
onShowListener,
|
||||
onDismissListener,
|
||||
) {
|
||||
companion object {
|
||||
const val TAG = "GradesConfigDialog"
|
||||
}
|
||||
|
||||
private val app by lazy { activity.application as App }
|
||||
private val config by lazy { app.config.grades }
|
||||
override val TAG = "GradesConfigDialog"
|
||||
|
||||
override fun getTitleRes() = R.string.menu_grades_config
|
||||
override fun inflate(layoutInflater: LayoutInflater) =
|
||||
DialogConfigGradesBinding.inflate(layoutInflater)
|
||||
|
||||
private val profileConfig by lazy { app.config.getFor(app.profileId).grades }
|
||||
|
||||
private lateinit var b: DialogConfigGradesBinding
|
||||
private lateinit var dialog: AlertDialog
|
||||
|
||||
init { run {
|
||||
if (activity.isFinishing)
|
||||
return@run
|
||||
b = DialogConfigGradesBinding.inflate(activity.layoutInflater)
|
||||
onShowListener?.invoke(TAG)
|
||||
dialog = MaterialAlertDialogBuilder(activity)
|
||||
.setTitle(R.string.menu_grades_config)
|
||||
.setView(b.root)
|
||||
.setPositiveButton(R.string.ok) { dialog, _ -> dialog.dismiss() }
|
||||
.setOnDismissListener {
|
||||
saveConfig()
|
||||
onDismissListener?.invoke(TAG)
|
||||
if (reloadOnDismiss) (activity as? MainActivity)?.reloadTarget()
|
||||
}
|
||||
.create()
|
||||
initView()
|
||||
loadConfig()
|
||||
dialog.show()
|
||||
}}
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
private fun loadConfig() {
|
||||
override suspend fun loadConfig() {
|
||||
b.customPlusCheckBox.isChecked = profileConfig.plusValue != null
|
||||
b.customPlusValue.isVisible = b.customPlusCheckBox.isChecked
|
||||
b.customMinusCheckBox.isChecked = profileConfig.minusValue != null
|
||||
@ -95,21 +78,23 @@ class GradesConfigDialog(
|
||||
else -> null
|
||||
}?.isChecked = true
|
||||
|
||||
b.dontCountGrades.isChecked = profileConfig.dontCountEnabled && profileConfig.dontCountGrades.isNotEmpty()
|
||||
b.dontCountGrades.isChecked =
|
||||
profileConfig.dontCountEnabled && profileConfig.dontCountGrades.isNotEmpty()
|
||||
b.hideImproved.isChecked = profileConfig.hideImproved
|
||||
b.averageWithoutWeight.isChecked = profileConfig.averageWithoutWeight
|
||||
|
||||
if (profileConfig.dontCountGrades.isEmpty()) {
|
||||
b.dontCountGradesText.setText("nb, 0, bz, bd")
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
b.dontCountGradesText.setText(profileConfig.dontCountGrades.join(", "))
|
||||
}
|
||||
}
|
||||
|
||||
private fun saveConfig() {
|
||||
profileConfig.plusValue = if (b.customPlusCheckBox.isChecked) b.customPlusValue.progress else null
|
||||
profileConfig.minusValue = if (b.customMinusCheckBox.isChecked) b.customMinusValue.progress else null
|
||||
override suspend fun saveConfig() {
|
||||
profileConfig.plusValue =
|
||||
if (b.customPlusCheckBox.isChecked) b.customPlusValue.progress else null
|
||||
profileConfig.minusValue =
|
||||
if (b.customMinusCheckBox.isChecked) b.customMinusValue.progress else null
|
||||
|
||||
b.dontCountGradesText.setText(
|
||||
b.dontCountGradesText
|
||||
@ -125,7 +110,7 @@ class GradesConfigDialog(
|
||||
?: listOf()
|
||||
}
|
||||
|
||||
private fun initView() {
|
||||
override fun initView() {
|
||||
b.customPlusCheckBox.onChange { _, isChecked ->
|
||||
b.customPlusValue.isVisible = isChecked
|
||||
}
|
||||
@ -145,17 +130,31 @@ class GradesConfigDialog(
|
||||
b.sortGradesByDateRadio.setOnSelectedListener { config.orderBy = ORDER_BY_DATE_DESC }
|
||||
b.sortGradesBySubjectRadio.setOnSelectedListener { config.orderBy = ORDER_BY_SUBJECT_ASC }
|
||||
|
||||
b.gradeColorFromERegister.setOnSelectedListener { profileConfig.colorMode = COLOR_MODE_DEFAULT }
|
||||
b.gradeColorFromERegister.setOnSelectedListener {
|
||||
profileConfig.colorMode = COLOR_MODE_DEFAULT
|
||||
}
|
||||
b.gradeColorByValue.setOnSelectedListener { profileConfig.colorMode = COLOR_MODE_WEIGHTED }
|
||||
|
||||
b.gradeAverageMode4.setOnSelectedListener { profileConfig.yearAverageMode = YEAR_ALL_GRADES }
|
||||
b.gradeAverageMode0.setOnSelectedListener { profileConfig.yearAverageMode = YEAR_1_AVG_2_AVG }
|
||||
b.gradeAverageMode1.setOnSelectedListener { profileConfig.yearAverageMode = YEAR_1_SEM_2_AVG }
|
||||
b.gradeAverageMode2.setOnSelectedListener { profileConfig.yearAverageMode = YEAR_1_AVG_2_SEM }
|
||||
b.gradeAverageMode3.setOnSelectedListener { profileConfig.yearAverageMode = YEAR_1_SEM_2_SEM }
|
||||
b.gradeAverageMode4.setOnSelectedListener {
|
||||
profileConfig.yearAverageMode = YEAR_ALL_GRADES
|
||||
}
|
||||
b.gradeAverageMode0.setOnSelectedListener {
|
||||
profileConfig.yearAverageMode = YEAR_1_AVG_2_AVG
|
||||
}
|
||||
b.gradeAverageMode1.setOnSelectedListener {
|
||||
profileConfig.yearAverageMode = YEAR_1_SEM_2_AVG
|
||||
}
|
||||
b.gradeAverageMode2.setOnSelectedListener {
|
||||
profileConfig.yearAverageMode = YEAR_1_AVG_2_SEM
|
||||
}
|
||||
b.gradeAverageMode3.setOnSelectedListener {
|
||||
profileConfig.yearAverageMode = YEAR_1_SEM_2_SEM
|
||||
}
|
||||
|
||||
b.hideImproved.onChange { _, isChecked -> profileConfig.hideImproved = isChecked }
|
||||
b.averageWithoutWeight.onChange { _, isChecked -> profileConfig.averageWithoutWeight = isChecked }
|
||||
b.averageWithoutWeight.onChange { _, isChecked ->
|
||||
profileConfig.averageWithoutWeight = isChecked
|
||||
}
|
||||
|
||||
b.averageWithoutWeightHelp.onClick {
|
||||
MaterialAlertDialogBuilder(activity)
|
||||
|
@ -4,59 +4,42 @@
|
||||
|
||||
package pl.szczodrzynski.edziennik.ui.dialogs.settings
|
||||
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import android.view.LayoutInflater
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import pl.szczodrzynski.edziennik.App
|
||||
import pl.szczodrzynski.edziennik.MainActivity
|
||||
import pl.szczodrzynski.edziennik.R
|
||||
import pl.szczodrzynski.edziennik.databinding.MessagesConfigDialogBinding
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.base.ConfigDialog
|
||||
|
||||
class MessagesConfigDialog(
|
||||
private val activity: AppCompatActivity,
|
||||
private val reloadOnDismiss: Boolean = true,
|
||||
private val onShowListener: ((tag: String) -> Unit)? = null,
|
||||
private val onDismissListener: ((tag: String) -> Unit)? = null
|
||||
activity: AppCompatActivity,
|
||||
reloadOnDismiss: Boolean = true,
|
||||
onShowListener: ((tag: String) -> Unit)? = null,
|
||||
onDismissListener: ((tag: String) -> Unit)? = null,
|
||||
) : ConfigDialog<MessagesConfigDialogBinding>(
|
||||
activity,
|
||||
reloadOnDismiss,
|
||||
onShowListener,
|
||||
onDismissListener,
|
||||
) {
|
||||
companion object {
|
||||
const val TAG = "MessagesConfigDialog"
|
||||
}
|
||||
|
||||
private val app by lazy { activity.application as App }
|
||||
private val config by lazy { app.config.ui }
|
||||
private val profileConfig by lazy { app.config.forProfile().ui }
|
||||
override val TAG = "MessagesConfigDialog"
|
||||
|
||||
private lateinit var b: MessagesConfigDialogBinding
|
||||
private lateinit var dialog: AlertDialog
|
||||
override fun getTitleRes() = R.string.menu_messages_config
|
||||
override fun inflate(layoutInflater: LayoutInflater) =
|
||||
MessagesConfigDialogBinding.inflate(layoutInflater)
|
||||
|
||||
init { run {
|
||||
if (activity.isFinishing)
|
||||
return@run
|
||||
b = MessagesConfigDialogBinding.inflate(activity.layoutInflater)
|
||||
onShowListener?.invoke(TAG)
|
||||
dialog = MaterialAlertDialogBuilder(activity)
|
||||
.setTitle(R.string.menu_messages_config)
|
||||
.setView(b.root)
|
||||
.setPositiveButton(R.string.ok) { dialog, _ -> dialog.dismiss() }
|
||||
.setOnDismissListener {
|
||||
saveConfig()
|
||||
onDismissListener?.invoke(TAG)
|
||||
if (reloadOnDismiss) (activity as? MainActivity)?.reloadTarget()
|
||||
}
|
||||
.create()
|
||||
loadConfig()
|
||||
dialog.show()
|
||||
}}
|
||||
private val profileConfig by lazy { app.config.getFor(app.profileId).ui }
|
||||
|
||||
private fun loadConfig() {
|
||||
override suspend fun loadConfig() {
|
||||
b.config = profileConfig
|
||||
|
||||
b.greetingText.setText(
|
||||
profileConfig.messagesGreetingText ?: "\n\nZ poważaniem\n${app.profile.accountOwnerName}"
|
||||
profileConfig.messagesGreetingText
|
||||
?: "\n\nZ poważaniem\n${app.profile.accountOwnerName}"
|
||||
)
|
||||
}
|
||||
|
||||
private fun saveConfig() {
|
||||
override suspend fun saveConfig() {
|
||||
val greetingText = b.greetingText.text?.toString()?.trim()
|
||||
if (greetingText.isNullOrEmpty())
|
||||
profileConfig.messagesGreetingText = null
|
||||
|
@ -4,13 +4,7 @@
|
||||
|
||||
package pl.szczodrzynski.edziennik.ui.dialogs.settings
|
||||
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import pl.szczodrzynski.edziennik.App
|
||||
import pl.szczodrzynski.edziennik.MainActivity
|
||||
import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_AGENDA
|
||||
import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_ANNOUNCEMENTS
|
||||
@ -24,73 +18,45 @@ import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_NOTIFICATIO
|
||||
import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_SETTINGS
|
||||
import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_TIMETABLE
|
||||
import pl.szczodrzynski.edziennik.R
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.base.BaseDialog
|
||||
|
||||
class MiniMenuConfigDialog(
|
||||
val activity: AppCompatActivity,
|
||||
val onShowListener: ((tag: String) -> Unit)? = null,
|
||||
val onDismissListener: ((tag: String) -> Unit)? = null
|
||||
) : CoroutineScope {
|
||||
companion object {
|
||||
private const val TAG = "MiniMenuConfigDialog"
|
||||
}
|
||||
activity: AppCompatActivity,
|
||||
onShowListener: ((tag: String) -> Unit)? = null,
|
||||
onDismissListener: ((tag: String) -> Unit)? = null,
|
||||
) : BaseDialog(activity, onShowListener, onDismissListener) {
|
||||
|
||||
private lateinit var app: App
|
||||
private lateinit var dialog: AlertDialog
|
||||
override val TAG = "BellSyncTimeChooseDialog"
|
||||
|
||||
private val job = Job()
|
||||
override val coroutineContext: CoroutineContext
|
||||
get() = job + Dispatchers.Main
|
||||
override fun getTitleRes() = R.string.settings_theme_mini_drawer_buttons_dialog_title
|
||||
override fun getMessageRes() = R.string.settings_theme_mini_drawer_buttons_dialog_text
|
||||
override fun getPositiveButtonText() = R.string.ok
|
||||
override fun getNegativeButtonText() = R.string.cancel
|
||||
|
||||
// local variables go here
|
||||
override fun getMultiChoiceItems(): Map<CharSequence, Any> = mapOf(
|
||||
R.string.menu_home_page to DRAWER_ITEM_HOME,
|
||||
R.string.menu_timetable to DRAWER_ITEM_TIMETABLE,
|
||||
R.string.menu_agenda to DRAWER_ITEM_AGENDA,
|
||||
R.string.menu_grades to DRAWER_ITEM_GRADES,
|
||||
R.string.menu_messages to DRAWER_ITEM_MESSAGES,
|
||||
R.string.menu_homework to DRAWER_ITEM_HOMEWORK,
|
||||
R.string.menu_notices to DRAWER_ITEM_BEHAVIOUR,
|
||||
R.string.menu_attendance to DRAWER_ITEM_ATTENDANCE,
|
||||
R.string.menu_announcements to DRAWER_ITEM_ANNOUNCEMENTS,
|
||||
R.string.menu_notifications to DRAWER_ITEM_NOTIFICATIONS,
|
||||
R.string.menu_settings to DRAWER_ITEM_SETTINGS,
|
||||
).mapKeys { (resId, _) -> activity.getString(resId) }
|
||||
|
||||
init { run {
|
||||
if (activity.isFinishing)
|
||||
return@run
|
||||
onShowListener?.invoke(TAG)
|
||||
app = activity.applicationContext as App
|
||||
override fun getDefaultSelectedItems() = app.config.ui.miniMenuButtons.toSet()
|
||||
|
||||
val buttons = mapOf(
|
||||
DRAWER_ITEM_HOME to R.string.menu_home_page,
|
||||
DRAWER_ITEM_TIMETABLE to R.string.menu_timetable,
|
||||
DRAWER_ITEM_AGENDA to R.string.menu_agenda,
|
||||
DRAWER_ITEM_GRADES to R.string.menu_grades,
|
||||
DRAWER_ITEM_MESSAGES to R.string.menu_messages,
|
||||
DRAWER_ITEM_HOMEWORK to R.string.menu_homework,
|
||||
DRAWER_ITEM_BEHAVIOUR to R.string.menu_notices,
|
||||
DRAWER_ITEM_ATTENDANCE to R.string.menu_attendance,
|
||||
DRAWER_ITEM_ANNOUNCEMENTS to R.string.menu_announcements,
|
||||
DRAWER_ITEM_NOTIFICATIONS to R.string.menu_notifications,
|
||||
DRAWER_ITEM_SETTINGS to R.string.menu_settings
|
||||
)
|
||||
val miniMenuButtons = app.config.ui.miniMenuButtons
|
||||
|
||||
dialog = MaterialAlertDialogBuilder(activity)
|
||||
.setTitle(R.string.settings_theme_mini_drawer_buttons_dialog_title)
|
||||
//.setMessage(R.string.settings_theme_mini_drawer_buttons_dialog_text)
|
||||
.setMultiChoiceItems(
|
||||
buttons.map { activity.getString(it.value) }.toTypedArray(),
|
||||
buttons.map { it.key in miniMenuButtons }.toBooleanArray(),
|
||||
null
|
||||
)
|
||||
.setPositiveButton(R.string.ok) { _, _ ->
|
||||
app.config.ui.miniMenuButtons =
|
||||
buttons.keys.mapIndexedNotNull { index, id ->
|
||||
if (dialog.listView.checkedItemPositions[index])
|
||||
id
|
||||
else
|
||||
null
|
||||
}
|
||||
override suspend fun onShow() = Unit
|
||||
|
||||
override suspend fun onPositiveClick(): Boolean {
|
||||
app.config.ui.miniMenuButtons = getMultiSelection().filterIsInstance<Int>()
|
||||
if (activity is MainActivity) {
|
||||
activity.setDrawerItems()
|
||||
activity.drawer.updateBadges()
|
||||
}
|
||||
return DISMISS
|
||||
}
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.setOnDismissListener {
|
||||
onDismissListener?.invoke(TAG)
|
||||
}
|
||||
.show()
|
||||
}}
|
||||
}
|
||||
|
@ -4,96 +4,71 @@
|
||||
|
||||
package pl.szczodrzynski.edziennik.ui.dialogs.settings
|
||||
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import pl.szczodrzynski.edziennik.App
|
||||
import pl.szczodrzynski.edziennik.R
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Notification
|
||||
import pl.szczodrzynski.edziennik.ext.onClick
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.base.BaseDialog
|
||||
|
||||
// TODO refactor dialog to allow configuring other profiles
|
||||
// than the selected one in UI
|
||||
class NotificationFilterDialog(
|
||||
val activity: AppCompatActivity,
|
||||
val onShowListener: ((tag: String) -> Unit)? = null,
|
||||
val onDismissListener: ((tag: String) -> Unit)? = null
|
||||
) : CoroutineScope {
|
||||
companion object {
|
||||
private const val TAG = "NotificationFilterDialog"
|
||||
private val notificationTypes = listOf(
|
||||
Notification.TYPE_TIMETABLE_LESSON_CHANGE to R.string.notification_type_timetable_lesson_change,
|
||||
Notification.TYPE_NEW_GRADE to R.string.notification_type_new_grade,
|
||||
Notification.TYPE_NEW_EVENT to R.string.notification_type_new_event,
|
||||
Notification.TYPE_NEW_HOMEWORK to R.string.notification_type_new_homework,
|
||||
Notification.TYPE_NEW_MESSAGE to R.string.notification_type_new_message,
|
||||
Notification.TYPE_LUCKY_NUMBER to R.string.notification_type_lucky_number,
|
||||
Notification.TYPE_NEW_NOTICE to R.string.notification_type_notice,
|
||||
Notification.TYPE_NEW_ATTENDANCE to R.string.notification_type_attendance,
|
||||
Notification.TYPE_NEW_ANNOUNCEMENT to R.string.notification_type_new_announcement,
|
||||
Notification.TYPE_NEW_SHARED_EVENT to R.string.notification_type_new_shared_event,
|
||||
Notification.TYPE_NEW_SHARED_HOMEWORK to R.string.notification_type_new_shared_homework,
|
||||
Notification.TYPE_REMOVED_SHARED_EVENT to R.string.notification_type_removed_shared_event,
|
||||
Notification.TYPE_TEACHER_ABSENCE to R.string.notification_type_new_teacher_absence
|
||||
)
|
||||
activity: AppCompatActivity,
|
||||
onShowListener: ((tag: String) -> Unit)? = null,
|
||||
onDismissListener: ((tag: String) -> Unit)? = null,
|
||||
) : BaseDialog(activity, onShowListener, onDismissListener) {
|
||||
|
||||
override val TAG = "NotificationFilterDialog"
|
||||
|
||||
override fun getTitleRes() = R.string.dialog_notification_filter_title
|
||||
override fun getMessageRes() = R.string.dialog_notification_filter_text
|
||||
override fun getPositiveButtonText() = R.string.ok
|
||||
override fun getNegativeButtonText() = R.string.cancel
|
||||
|
||||
override fun getMultiChoiceItems(): Map<CharSequence, Any> {
|
||||
notificationTypes = mapOf(
|
||||
R.string.notification_type_timetable_lesson_change to Notification.TYPE_TIMETABLE_LESSON_CHANGE,
|
||||
R.string.notification_type_new_grade to Notification.TYPE_NEW_GRADE,
|
||||
R.string.notification_type_new_event to Notification.TYPE_NEW_EVENT,
|
||||
R.string.notification_type_new_homework to Notification.TYPE_NEW_HOMEWORK,
|
||||
R.string.notification_type_new_message to Notification.TYPE_NEW_MESSAGE,
|
||||
R.string.notification_type_lucky_number to Notification.TYPE_LUCKY_NUMBER,
|
||||
R.string.notification_type_notice to Notification.TYPE_NEW_NOTICE,
|
||||
R.string.notification_type_attendance to Notification.TYPE_NEW_ATTENDANCE,
|
||||
R.string.notification_type_new_announcement to Notification.TYPE_NEW_ANNOUNCEMENT,
|
||||
R.string.notification_type_new_shared_event to Notification.TYPE_NEW_SHARED_EVENT,
|
||||
R.string.notification_type_new_shared_homework to Notification.TYPE_NEW_SHARED_HOMEWORK,
|
||||
R.string.notification_type_removed_shared_event to Notification.TYPE_REMOVED_SHARED_EVENT,
|
||||
R.string.notification_type_new_teacher_absence to Notification.TYPE_TEACHER_ABSENCE,
|
||||
).mapKeys { (resId, _) -> activity.getString(resId) }
|
||||
return notificationTypes
|
||||
}
|
||||
|
||||
private lateinit var app: App
|
||||
private lateinit var dialog: AlertDialog
|
||||
override fun getDefaultSelectedItems() =
|
||||
notificationTypes.values.subtract(app.config.forProfile().sync.notificationFilter)
|
||||
|
||||
private val job = Job()
|
||||
override val coroutineContext: CoroutineContext
|
||||
get() = job + Dispatchers.Main
|
||||
override suspend fun onShow() = Unit
|
||||
|
||||
private val notificationFilter = mutableListOf<Int>()
|
||||
private lateinit var notificationTypes: Map<CharSequence, Int>
|
||||
|
||||
init { run {
|
||||
if (activity.isFinishing)
|
||||
return@run
|
||||
onShowListener?.invoke(TAG)
|
||||
app = activity.applicationContext as App
|
||||
override suspend fun onPositiveClick(): Boolean {
|
||||
val enabledTypes = getMultiSelection().filterIsInstance<Int>()
|
||||
val disabledTypes = notificationTypes.values.subtract(enabledTypes).toList()
|
||||
|
||||
notificationFilter.clear()
|
||||
notificationFilter += app.config.forProfile().sync.notificationFilter
|
||||
val items = notificationTypes.map { app.getString(it.second) }.toTypedArray()
|
||||
val checkedItems = notificationTypes.map { !notificationFilter.contains(it.first) }.toBooleanArray()
|
||||
|
||||
dialog = MaterialAlertDialogBuilder(activity)
|
||||
.setTitle(R.string.dialog_notification_filter_title)
|
||||
//.setMessage(R.string.dialog_notification_filter_text)
|
||||
.setMultiChoiceItems(items, checkedItems) { _, which, isChecked ->
|
||||
val type = notificationTypes[which].first
|
||||
notificationFilter.remove(type)
|
||||
if (!isChecked)
|
||||
notificationFilter += type
|
||||
}
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.setOnDismissListener {
|
||||
onDismissListener?.invoke(TAG)
|
||||
}
|
||||
.show()
|
||||
|
||||
dialog.getButton(AlertDialog.BUTTON_POSITIVE)?.onClick {
|
||||
if (notificationFilter.isEmpty()) {
|
||||
app.config.forProfile().sync.notificationFilter = notificationFilter
|
||||
dialog.dismiss()
|
||||
return@onClick
|
||||
}
|
||||
if (disabledTypes.isNotEmpty()) {
|
||||
// warn user when he tries to disable some notifications
|
||||
MaterialAlertDialogBuilder(activity)
|
||||
.setTitle(R.string.are_you_sure)
|
||||
.setMessage(R.string.notification_filter_warning)
|
||||
.setPositiveButton(R.string.ok) { _, _ ->
|
||||
app.config.forProfile().sync.notificationFilter = notificationFilter
|
||||
dialog.dismiss()
|
||||
app.config.forProfile().sync.notificationFilter = disabledTypes
|
||||
dismiss()
|
||||
}
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.show()
|
||||
return NO_DISMISS
|
||||
}
|
||||
|
||||
app.config.forProfile().sync.notificationFilter = disabledTypes
|
||||
|
||||
return DISMISS
|
||||
}
|
||||
}}
|
||||
}
|
||||
|
@ -5,14 +5,10 @@
|
||||
package pl.szczodrzynski.edziennik.ui.dialogs.settings
|
||||
|
||||
import android.content.res.ColorStateList
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import android.view.LayoutInflater
|
||||
import androidx.core.widget.addTextChangedListener
|
||||
import com.google.android.material.color.MaterialColors
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.google.android.material.shape.MaterialShapeDrawable
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import pl.szczodrzynski.edziennik.*
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Profile
|
||||
import pl.szczodrzynski.edziennik.databinding.DialogProfileConfigBinding
|
||||
@ -20,54 +16,38 @@ import pl.szczodrzynski.edziennik.ext.dp
|
||||
import pl.szczodrzynski.edziennik.ext.onChange
|
||||
import pl.szczodrzynski.edziennik.ext.onClick
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.ProfileRemoveDialog
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.base.BindingDialog
|
||||
|
||||
class ProfileConfigDialog(
|
||||
val activity: MainActivity,
|
||||
val profile: Profile,
|
||||
val onProfileSaved: ((profile: Profile) -> Unit)? = null,
|
||||
val onShowListener: ((tag: String) -> Unit)? = null,
|
||||
val onDismissListener: ((tag: String) -> Unit)? = null
|
||||
) : CoroutineScope {
|
||||
companion object {
|
||||
private const val TAG = "ProfileConfigDialog"
|
||||
}
|
||||
activity: MainActivity,
|
||||
private val profile: Profile,
|
||||
private val onProfileSaved: ((profile: Profile) -> Unit)? = null,
|
||||
onShowListener: ((tag: String) -> Unit)? = null,
|
||||
onDismissListener: ((tag: String) -> Unit)? = null,
|
||||
) : BindingDialog<DialogProfileConfigBinding>(activity, onShowListener, onDismissListener) {
|
||||
|
||||
private lateinit var app: App
|
||||
private lateinit var b: DialogProfileConfigBinding
|
||||
private lateinit var dialog: AlertDialog
|
||||
override val TAG = "ProfileConfigDialog"
|
||||
|
||||
private val job = Job()
|
||||
override val coroutineContext: CoroutineContext
|
||||
get() = job + Dispatchers.Main
|
||||
override fun getTitleRes(): Int? = null
|
||||
override fun inflate(layoutInflater: LayoutInflater) =
|
||||
DialogProfileConfigBinding.inflate(layoutInflater)
|
||||
|
||||
override fun getPositiveButtonText() = R.string.close
|
||||
|
||||
// local variables go here
|
||||
private var profileChanged = false
|
||||
private var profileRemoved = false
|
||||
|
||||
init { run {
|
||||
if (activity.isFinishing)
|
||||
return@run
|
||||
onShowListener?.invoke(TAG)
|
||||
app = activity.applicationContext as App
|
||||
b = DialogProfileConfigBinding.inflate(activity.layoutInflater)
|
||||
dialog = MaterialAlertDialogBuilder(activity)
|
||||
.setView(b.root)
|
||||
.setPositiveButton(R.string.close, null)
|
||||
.setOnDismissListener {
|
||||
if (!profileRemoved && profileChanged) {
|
||||
app.profileSave(profile)
|
||||
onProfileSaved?.invoke(profile)
|
||||
}
|
||||
onDismissListener?.invoke(TAG)
|
||||
}
|
||||
.show()
|
||||
|
||||
override suspend fun onShow() {
|
||||
b.profile = profile
|
||||
profile.applyImageTo(b.image)
|
||||
|
||||
// I can't believe how simple it is to get the dialog's background color !!
|
||||
val shape = MaterialShapeDrawable(activity, null, R.attr.alertDialogStyle, R.style.MaterialAlertDialog_MaterialComponents)
|
||||
val shape = MaterialShapeDrawable(
|
||||
activity,
|
||||
null,
|
||||
R.attr.alertDialogStyle,
|
||||
R.style.MaterialAlertDialog_MaterialComponents
|
||||
)
|
||||
val surface = MaterialColors.getColor(activity, R.attr.colorSurface, TAG)
|
||||
shape.setCornerSize(18.dp.toFloat())
|
||||
shape.initializeElevationOverlay(activity)
|
||||
@ -84,6 +64,8 @@ class ProfileConfigDialog(
|
||||
}
|
||||
|
||||
b.imageButton.onClick {
|
||||
if (activity !is MainActivity)
|
||||
return@onClick
|
||||
activity.requestHandler.requestProfileImage(profile) {
|
||||
val profile = it as? Profile ?: return@requestProfileImage
|
||||
if (this@ProfileConfigDialog.profile == profile) {
|
||||
@ -98,7 +80,14 @@ class ProfileConfigDialog(
|
||||
ProfileRemoveDialog(activity, profile.id, profile.name) {
|
||||
profileRemoved = true
|
||||
dialog.dismiss()
|
||||
}.show()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDismiss() {
|
||||
if (!profileRemoved && profileChanged) {
|
||||
app.profileSave(profile)
|
||||
onProfileSaved?.invoke(profile)
|
||||
}
|
||||
}
|
||||
}}
|
||||
}
|
||||
|
@ -4,44 +4,28 @@
|
||||
|
||||
package pl.szczodrzynski.edziennik.ui.dialogs.settings
|
||||
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import pl.szczodrzynski.edziennik.*
|
||||
import pl.szczodrzynski.edziennik.R
|
||||
import pl.szczodrzynski.edziennik.ext.HOUR
|
||||
import pl.szczodrzynski.edziennik.ext.MINUTE
|
||||
import pl.szczodrzynski.edziennik.ext.getSyncInterval
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.base.BaseDialog
|
||||
|
||||
class SyncIntervalDialog(
|
||||
val activity: AppCompatActivity,
|
||||
val onChangeListener: (() -> Unit)? = null,
|
||||
val onShowListener: ((tag: String) -> Unit)? = null,
|
||||
val onDismissListener: ((tag: String) -> Unit)? = null
|
||||
) : CoroutineScope {
|
||||
companion object {
|
||||
private const val TAG = "SyncIntervalDialog"
|
||||
}
|
||||
activity: AppCompatActivity,
|
||||
private val onChangeListener: (() -> Unit)? = null,
|
||||
onShowListener: ((tag: String) -> Unit)? = null,
|
||||
onDismissListener: ((tag: String) -> Unit)? = null,
|
||||
) : BaseDialog(activity, onShowListener, onDismissListener) {
|
||||
|
||||
private lateinit var app: App
|
||||
private lateinit var dialog: AlertDialog
|
||||
override val TAG = "SyncIntervalDialog"
|
||||
|
||||
private val job = Job()
|
||||
override val coroutineContext: CoroutineContext
|
||||
get() = job + Dispatchers.Main
|
||||
override fun getTitleRes() = R.string.settings_sync_sync_interval_dialog_title
|
||||
override fun getMessageRes() = R.string.settings_sync_sync_interval_dialog_text
|
||||
override fun getPositiveButtonText() = R.string.ok
|
||||
override fun getNegativeButtonText() = R.string.cancel
|
||||
|
||||
// local variables go here
|
||||
|
||||
init { run {
|
||||
if (activity.isFinishing)
|
||||
return@run
|
||||
onShowListener?.invoke(TAG)
|
||||
app = activity.applicationContext as App
|
||||
|
||||
val intervals = listOf(
|
||||
override fun getSingleChoiceItems(): Map<CharSequence, Any> = listOf(
|
||||
30 * MINUTE,
|
||||
45 * MINUTE,
|
||||
60 * MINUTE,
|
||||
@ -50,31 +34,17 @@ class SyncIntervalDialog(
|
||||
3 * HOUR,
|
||||
4 * HOUR,
|
||||
6 * HOUR,
|
||||
10 * HOUR
|
||||
)
|
||||
val intervalNames = intervals.map {
|
||||
activity.getSyncInterval(it.toInt())
|
||||
}
|
||||
10 * HOUR,
|
||||
).associateBy { activity.getSyncInterval(it.toInt()) }
|
||||
|
||||
dialog = MaterialAlertDialogBuilder(activity)
|
||||
.setTitle(R.string.settings_sync_sync_interval_dialog_title)
|
||||
//.setMessage(R.string.settings_sync_sync_interval_dialog_text)
|
||||
.setSingleChoiceItems(
|
||||
intervalNames.toTypedArray(),
|
||||
intervals.indexOf(app.config.sync.interval.toLong()),
|
||||
null
|
||||
)
|
||||
.setPositiveButton(R.string.ok) { _, _ ->
|
||||
val which = dialog.listView.checkedItemPosition
|
||||
override fun getDefaultSelectedItem() = app.config.sync.interval.toLong()
|
||||
|
||||
val interval = intervals[which]
|
||||
override suspend fun onShow() = Unit
|
||||
|
||||
override suspend fun onPositiveClick(): Boolean {
|
||||
val interval = getSingleSelection() as? Long ?: return DISMISS
|
||||
app.config.sync.interval = interval.toInt()
|
||||
onChangeListener?.invoke()
|
||||
return DISMISS
|
||||
}
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.setOnDismissListener {
|
||||
onDismissListener?.invoke(TAG)
|
||||
}
|
||||
.show()
|
||||
}}
|
||||
}
|
||||
|
@ -4,62 +4,38 @@
|
||||
|
||||
package pl.szczodrzynski.edziennik.ui.dialogs.settings
|
||||
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import pl.szczodrzynski.edziennik.App
|
||||
import pl.szczodrzynski.edziennik.R
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.base.BaseDialog
|
||||
import pl.szczodrzynski.edziennik.utils.Themes
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
class ThemeChooserDialog(
|
||||
val activity: AppCompatActivity,
|
||||
val onShowListener: ((tag: String) -> Unit)? = null,
|
||||
val onDismissListener: ((tag: String) -> Unit)? = null
|
||||
) : CoroutineScope {
|
||||
companion object {
|
||||
private const val TAG = "ThemeChooserDialog"
|
||||
activity: AppCompatActivity,
|
||||
onShowListener: ((tag: String) -> Unit)? = null,
|
||||
onDismissListener: ((tag: String) -> Unit)? = null,
|
||||
) : BaseDialog(activity, onShowListener, onDismissListener) {
|
||||
|
||||
override val TAG = "ThemeChooserDialog"
|
||||
|
||||
override fun getTitleRes() = R.string.settings_theme_theme_text
|
||||
override fun getPositiveButtonText() = R.string.ok
|
||||
override fun getNegativeButtonText() = R.string.cancel
|
||||
|
||||
override fun getSingleChoiceItems(): Map<CharSequence, Any> = Themes.themeList.associate {
|
||||
activity.getString(it.name) to it.id
|
||||
}
|
||||
|
||||
private lateinit var app: App
|
||||
private lateinit var dialog: AlertDialog
|
||||
override fun getDefaultSelectedItem() = Themes.theme.id
|
||||
|
||||
private val job = Job()
|
||||
override val coroutineContext: CoroutineContext
|
||||
get() = job + Dispatchers.Main
|
||||
override suspend fun onShow() = Unit
|
||||
|
||||
// local variables go here
|
||||
|
||||
init { run {
|
||||
if (activity.isFinishing)
|
||||
return@run
|
||||
onShowListener?.invoke(TAG)
|
||||
app = activity.applicationContext as App
|
||||
|
||||
dialog = MaterialAlertDialogBuilder(activity)
|
||||
.setTitle(R.string.settings_theme_theme_text)
|
||||
.setSingleChoiceItems(
|
||||
Themes.getThemeNames(activity).toTypedArray(),
|
||||
Themes.themeIndex,
|
||||
null
|
||||
)
|
||||
.setPositiveButton(R.string.ok) { _, _ ->
|
||||
val which = dialog.listView.checkedItemPosition
|
||||
|
||||
val theme = Themes.themeList[which]
|
||||
if (app.config.ui.theme == theme.id)
|
||||
return@setPositiveButton
|
||||
app.config.ui.theme = theme.id
|
||||
Themes.themeIndex = which
|
||||
override suspend fun onPositiveClick(): Boolean {
|
||||
val themeId = getSingleSelection() as? Int ?: return DISMISS
|
||||
if (app.config.ui.theme != themeId) {
|
||||
app.config.ui.theme = themeId
|
||||
Themes.themeInt = themeId
|
||||
activity.recreate()
|
||||
}
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.setOnDismissListener {
|
||||
onDismissListener?.invoke(TAG)
|
||||
return DISMISS
|
||||
}
|
||||
.show()
|
||||
}}
|
||||
}
|
||||
|
@ -6,89 +6,60 @@ package pl.szczodrzynski.edziennik.ui.dialogs.sync
|
||||
|
||||
import android.text.method.LinkMovementMethod
|
||||
import android.view.LayoutInflater
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import coil.load
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import pl.szczodrzynski.edziennik.App
|
||||
import pl.szczodrzynski.edziennik.BuildConfig
|
||||
import pl.szczodrzynski.edziennik.R
|
||||
import pl.szczodrzynski.edziennik.data.api.szkolny.response.RegisterAvailabilityStatus
|
||||
import pl.szczodrzynski.edziennik.databinding.DialogRegisterUnavailableBinding
|
||||
import pl.szczodrzynski.edziennik.ext.onClick
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.base.BindingDialog
|
||||
import pl.szczodrzynski.edziennik.utils.Utils
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
class RegisterUnavailableDialog(
|
||||
val activity: AppCompatActivity,
|
||||
val status: RegisterAvailabilityStatus,
|
||||
val onShowListener: ((tag: String) -> Unit)? = null,
|
||||
val onDismissListener: ((tag: String) -> Unit)? = null
|
||||
) : CoroutineScope {
|
||||
companion object {
|
||||
private const val TAG = "RegisterUnavailableDialog"
|
||||
activity: AppCompatActivity,
|
||||
private val status: RegisterAvailabilityStatus,
|
||||
onShowListener: ((tag: String) -> Unit)? = null,
|
||||
onDismissListener: ((tag: String) -> Unit)? = null,
|
||||
) : BindingDialog<DialogRegisterUnavailableBinding>(activity, onShowListener, onDismissListener) {
|
||||
|
||||
override val TAG = "RegisterUnavailableDialog"
|
||||
|
||||
override fun getTitleRes(): Int? = null
|
||||
override fun inflate(layoutInflater: LayoutInflater) =
|
||||
DialogRegisterUnavailableBinding.inflate(layoutInflater)
|
||||
|
||||
override fun getPositiveButtonText() = R.string.close
|
||||
|
||||
override suspend fun onBeforeShow(): Boolean {
|
||||
if (!status.available && status.userMessage != null)
|
||||
return true
|
||||
|
||||
if (status.minVersionCode <= BuildConfig.VERSION_CODE)
|
||||
return false
|
||||
|
||||
val update = app.config.update
|
||||
UpdateAvailableDialog(
|
||||
activity = activity,
|
||||
update = update,
|
||||
mandatory = update != null && update.versionCode >= status.minVersionCode,
|
||||
onShowListener = onShowListener,
|
||||
onDismissListener = onDismissListener
|
||||
).show()
|
||||
return false
|
||||
}
|
||||
|
||||
private lateinit var app: App
|
||||
private lateinit var dialog: AlertDialog
|
||||
override suspend fun onShow() {
|
||||
b.message = status.userMessage ?: return
|
||||
b.text.movementMethod = LinkMovementMethod.getInstance()
|
||||
|
||||
private val job = Job()
|
||||
override val coroutineContext: CoroutineContext
|
||||
get() = job + Dispatchers.Main
|
||||
|
||||
init { run {
|
||||
if (activity.isFinishing)
|
||||
return@run
|
||||
onShowListener?.invoke(TAG)
|
||||
app = activity.applicationContext as App
|
||||
|
||||
if (!status.available && status.userMessage != null) {
|
||||
val b = DialogRegisterUnavailableBinding.inflate(LayoutInflater.from(activity), null, false)
|
||||
b.message = status.userMessage
|
||||
if (status.userMessage.image != null)
|
||||
if (status.userMessage.image != null) {
|
||||
b.image.load(status.userMessage.image)
|
||||
}
|
||||
if (status.userMessage.url != null) {
|
||||
b.readMore.onClick {
|
||||
Utils.openUrl(activity, status.userMessage.url)
|
||||
}
|
||||
}
|
||||
b.text.movementMethod = LinkMovementMethod.getInstance()
|
||||
dialog = MaterialAlertDialogBuilder(activity)
|
||||
.setView(b.root)
|
||||
.setPositiveButton(R.string.close) { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
}
|
||||
.setOnDismissListener {
|
||||
onDismissListener?.invoke(TAG)
|
||||
}
|
||||
.show()
|
||||
return@run
|
||||
}
|
||||
|
||||
val update = app.config.update
|
||||
if (status.minVersionCode > BuildConfig.VERSION_CODE) {
|
||||
if (update != null && update.versionCode >= status.minVersionCode) {
|
||||
UpdateAvailableDialog(activity, update, true, onShowListener, onDismissListener)
|
||||
}
|
||||
else {
|
||||
// this *should* never happen
|
||||
dialog = MaterialAlertDialogBuilder(activity)
|
||||
.setTitle(R.string.update_available_title)
|
||||
.setMessage(R.string.update_available_fallback)
|
||||
.setPositiveButton(R.string.update_available_button) { dialog, _ ->
|
||||
Utils.openGooglePlay(activity)
|
||||
dialog.dismiss()
|
||||
}
|
||||
.setCancelable(false)
|
||||
.setOnDismissListener {
|
||||
onDismissListener?.invoke(TAG)
|
||||
}
|
||||
.show()
|
||||
}
|
||||
return@run
|
||||
}
|
||||
}}
|
||||
}
|
||||
|
@ -4,48 +4,24 @@
|
||||
|
||||
package pl.szczodrzynski.edziennik.ui.dialogs.sync
|
||||
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import pl.szczodrzynski.edziennik.App
|
||||
import pl.szczodrzynski.edziennik.R
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.base.BaseDialog
|
||||
|
||||
class ServerMessageDialog(
|
||||
val activity: AppCompatActivity,
|
||||
val title: String,
|
||||
val message: CharSequence,
|
||||
val onShowListener: ((tag: String) -> Unit)? = null,
|
||||
val onDismissListener: ((tag: String) -> Unit)? = null
|
||||
) : CoroutineScope {
|
||||
companion object {
|
||||
private const val TAG = "ServerMessageDialog"
|
||||
}
|
||||
activity: AppCompatActivity,
|
||||
private val titleText: String,
|
||||
private val messageText: CharSequence,
|
||||
onShowListener: ((tag: String) -> Unit)? = null,
|
||||
onDismissListener: ((tag: String) -> Unit)? = null,
|
||||
) : BaseDialog(activity, onShowListener, onDismissListener) {
|
||||
|
||||
private lateinit var app: App
|
||||
private lateinit var dialog: AlertDialog
|
||||
override val TAG = "ServerMessageDialog"
|
||||
|
||||
private val job = Job()
|
||||
override val coroutineContext: CoroutineContext
|
||||
get() = job + Dispatchers.Main
|
||||
override fun getTitle() = titleText
|
||||
override fun getTitleRes(): Int? = null
|
||||
override fun getMessage() = messageText
|
||||
override fun getPositiveButtonText() = R.string.close
|
||||
|
||||
init { run {
|
||||
if (activity.isFinishing)
|
||||
return@run
|
||||
onShowListener?.invoke(TAG)
|
||||
app = activity.applicationContext as App
|
||||
dialog = MaterialAlertDialogBuilder(activity)
|
||||
.setTitle(title)
|
||||
.setMessage(message)
|
||||
.setPositiveButton(R.string.close) { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
}
|
||||
.setOnDismissListener {
|
||||
onDismissListener?.invoke(TAG)
|
||||
}
|
||||
.show()
|
||||
}}
|
||||
override suspend fun onShow() = Unit
|
||||
}
|
||||
|
@ -4,113 +4,93 @@
|
||||
|
||||
package pl.szczodrzynski.edziennik.ui.dialogs.sync
|
||||
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import pl.szczodrzynski.edziennik.App
|
||||
import pl.szczodrzynski.edziennik.MainActivity
|
||||
import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_AGENDA
|
||||
import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_ANNOUNCEMENTS
|
||||
import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_ATTENDANCE
|
||||
import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_BEHAVIOUR
|
||||
import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_GRADES
|
||||
import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_HOME
|
||||
import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_HOMEWORK
|
||||
import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_MESSAGES
|
||||
import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_TIMETABLE
|
||||
import pl.szczodrzynski.edziennik.R
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.EdziennikTask
|
||||
import pl.szczodrzynski.edziennik.databinding.DialogLessonDetailsBinding
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.base.BaseDialog
|
||||
import pl.szczodrzynski.edziennik.ui.messages.list.MessagesFragment
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
class SyncViewListDialog(
|
||||
val activity: MainActivity,
|
||||
val currentViewId: Int? = null
|
||||
) : CoroutineScope {
|
||||
companion object {
|
||||
private const val TAG = "SyncViewListDialog"
|
||||
activity: MainActivity,
|
||||
private val currentViewId: Int,
|
||||
onShowListener: ((tag: String) -> Unit)? = null,
|
||||
onDismissListener: ((tag: String) -> Unit)? = null,
|
||||
) : BaseDialog(activity, onShowListener, onDismissListener) {
|
||||
|
||||
override val TAG = "SyncViewListDialog"
|
||||
|
||||
override fun getTitleRes() = R.string.dialog_sync_view_list_title
|
||||
override fun getPositiveButtonText() = R.string.ok
|
||||
override fun getNeutralButtonText() = R.string.sync_feature_all
|
||||
override fun getNegativeButtonText() = R.string.cancel
|
||||
|
||||
override fun getMultiChoiceItems(): Map<CharSequence, Any> {
|
||||
items = mapOf(
|
||||
R.string.menu_timetable to DRAWER_ITEM_TIMETABLE,
|
||||
R.string.menu_agenda to DRAWER_ITEM_AGENDA,
|
||||
R.string.menu_grades to DRAWER_ITEM_GRADES,
|
||||
R.string.menu_homework to DRAWER_ITEM_HOMEWORK,
|
||||
R.string.menu_notices to DRAWER_ITEM_BEHAVIOUR,
|
||||
R.string.menu_attendance to DRAWER_ITEM_ATTENDANCE,
|
||||
R.string.title_messages_inbox_single to (DRAWER_ITEM_MESSAGES to 0),
|
||||
R.string.title_messages_sent_single to (DRAWER_ITEM_MESSAGES to 1),
|
||||
R.string.menu_announcements to DRAWER_ITEM_ANNOUNCEMENTS,
|
||||
).mapKeys { (resId, _) -> activity.getString(resId) }
|
||||
return items
|
||||
}
|
||||
|
||||
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: DialogLessonDetailsBinding
|
||||
private lateinit var dialog: AlertDialog
|
||||
|
||||
init { run {
|
||||
job = Job()
|
||||
|
||||
val viewIds = arrayOf(
|
||||
MainActivity.DRAWER_ITEM_TIMETABLE,
|
||||
MainActivity.DRAWER_ITEM_AGENDA,
|
||||
MainActivity.DRAWER_ITEM_GRADES,
|
||||
MainActivity.DRAWER_ITEM_HOMEWORK,
|
||||
MainActivity.DRAWER_ITEM_BEHAVIOUR,
|
||||
MainActivity.DRAWER_ITEM_ATTENDANCE,
|
||||
MainActivity.DRAWER_ITEM_MESSAGES,
|
||||
MainActivity.DRAWER_ITEM_MESSAGES,
|
||||
MainActivity.DRAWER_ITEM_ANNOUNCEMENTS
|
||||
)
|
||||
|
||||
val items = arrayOf<String>(
|
||||
app.getString(R.string.menu_timetable),
|
||||
app.getString(R.string.menu_agenda),
|
||||
app.getString(R.string.menu_grades),
|
||||
app.getString(R.string.menu_homework),
|
||||
app.getString(R.string.menu_notices),
|
||||
app.getString(R.string.menu_attendance),
|
||||
app.getString(R.string.title_messages_inbox_single),
|
||||
app.getString(R.string.title_messages_sent_single),
|
||||
app.getString(R.string.menu_announcements)
|
||||
)
|
||||
|
||||
val everything = currentViewId == MainActivity.DRAWER_ITEM_HOME
|
||||
val checkedItems = booleanArrayOf(
|
||||
everything || currentViewId == MainActivity.DRAWER_ITEM_TIMETABLE,
|
||||
everything || currentViewId == MainActivity.DRAWER_ITEM_AGENDA,
|
||||
everything || currentViewId == MainActivity.DRAWER_ITEM_GRADES,
|
||||
everything || currentViewId == MainActivity.DRAWER_ITEM_HOMEWORK,
|
||||
everything || currentViewId == MainActivity.DRAWER_ITEM_BEHAVIOUR,
|
||||
everything || currentViewId == MainActivity.DRAWER_ITEM_ATTENDANCE,
|
||||
everything || currentViewId == MainActivity.DRAWER_ITEM_MESSAGES && MessagesFragment.pageSelection != 1,
|
||||
everything || currentViewId == MainActivity.DRAWER_ITEM_MESSAGES && MessagesFragment.pageSelection == 1,
|
||||
everything || currentViewId == MainActivity.DRAWER_ITEM_ANNOUNCEMENTS
|
||||
)
|
||||
val userChooses = checkedItems.toMutableList()
|
||||
|
||||
dialog = MaterialAlertDialogBuilder(activity)
|
||||
.setTitle(R.string.dialog_sync_view_list_title)
|
||||
.setMultiChoiceItems(items, checkedItems) { _, which, isChecked ->
|
||||
userChooses[which] = isChecked
|
||||
override fun getDefaultSelectedItems(): Set<Any> {
|
||||
val everything = currentViewId == DRAWER_ITEM_HOME
|
||||
return when {
|
||||
everything -> items.values.toSet()
|
||||
currentViewId == DRAWER_ITEM_MESSAGES -> when (MessagesFragment.pageSelection) {
|
||||
1 -> setOf(DRAWER_ITEM_MESSAGES to 1)
|
||||
else -> setOf(DRAWER_ITEM_MESSAGES to 0)
|
||||
}
|
||||
.setPositiveButton(R.string.ok) { _, _ ->
|
||||
dialog.dismiss()
|
||||
|
||||
val selectedViewIds = userChooses.mapIndexed { index, it ->
|
||||
if (it)
|
||||
viewIds[index] to when (index) {
|
||||
7 -> 1
|
||||
else -> 0
|
||||
else -> setOf(currentViewId)
|
||||
}
|
||||
else
|
||||
null
|
||||
}.let {
|
||||
listOfNotNull(*it.toTypedArray())
|
||||
}
|
||||
|
||||
if (selectedViewIds.isNotEmpty()) {
|
||||
override suspend fun onShow() = Unit
|
||||
|
||||
private lateinit var items: Map<CharSequence, Any>
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override suspend fun onPositiveClick(): Boolean {
|
||||
val selected = getMultiSelection().mapNotNull {
|
||||
when (it) {
|
||||
is Int -> it to 0
|
||||
is Pair<*, *> -> it as Pair<Int, Int>
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
if (selected.isEmpty())
|
||||
return DISMISS
|
||||
|
||||
if (activity is MainActivity)
|
||||
activity.swipeRefreshLayout.isRefreshing = true
|
||||
EdziennikTask.syncProfile(
|
||||
App.profileId,
|
||||
selectedViewIds
|
||||
selected
|
||||
).enqueue(activity)
|
||||
return DISMISS
|
||||
}
|
||||
}
|
||||
.setNeutralButton(R.string.sync_feature_all) { _, _ ->
|
||||
dialog.dismiss()
|
||||
|
||||
override suspend fun onNeutralClick(): Boolean {
|
||||
if (activity is MainActivity)
|
||||
activity.swipeRefreshLayout.isRefreshing = true
|
||||
EdziennikTask.syncProfile(App.profileId).enqueue(activity)
|
||||
return DISMISS
|
||||
}
|
||||
.setNegativeButton(R.string.cancel) { _, _ ->
|
||||
dialog.dismiss()
|
||||
}
|
||||
.show()
|
||||
}}
|
||||
}
|
||||
|
@ -4,66 +4,54 @@
|
||||
|
||||
package pl.szczodrzynski.edziennik.ui.dialogs.sync
|
||||
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import pl.szczodrzynski.edziennik.*
|
||||
import pl.szczodrzynski.edziennik.BuildConfig
|
||||
import pl.szczodrzynski.edziennik.R
|
||||
import pl.szczodrzynski.edziennik.data.api.szkolny.response.Update
|
||||
import pl.szczodrzynski.edziennik.ext.Intent
|
||||
import pl.szczodrzynski.edziennik.ext.setMessage
|
||||
import pl.szczodrzynski.edziennik.sync.UpdateDownloaderService
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.base.BaseDialog
|
||||
import pl.szczodrzynski.edziennik.utils.Utils
|
||||
import pl.szczodrzynski.edziennik.utils.html.BetterHtml
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
class UpdateAvailableDialog(
|
||||
val activity: AppCompatActivity,
|
||||
val update: Update,
|
||||
val mandatory: Boolean = update.updateMandatory,
|
||||
val onShowListener: ((tag: String) -> Unit)? = null,
|
||||
val onDismissListener: ((tag: String) -> Unit)? = null
|
||||
) : CoroutineScope {
|
||||
companion object {
|
||||
private const val TAG = "UpdateAvailableDialog"
|
||||
}
|
||||
activity: AppCompatActivity,
|
||||
private val update: Update?,
|
||||
private val mandatory: Boolean = update?.updateMandatory ?: false,
|
||||
onShowListener: ((tag: String) -> Unit)? = null,
|
||||
onDismissListener: ((tag: String) -> Unit)? = null,
|
||||
) : BaseDialog(activity, onShowListener, onDismissListener) {
|
||||
|
||||
private lateinit var app: App
|
||||
private lateinit var dialog: AlertDialog
|
||||
override val TAG = "UpdateAvailableDialog"
|
||||
|
||||
private val job = Job()
|
||||
override val coroutineContext: CoroutineContext
|
||||
get() = job + Dispatchers.Main
|
||||
|
||||
init { run {
|
||||
if (activity.isFinishing)
|
||||
return@run
|
||||
if (update.versionCode <= BuildConfig.VERSION_CODE)
|
||||
return@run
|
||||
onShowListener?.invoke(TAG)
|
||||
app = activity.applicationContext as App
|
||||
|
||||
dialog = MaterialAlertDialogBuilder(activity)
|
||||
.setTitle(R.string.update_available_title)
|
||||
.setMessage(
|
||||
R.string.update_available_format,
|
||||
override fun getTitleRes() = R.string.update_available_title
|
||||
override fun getMessageFormat(): Pair<Int, List<CharSequence>> {
|
||||
if (update != null) {
|
||||
return R.string.update_available_format to listOf(
|
||||
BuildConfig.VERSION_NAME,
|
||||
update.versionName,
|
||||
update.releaseNotes?.let { BetterHtml.fromHtml(activity, it) } ?: "---"
|
||||
update.releaseNotes?.let { BetterHtml.fromHtml(activity, it) } ?: "---",
|
||||
)
|
||||
.setPositiveButton(R.string.update_available_button) { dialog, _ ->
|
||||
}
|
||||
return R.string.update_available_fallback to emptyList()
|
||||
}
|
||||
|
||||
override fun isCancelable() = !mandatory
|
||||
override fun getPositiveButtonText() = R.string.update_available_button
|
||||
override fun getNeutralButtonText() = if (mandatory) null else R.string.update_available_later
|
||||
|
||||
override suspend fun onShow() = Unit
|
||||
|
||||
override suspend fun onPositiveClick(): Boolean {
|
||||
if (update == null)
|
||||
Utils.openGooglePlay(activity)
|
||||
else
|
||||
activity.startService(Intent(app, UpdateDownloaderService::class.java))
|
||||
dialog.dismiss()
|
||||
return NO_DISMISS
|
||||
}
|
||||
.also {
|
||||
if (!mandatory)
|
||||
it.setNeutralButton(R.string.update_available_later, null)
|
||||
|
||||
override suspend fun onBeforeShow(): Boolean {
|
||||
// show only if app is older than available
|
||||
return update == null || update.versionCode > BuildConfig.VERSION_CODE
|
||||
}
|
||||
.setCancelable(!mandatory)
|
||||
.setOnDismissListener {
|
||||
onDismissListener?.invoke(TAG)
|
||||
}
|
||||
.show()
|
||||
}}
|
||||
}
|
||||
|
@ -5,46 +5,32 @@
|
||||
package pl.szczodrzynski.edziennik.ui.error
|
||||
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import kotlinx.coroutines.*
|
||||
import pl.szczodrzynski.edziennik.*
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import pl.szczodrzynski.edziennik.App
|
||||
import pl.szczodrzynski.edziennik.R
|
||||
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
||||
import pl.szczodrzynski.edziennik.data.api.szkolny.SzkolnyApi
|
||||
import pl.szczodrzynski.edziennik.ext.*
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.base.BaseDialog
|
||||
|
||||
class ErrorDetailsDialog(
|
||||
val activity: AppCompatActivity,
|
||||
val errors: List<ApiError>,
|
||||
val titleRes: Int = R.string.dialog_error_details_title,
|
||||
val onShowListener: ((tag: String) -> Unit)? = null,
|
||||
val onDismissListener: ((tag: String) -> Unit)? = null
|
||||
) : CoroutineScope {
|
||||
companion object {
|
||||
private const val TAG = "ApiErrorDialog"
|
||||
}
|
||||
activity: AppCompatActivity,
|
||||
private val errors: List<ApiError>,
|
||||
private val titleRes: Int = R.string.dialog_error_details_title,
|
||||
onShowListener: ((tag: String) -> Unit)? = null,
|
||||
onDismissListener: ((tag: String) -> Unit)? = null,
|
||||
) : BaseDialog(activity, onShowListener, onDismissListener) {
|
||||
|
||||
private lateinit var app: App
|
||||
private lateinit var dialog: AlertDialog
|
||||
override val TAG = "ErrorDetailsDialog"
|
||||
|
||||
private val job = Job()
|
||||
override val coroutineContext: CoroutineContext
|
||||
get() = job + Dispatchers.Main
|
||||
|
||||
private val api by lazy { SzkolnyApi(activity.applicationContext as App) }
|
||||
|
||||
init { run {
|
||||
if (activity.isFinishing)
|
||||
return@run
|
||||
onShowListener?.invoke(TAG)
|
||||
app = activity.applicationContext as App
|
||||
|
||||
if (errors.isNotEmpty()) {
|
||||
val message = errors.map {
|
||||
override fun getTitleRes() = titleRes
|
||||
override fun getMessage() = errors.map {
|
||||
listOf(
|
||||
it.getStringReason(activity).asBoldSpannable().asColoredSpannable(R.attr.colorOnBackground.resolveAttr(activity)),
|
||||
it.getStringReason(activity)
|
||||
.asBoldSpannable()
|
||||
.asColoredSpannable(R.attr.colorOnBackground.resolveAttr(activity)),
|
||||
activity.getString(R.string.error_unknown_format, it.errorCode, it.tag),
|
||||
if (App.devMode)
|
||||
it.throwable?.stackTraceString ?: it.throwable?.localizedMessage
|
||||
@ -53,30 +39,30 @@ class ErrorDetailsDialog(
|
||||
).concat("\n")
|
||||
}.concat("\n\n")
|
||||
|
||||
dialog = MaterialAlertDialogBuilder(activity)
|
||||
.setTitle(titleRes)
|
||||
.setMessage(message)
|
||||
.setPositiveButton(R.string.ok) { _, _ ->
|
||||
dialog.dismiss()
|
||||
override fun isCancelable() = false
|
||||
override fun getPositiveButtonText() = R.string.close
|
||||
override fun getNeutralButtonText() = R.string.report
|
||||
|
||||
override suspend fun onShow() = Unit
|
||||
|
||||
private val api by lazy { SzkolnyApi(activity.applicationContext as App) }
|
||||
|
||||
override suspend fun onBeforeShow(): Boolean {
|
||||
return errors.isNotEmpty()
|
||||
}
|
||||
.setNeutralButton(R.string.report) { _, _ ->
|
||||
launch {
|
||||
|
||||
override suspend fun onNeutralClick(): Boolean {
|
||||
api.runCatching({
|
||||
withContext(Dispatchers.Default) {
|
||||
errorReport(errors.map { it.toReportableError(activity) })
|
||||
}
|
||||
}, {
|
||||
Toast.makeText(activity, activity.getString(R.string.crash_report_cannot_send) + it, Toast.LENGTH_LONG).show()
|
||||
}) ?: return@launch
|
||||
|
||||
dialog.dismiss()
|
||||
Toast.makeText(
|
||||
activity,
|
||||
activity.getString(R.string.crash_report_cannot_send) + it,
|
||||
Toast.LENGTH_LONG
|
||||
).show()
|
||||
})
|
||||
return DISMISS
|
||||
}
|
||||
}
|
||||
.setCancelable(false)
|
||||
.setOnDismissListener {
|
||||
onDismissListener?.invoke(TAG)
|
||||
}
|
||||
.show()
|
||||
}
|
||||
}}
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ class ErrorSnackbar(val activity: AppCompatActivity) : CoroutineScope {
|
||||
this.coordinator = coordinatorLayout
|
||||
snackbar = Snackbar.make(coordinator, R.string.snackbar_error_text, Snackbar.LENGTH_INDEFINITE)
|
||||
snackbar?.setAction(R.string.more) {
|
||||
ErrorDetailsDialog(activity, errors)
|
||||
ErrorDetailsDialog(activity, errors).show()
|
||||
errors = mutableListOf()
|
||||
}
|
||||
val bgColor = ColorUtils.compositeColors(
|
||||
|
@ -8,6 +8,7 @@ import android.content.ActivityNotFoundException
|
||||
import android.content.Intent
|
||||
import android.provider.CalendarContract
|
||||
import android.provider.CalendarContract.Events
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
@ -25,74 +26,63 @@ import pl.szczodrzynski.edziennik.data.api.szkolny.SzkolnyApi
|
||||
import pl.szczodrzynski.edziennik.data.db.full.EventFull
|
||||
import pl.szczodrzynski.edziennik.databinding.DialogEventDetailsBinding
|
||||
import pl.szczodrzynski.edziennik.ext.*
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.base.BindingDialog
|
||||
import pl.szczodrzynski.edziennik.ui.timetable.TimetableFragment
|
||||
import pl.szczodrzynski.edziennik.utils.BetterLink
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
// TODO: 2021-10-19 rewrite to the new dialog style
|
||||
class EventDetailsDialog(
|
||||
val activity: AppCompatActivity,
|
||||
activity: AppCompatActivity,
|
||||
// this event is observed for changes
|
||||
var event: EventFull,
|
||||
val onShowListener: ((tag: String) -> Unit)? = null,
|
||||
val onDismissListener: ((tag: String) -> Unit)? = null
|
||||
) : CoroutineScope {
|
||||
companion object {
|
||||
private const val TAG = "EventDetailsDialog"
|
||||
}
|
||||
private var event: EventFull,
|
||||
onShowListener: ((tag: String) -> Unit)? = null,
|
||||
onDismissListener: ((tag: String) -> Unit)? = null,
|
||||
) : BindingDialog<DialogEventDetailsBinding>(activity, onShowListener, onDismissListener) {
|
||||
|
||||
override val TAG = "EventDetailsDialog"
|
||||
|
||||
override fun getTitleRes(): Int? = null
|
||||
override fun inflate(layoutInflater: LayoutInflater) =
|
||||
DialogEventDetailsBinding.inflate(layoutInflater)
|
||||
|
||||
override fun getPositiveButtonText() = R.string.close
|
||||
override fun getNeutralButtonText() = if (event.addedManually) R.string.remove else null
|
||||
|
||||
private lateinit var app: App
|
||||
private lateinit var b: DialogEventDetailsBinding
|
||||
private lateinit var dialog: AlertDialog
|
||||
private var removeEventDialog: AlertDialog? = null
|
||||
private val eventShared = event.sharedBy != null
|
||||
private val eventOwn = event.sharedBy == "self"
|
||||
private val manager
|
||||
get() = app.eventManager
|
||||
|
||||
private val job = Job()
|
||||
override val coroutineContext: CoroutineContext
|
||||
get() = job + Dispatchers.Main
|
||||
|
||||
private val api by lazy {
|
||||
SzkolnyApi(app)
|
||||
}
|
||||
|
||||
private var progressDialog: AlertDialog? = null
|
||||
|
||||
init { run {
|
||||
if (activity.isFinishing)
|
||||
return@run
|
||||
onShowListener?.invoke(TAG)
|
||||
EventBus.getDefault().register(this)
|
||||
app = activity.applicationContext as App
|
||||
b = DialogEventDetailsBinding.inflate(activity.layoutInflater)
|
||||
dialog = MaterialAlertDialogBuilder(activity)
|
||||
.setView(b.root)
|
||||
.setPositiveButton(R.string.close) { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
}
|
||||
.apply {
|
||||
if (event.addedManually)
|
||||
setNeutralButton(R.string.remove, null)
|
||||
}
|
||||
.setOnDismissListener {
|
||||
onDismissListener?.invoke(TAG)
|
||||
EventBus.getDefault().unregister(this@EventDetailsDialog)
|
||||
progressDialog?.dismiss()
|
||||
}
|
||||
.show()
|
||||
|
||||
dialog.getButton(AlertDialog.BUTTON_NEUTRAL)?.onClick {
|
||||
override suspend fun onNeutralClick(): Boolean {
|
||||
showRemoveEventDialog()
|
||||
return NO_DISMISS
|
||||
}
|
||||
|
||||
override suspend fun onBeforeShow(): Boolean {
|
||||
EventBus.getDefault().register(this)
|
||||
return true
|
||||
}
|
||||
|
||||
override suspend fun onShow() {
|
||||
// watch the event for changes
|
||||
app.db.eventDao().getById(event.profileId, event.id).observe(activity) {
|
||||
event = it ?: return@observe
|
||||
update()
|
||||
}
|
||||
}}
|
||||
}
|
||||
|
||||
override fun onDismiss() {
|
||||
EventBus.getDefault().unregister(this@EventDetailsDialog)
|
||||
progressDialog?.dismiss()
|
||||
}
|
||||
|
||||
private fun update() {
|
||||
b.event = event
|
||||
@ -185,7 +175,7 @@ class EventDetailsDialog(
|
||||
},
|
||||
onShowListener = onShowListener,
|
||||
onDismissListener = onDismissListener
|
||||
)
|
||||
).show()
|
||||
}
|
||||
b.editButton.attachToastHint(R.string.hint_edit_event)
|
||||
|
||||
|
@ -4,10 +4,10 @@
|
||||
|
||||
package pl.szczodrzynski.edziennik.ui.event
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.app.AlertDialog.BUTTON_NEUTRAL
|
||||
import androidx.appcompat.app.AlertDialog.BUTTON_POSITIVE
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
@ -32,6 +32,7 @@ import pl.szczodrzynski.edziennik.data.db.full.LessonFull
|
||||
import pl.szczodrzynski.edziennik.databinding.DialogEventManualV2Binding
|
||||
import pl.szczodrzynski.edziennik.ext.*
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.StyledTextDialog
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.base.BindingDialog
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.settings.RegistrationConfigDialog
|
||||
import pl.szczodrzynski.edziennik.ui.views.TimeDropdown.Companion.DISPLAY_LESSONS
|
||||
import pl.szczodrzynski.edziennik.utils.Anim
|
||||
@ -40,32 +41,32 @@ import pl.szczodrzynski.edziennik.utils.managers.TextStylingManager.HtmlMode.SIM
|
||||
import pl.szczodrzynski.edziennik.utils.managers.TextStylingManager.StylingConfigBase
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
import pl.szczodrzynski.edziennik.utils.models.Time
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
// TODO: 2021-10-19 rewrite to the new dialog style
|
||||
class EventManualDialog(
|
||||
val activity: AppCompatActivity,
|
||||
val profileId: Int,
|
||||
val defaultLesson: LessonFull? = null,
|
||||
val defaultDate: Date? = null,
|
||||
val defaultTime: Time? = null,
|
||||
val defaultType: Long? = null,
|
||||
val editingEvent: EventFull? = null,
|
||||
val onSaveListener: ((event: EventFull?) -> Unit)? = null,
|
||||
val onShowListener: ((tag: String) -> Unit)? = null,
|
||||
val onDismissListener: ((tag: String) -> Unit)? = null
|
||||
) : CoroutineScope {
|
||||
activity: AppCompatActivity,
|
||||
private val profileId: Int,
|
||||
private val defaultLesson: LessonFull? = null,
|
||||
private val defaultDate: Date? = null,
|
||||
private val defaultTime: Time? = null,
|
||||
private val defaultType: Long? = null,
|
||||
private val editingEvent: EventFull? = null,
|
||||
private val onSaveListener: ((event: EventFull?) -> Unit)? = null,
|
||||
onShowListener: ((tag: String) -> Unit)? = null,
|
||||
onDismissListener: ((tag: String) -> Unit)? = null,
|
||||
) : BindingDialog<DialogEventManualV2Binding>(activity, onShowListener, onDismissListener) {
|
||||
|
||||
companion object {
|
||||
private const val TAG = "EventManualDialog"
|
||||
}
|
||||
override val TAG = "EventManualDialog"
|
||||
|
||||
private val job: Job = Job()
|
||||
override val coroutineContext: CoroutineContext
|
||||
get() = job + Dispatchers.Main
|
||||
override fun getTitleRes() = R.string.dialog_event_manual_title
|
||||
override fun inflate(layoutInflater: LayoutInflater) =
|
||||
DialogEventManualV2Binding.inflate(layoutInflater)
|
||||
|
||||
override fun isCancelable() = false
|
||||
override fun getPositiveButtonText() = R.string.save
|
||||
override fun getNeutralButtonText() = if (editingEvent != null) R.string.remove else null
|
||||
override fun getNegativeButtonText() = R.string.cancel
|
||||
|
||||
private val app by lazy { activity.application as App }
|
||||
private lateinit var b: DialogEventManualV2Binding
|
||||
private lateinit var dialog: AlertDialog
|
||||
private lateinit var profile: Profile
|
||||
private lateinit var stylingConfig: StylingConfigBase
|
||||
|
||||
@ -86,46 +87,28 @@ class EventManualDialog(
|
||||
|
||||
private var progressDialog: AlertDialog? = null
|
||||
|
||||
init { launch {
|
||||
if (activity.isFinishing)
|
||||
return@launch
|
||||
onShowListener?.invoke(TAG)
|
||||
override suspend fun onPositiveClick(): Boolean {
|
||||
saveEvent()
|
||||
return NO_DISMISS
|
||||
}
|
||||
|
||||
override suspend fun onNeutralClick(): Boolean {
|
||||
showRemoveEventDialog()
|
||||
return NO_DISMISS
|
||||
}
|
||||
|
||||
override suspend fun onBeforeShow(): Boolean {
|
||||
EventBus.getDefault().register(this@EventManualDialog)
|
||||
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, null)
|
||||
.apply {
|
||||
if (editingEvent != null) {
|
||||
setNeutralButton(R.string.remove, null)
|
||||
return true
|
||||
}
|
||||
}
|
||||
.setOnDismissListener {
|
||||
onDismissListener?.invoke(TAG)
|
||||
|
||||
override fun onDismiss() {
|
||||
EventBus.getDefault().unregister(this@EventManualDialog)
|
||||
enqueuedWeekDialog?.dismiss()
|
||||
progressDialog?.dismiss()
|
||||
}
|
||||
.setCancelable(false)
|
||||
.create()
|
||||
.apply {
|
||||
setOnShowListener { dialog ->
|
||||
val positiveButton = (dialog as AlertDialog).getButton(BUTTON_POSITIVE)
|
||||
positiveButton?.setOnClickListener {
|
||||
saveEvent()
|
||||
}
|
||||
|
||||
val neutralButton = dialog.getButton(BUTTON_NEUTRAL)
|
||||
neutralButton?.setOnClickListener {
|
||||
showRemoveEventDialog()
|
||||
}
|
||||
}
|
||||
|
||||
show()
|
||||
}
|
||||
|
||||
override suspend fun onShow() {
|
||||
b.shareSwitch.isChecked = editingShared
|
||||
b.shareSwitch.isEnabled = !editingShared || (editingShared && editingOwn)
|
||||
|
||||
@ -152,7 +135,7 @@ class EventManualDialog(
|
||||
},
|
||||
onShowListener,
|
||||
onDismissListener
|
||||
)
|
||||
).show()
|
||||
}
|
||||
|
||||
stylingConfig = StylingConfigBase(editText = b.topic, htmlMode = SIMPLE)
|
||||
@ -163,7 +146,7 @@ class EventManualDialog(
|
||||
}
|
||||
|
||||
loadLists()
|
||||
}}
|
||||
}
|
||||
|
||||
private fun updateShareText(checked: Boolean = b.shareSwitch.isChecked) {
|
||||
b.shareDetails.visibility = if (checked || editingShared)
|
||||
@ -259,13 +242,13 @@ class EventManualDialog(
|
||||
progressDialog?.dismiss()
|
||||
}
|
||||
|
||||
private fun loadLists() = launch {
|
||||
private suspend fun loadLists() {
|
||||
val profile = withContext(Dispatchers.Default) {
|
||||
app.db.profileDao().getByIdNow(profileId)
|
||||
}
|
||||
if (profile == null) {
|
||||
Toast.makeText(activity, R.string.event_manual_no_profile, Toast.LENGTH_SHORT).show()
|
||||
return@launch
|
||||
return
|
||||
}
|
||||
this@EventManualDialog.profile = profile
|
||||
|
||||
@ -611,7 +594,7 @@ class EventManualDialog(
|
||||
it.teamName = b.teamDropdown.getSelected()?.name
|
||||
it.typeName = b.typeDropdown.getSelected()?.name
|
||||
})
|
||||
dialog.dismiss()
|
||||
dismiss()
|
||||
Toast.makeText(activity, R.string.saved, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
private fun finishRemoving() {
|
||||
@ -624,7 +607,7 @@ class EventManualDialog(
|
||||
|
||||
removeEventDialog?.dismiss()
|
||||
onSaveListener?.invoke(null)
|
||||
dialog.dismiss()
|
||||
dismiss()
|
||||
Toast.makeText(activity, R.string.removed, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
@ -1,56 +1,39 @@
|
||||
package pl.szczodrzynski.edziennik.ui.grades
|
||||
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import android.view.LayoutInflater
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.graphics.ColorUtils
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import pl.szczodrzynski.edziennik.App
|
||||
import pl.szczodrzynski.edziennik.R
|
||||
import pl.szczodrzynski.edziennik.data.db.full.GradeFull
|
||||
import pl.szczodrzynski.edziennik.databinding.DialogGradeDetailsBinding
|
||||
import pl.szczodrzynski.edziennik.ext.onClick
|
||||
import pl.szczodrzynski.edziennik.ext.setTintColor
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.base.BindingDialog
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.settings.GradesConfigDialog
|
||||
import pl.szczodrzynski.edziennik.utils.BetterLink
|
||||
import pl.szczodrzynski.edziennik.utils.SimpleDividerItemDecoration
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
class GradeDetailsDialog(
|
||||
val activity: AppCompatActivity,
|
||||
val grade: GradeFull,
|
||||
val onShowListener: ((tag: String) -> Unit)? = null,
|
||||
val onDismissListener: ((tag: String) -> Unit)? = null
|
||||
) : CoroutineScope {
|
||||
companion object {
|
||||
private const val TAG = "GradeDetailsDialog"
|
||||
}
|
||||
activity: AppCompatActivity,
|
||||
private val grade: GradeFull,
|
||||
onShowListener: ((tag: String) -> Unit)? = null,
|
||||
onDismissListener: ((tag: String) -> Unit)? = null,
|
||||
) : BindingDialog<DialogGradeDetailsBinding>(activity, onShowListener, onDismissListener) {
|
||||
|
||||
private lateinit var app: App
|
||||
private lateinit var b: DialogGradeDetailsBinding
|
||||
private lateinit var dialog: AlertDialog
|
||||
override val TAG = "GradeDetailsDialog"
|
||||
|
||||
private val job = Job()
|
||||
override val coroutineContext: CoroutineContext
|
||||
get() = job + Dispatchers.Main
|
||||
override fun getTitleRes(): Int? = null
|
||||
override fun inflate(layoutInflater: LayoutInflater) =
|
||||
DialogGradeDetailsBinding.inflate(layoutInflater)
|
||||
|
||||
// local variables go here
|
||||
override fun getPositiveButtonText() = R.string.close
|
||||
|
||||
init { run {
|
||||
if (activity.isFinishing)
|
||||
return@run
|
||||
onShowListener?.invoke(TAG)
|
||||
app = activity.applicationContext as App
|
||||
b = DialogGradeDetailsBinding.inflate(activity.layoutInflater)
|
||||
dialog = MaterialAlertDialogBuilder(activity)
|
||||
.setView(b.root)
|
||||
.setPositiveButton(R.string.close, null)
|
||||
.setOnDismissListener {
|
||||
onDismissListener?.invoke(TAG)
|
||||
}
|
||||
.show()
|
||||
override suspend fun onShow() {
|
||||
val manager = app.gradesManager
|
||||
|
||||
val gradeColor = manager.getGradeColor(grade)
|
||||
@ -58,15 +41,23 @@ class GradeDetailsDialog(
|
||||
b.weightText = manager.getWeightString(app, grade)
|
||||
b.commentVisible = false
|
||||
b.devMode = App.devMode
|
||||
b.gradeName.setTextColor(if (ColorUtils.calculateLuminance(gradeColor) > 0.3) 0xaa000000.toInt() else 0xccffffff.toInt())
|
||||
b.gradeName.setTextColor(
|
||||
if (ColorUtils.calculateLuminance(gradeColor) > 0.3)
|
||||
0xaa000000.toInt()
|
||||
else
|
||||
0xccffffff.toInt()
|
||||
)
|
||||
b.gradeName.background.setTintColor(gradeColor)
|
||||
|
||||
b.gradeValue = if (grade.weight == 0f || grade.value < 0f) -1f else manager.getGradeValue(grade)
|
||||
b.gradeValue = if (grade.weight == 0f || grade.value < 0f)
|
||||
-1f
|
||||
else
|
||||
manager.getGradeValue(grade)
|
||||
|
||||
b.customValueDivider.isVisible = manager.plusValue != null || manager.minusValue != null
|
||||
b.customValueLayout.isVisible = b.customValueDivider.isVisible
|
||||
b.customValueButton.onClick {
|
||||
GradesConfigDialog(activity, reloadOnDismiss = true)
|
||||
GradesConfigDialog(activity, reloadOnDismiss = true).show()
|
||||
}
|
||||
|
||||
grade.teacherName?.let { name ->
|
||||
@ -77,24 +68,26 @@ class GradeDetailsDialog(
|
||||
)
|
||||
}
|
||||
|
||||
launch {
|
||||
val historyList = withContext(Dispatchers.Default) {
|
||||
app.db.gradeDao().getByParentIdNow(App.profileId, grade.id)
|
||||
}
|
||||
if (historyList.isEmpty()) {
|
||||
b.historyVisible = false
|
||||
return@launch
|
||||
return
|
||||
}
|
||||
b.historyVisible = true
|
||||
//b.gradeHistoryNest.isNestedScrollingEnabled = false
|
||||
|
||||
b.gradeHistoryList.adapter = GradesAdapter(activity, {
|
||||
GradeDetailsDialog(activity, it)
|
||||
}).also { it.items = historyList.toMutableList() }
|
||||
GradeDetailsDialog(activity, it).show()
|
||||
}).also {
|
||||
it.items = historyList.toMutableList()
|
||||
}
|
||||
|
||||
b.gradeHistoryList.apply {
|
||||
setHasFixedSize(true)
|
||||
layoutManager = LinearLayoutManager(context)
|
||||
addItemDecoration(SimpleDividerItemDecoration(context))
|
||||
}
|
||||
}
|
||||
}}
|
||||
}
|
||||
|
@ -110,7 +110,7 @@ class GradesListFragment : Fragment(), CoroutineScope {
|
||||
}})
|
||||
|
||||
adapter.onGradeClick = {
|
||||
GradeDetailsDialog(activity, it)
|
||||
GradeDetailsDialog(activity, it).show()
|
||||
}
|
||||
|
||||
adapter.onGradesEditorClick = { subject, semester ->
|
||||
@ -140,7 +140,7 @@ class GradesListFragment : Fragment(), CoroutineScope {
|
||||
.withIcon(CommunityMaterial.Icon.cmd_cog_outline)
|
||||
.withOnClickListener(View.OnClickListener {
|
||||
activity.bottomSheet.close()
|
||||
GradesConfigDialog(activity, true, null, null)
|
||||
GradesConfigDialog(activity, true, null, null).show()
|
||||
}),
|
||||
BottomSheetSeparatorItem(true),
|
||||
BottomSheetPrimaryItem(true)
|
||||
|
@ -105,7 +105,7 @@ class StatsViewHolder(
|
||||
b.customValueDivider.isVisible = manager.dontCountEnabled || manager.plusValue != null || manager.minusValue != null
|
||||
b.customValueLayout.isVisible = b.customValueDivider.isVisible
|
||||
b.customValueButton.onClick {
|
||||
GradesConfigDialog(activity, reloadOnDismiss = true)
|
||||
GradesConfigDialog(activity, reloadOnDismiss = true).show()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -70,7 +70,7 @@ class CounterActivity : AppCompatActivity(), CoroutineScope {
|
||||
}
|
||||
)
|
||||
b.bellSync.onClick {
|
||||
BellSyncTimeChooseDialog(activity = this@CounterActivity)
|
||||
BellSyncTimeChooseDialog(activity = this@CounterActivity).show()
|
||||
}
|
||||
|
||||
app.config.timetable.bellSyncDiff?.let {
|
||||
|
@ -4,77 +4,66 @@
|
||||
|
||||
package pl.szczodrzynski.edziennik.ui.home
|
||||
|
||||
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.MainActivity
|
||||
import pl.szczodrzynski.edziennik.R
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.base.BaseDialog
|
||||
import pl.szczodrzynski.edziennik.ui.home.HomeCard.Companion.CARD_EVENTS
|
||||
import pl.szczodrzynski.edziennik.ui.home.HomeCard.Companion.CARD_GRADES
|
||||
import pl.szczodrzynski.edziennik.ui.home.HomeCard.Companion.CARD_LUCKY_NUMBER
|
||||
import pl.szczodrzynski.edziennik.ui.home.HomeCard.Companion.CARD_TIMETABLE
|
||||
import kotlin.collections.set
|
||||
|
||||
class HomeConfigDialog(
|
||||
val activity: AppCompatActivity,
|
||||
activity: AppCompatActivity,
|
||||
private val reloadOnDismiss: Boolean = true,
|
||||
val onShowListener: ((tag: String) -> Unit)? = null,
|
||||
val onDismissListener: ((tag: String) -> Unit)? = null
|
||||
) {
|
||||
companion object {
|
||||
const val TAG = "HomeConfigDialog"
|
||||
}
|
||||
onShowListener: ((tag: String) -> Unit)? = null,
|
||||
onDismissListener: ((tag: String) -> Unit)? = null,
|
||||
) : BaseDialog(activity, onShowListener, onDismissListener) {
|
||||
|
||||
override val TAG = "HomeConfigDialog"
|
||||
|
||||
override fun getTitleRes() = R.string.home_configure_add_remove
|
||||
override fun getPositiveButtonText() = R.string.ok
|
||||
override fun getNegativeButtonText() = R.string.cancel
|
||||
|
||||
override fun getMultiChoiceItems(): Map<CharSequence, Any> = mapOf(
|
||||
R.string.card_type_lucky_number to CARD_LUCKY_NUMBER,
|
||||
R.string.card_type_timetable to CARD_TIMETABLE,
|
||||
R.string.card_type_grades to CARD_GRADES,
|
||||
R.string.card_type_events to CARD_EVENTS,
|
||||
).mapKeys { (resId, _) -> activity.getString(resId) }
|
||||
|
||||
override fun getDefaultSelectedItems() =
|
||||
profileConfig.homeCards
|
||||
.filter { it.profileId == App.profileId }
|
||||
.map { it.cardId }
|
||||
.toSet()
|
||||
|
||||
override suspend fun onShow() = Unit
|
||||
|
||||
private val app by lazy { activity.application as App }
|
||||
private val profileConfig by lazy { app.config.getFor(app.profileId).ui }
|
||||
private var configChanged = false
|
||||
|
||||
private lateinit var dialog: AlertDialog
|
||||
|
||||
init { run {
|
||||
if (activity.isFinishing)
|
||||
return@run
|
||||
onShowListener?.invoke(TAG)
|
||||
|
||||
val ids = listOf(
|
||||
CARD_LUCKY_NUMBER,
|
||||
CARD_TIMETABLE,
|
||||
CARD_GRADES,
|
||||
CARD_EVENTS
|
||||
override suspend fun onPositiveClick(): Boolean {
|
||||
val homeCards = profileConfig.homeCards.toMutableList()
|
||||
homeCards.removeAll { it.profileId == App.profileId }
|
||||
homeCards += getMultiSelection().mapNotNull {
|
||||
HomeCardModel(
|
||||
profileId = App.profileId,
|
||||
cardId = it as? Int ?: return@mapNotNull null
|
||||
)
|
||||
val items = listOf(
|
||||
app.getString(R.string.card_type_lucky_number),
|
||||
app.getString(R.string.card_type_timetable),
|
||||
app.getString(R.string.card_type_grades),
|
||||
app.getString(R.string.card_type_events)
|
||||
)
|
||||
val checkedItems = ids.map { it to false }.toMap().toMutableMap()
|
||||
|
||||
val profileId = App.profileId
|
||||
val homeCards = profileConfig.homeCards
|
||||
.filter { it.profileId == profileId }
|
||||
.toMutableList()
|
||||
|
||||
homeCards.forEach {
|
||||
checkedItems[it.cardId] = true
|
||||
}
|
||||
|
||||
dialog = MaterialAlertDialogBuilder(activity)
|
||||
.setTitle(R.string.home_configure_add_remove)
|
||||
.setMultiChoiceItems(items.toTypedArray(), checkedItems.values.toBooleanArray()) { _, which, isChecked ->
|
||||
if (isChecked) {
|
||||
homeCards += HomeCardModel(profileId, ids[which])
|
||||
}
|
||||
else {
|
||||
homeCards.removeAll { it.profileId == profileId && it.cardId == ids[which] }
|
||||
}
|
||||
}
|
||||
.setPositiveButton(R.string.ok) { dialog, _ -> dialog.dismiss() }
|
||||
.setOnDismissListener {
|
||||
profileConfig.homeCards = homeCards
|
||||
onDismissListener?.invoke(TAG)
|
||||
if (reloadOnDismiss) (activity as? MainActivity)?.reloadTarget()
|
||||
return DISMISS
|
||||
}
|
||||
|
||||
override suspend fun onMultiSelectionChanged(items: Set<Any>) {
|
||||
configChanged = true
|
||||
}
|
||||
|
||||
override fun onDismiss() {
|
||||
if (configChanged && reloadOnDismiss && activity is MainActivity)
|
||||
activity.reloadTarget()
|
||||
}
|
||||
.show()
|
||||
}}
|
||||
}
|
||||
|
@ -102,7 +102,7 @@ class HomeFragment : Fragment(), CoroutineScope {
|
||||
.withIcon(Icon.cmd_card_bulleted_settings_outline)
|
||||
.withOnClickListener(OnClickListener {
|
||||
activity.bottomSheet.close()
|
||||
HomeConfigDialog(activity, reloadOnDismiss = true)
|
||||
HomeConfigDialog(activity, reloadOnDismiss = true).show()
|
||||
}),
|
||||
BottomSheetPrimaryItem(true)
|
||||
.withTitle(R.string.menu_set_student_number)
|
||||
@ -131,7 +131,7 @@ class HomeFragment : Fragment(), CoroutineScope {
|
||||
})
|
||||
)
|
||||
b.configureCards.onClick {
|
||||
HomeConfigDialog(activity, reloadOnDismiss = true)
|
||||
HomeConfigDialog(activity, reloadOnDismiss = true).show()
|
||||
}
|
||||
|
||||
b.scrollView.setOnScrollChangeListener { _: NestedScrollView?, _: Int, scrollY: Int, _: Int, _: Int ->
|
||||
|
@ -72,7 +72,7 @@ class HomeAvailabilityCard(
|
||||
if (status.userMessage.icon != null)
|
||||
b.homeAvailabilityIcon.load(status.userMessage.icon)
|
||||
onInfoClick = {
|
||||
RegisterUnavailableDialog(activity, status)
|
||||
RegisterUnavailableDialog(activity, status).show()
|
||||
}
|
||||
}
|
||||
// show "update available" when available OR version too old for the register
|
||||
@ -82,7 +82,7 @@ class HomeAvailabilityCard(
|
||||
b.homeAvailabilityUpdate.isVisible = true
|
||||
b.homeAvailabilityIcon.setImageResource(R.drawable.ic_update)
|
||||
onInfoClick = {
|
||||
UpdateAvailableDialog(activity, update)
|
||||
UpdateAvailableDialog(activity, update).show()
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -87,7 +87,7 @@ class HomeDebugCard(
|
||||
|
||||
b.librusCaptchaButton.onClick {
|
||||
//app.startActivity(Intent(activity, LoginLibrusCaptchaActivity::class.java))
|
||||
LibrusCaptchaDialog(activity, onSuccess = {}, onFailure = {})
|
||||
LibrusCaptchaDialog(activity, onSuccess = {}, onFailure = {}).show()
|
||||
}
|
||||
|
||||
b.getLogs.onClick {
|
||||
|
@ -70,14 +70,14 @@ class HomeEventsCard(
|
||||
EventDetailsDialog(
|
||||
activity,
|
||||
it
|
||||
)
|
||||
).show()
|
||||
},
|
||||
onEventEditClick = {
|
||||
EventManualDialog(
|
||||
activity,
|
||||
it.profileId,
|
||||
editingEvent = it
|
||||
)
|
||||
).show()
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -112,7 +112,7 @@ class HomeTimetableCard(
|
||||
b.bellSync.setOnClickListener {
|
||||
BellSyncTimeChooseDialog(
|
||||
activity
|
||||
)
|
||||
).show()
|
||||
}
|
||||
|
||||
b.showCounter.setOnClickListener {
|
||||
|
@ -65,7 +65,7 @@ class HomeworkFragment : Fragment(), CoroutineScope {
|
||||
.withIcon(SzkolnyFont.Icon.szf_calendar_plus_outline)
|
||||
.withOnClickListener(View.OnClickListener {
|
||||
activity.bottomSheet.close()
|
||||
EventManualDialog(activity, App.profileId, defaultType = Event.TYPE_HOMEWORK)
|
||||
EventManualDialog(activity, App.profileId, defaultType = Event.TYPE_HOMEWORK).show()
|
||||
}),
|
||||
BottomSheetSeparatorItem(true),
|
||||
BottomSheetPrimaryItem(true)
|
||||
@ -108,7 +108,7 @@ class HomeworkFragment : Fragment(), CoroutineScope {
|
||||
}
|
||||
|
||||
setFabOnClickListener(View.OnClickListener {
|
||||
EventManualDialog(activity, App.profileId, defaultType = Event.TYPE_HOMEWORK)
|
||||
EventManualDialog(activity, App.profileId, defaultType = Event.TYPE_HOMEWORK).show()
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -68,14 +68,14 @@ class HomeworkListFragment : LazyFragment(), CoroutineScope {
|
||||
EventDetailsDialog(
|
||||
activity,
|
||||
it
|
||||
)
|
||||
).show()
|
||||
},
|
||||
onEventEditClick = {
|
||||
EventManualDialog(
|
||||
activity,
|
||||
it.profileId,
|
||||
editingEvent = it
|
||||
)
|
||||
).show()
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -275,7 +275,7 @@ class LoginChooserFragment : Fragment(), CoroutineScope {
|
||||
|
||||
return when (error.type) {
|
||||
Type.NOT_AVAILABLE -> {
|
||||
RegisterUnavailableDialog(activity, error.status!!)
|
||||
RegisterUnavailableDialog(activity, error.status!!).show()
|
||||
false
|
||||
}
|
||||
Type.API_ERROR -> {
|
||||
|
@ -141,7 +141,7 @@ class MessagesComposeFragment : Fragment(), CoroutineScope {
|
||||
.withIcon(CommunityMaterial.Icon.cmd_cog_outline)
|
||||
.withOnClickListener {
|
||||
activity.bottomSheet.close()
|
||||
MessagesConfigDialog(activity, false, null, null)
|
||||
MessagesConfigDialog(activity, false, null, null).show()
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -118,7 +118,7 @@ class MessagesFragment : Fragment(), CoroutineScope {
|
||||
.withIcon(CommunityMaterial.Icon.cmd_cog_outline)
|
||||
.withOnClickListener {
|
||||
activity.bottomSheet.close()
|
||||
MessagesConfigDialog(activity, false, null, null)
|
||||
MessagesConfigDialog(activity, false, null, null).show()
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -74,7 +74,7 @@ class MessageFragment : Fragment(), CoroutineScope {
|
||||
.withIcon(CommunityMaterial.Icon.cmd_cog_outline)
|
||||
.withOnClickListener {
|
||||
activity.bottomSheet.close()
|
||||
MessagesConfigDialog(activity, false, null, null)
|
||||
MessagesConfigDialog(activity, false, null, null).show()
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -104,7 +104,7 @@ class SettingsAboutCard(util: SettingsUtil) : SettingsCard(util), CoroutineScope
|
||||
text = R.string.settings_about_changelog_text,
|
||||
icon = CommunityMaterial.Icon3.cmd_radar
|
||||
) {
|
||||
ChangelogDialog(activity)
|
||||
ChangelogDialog(activity).show()
|
||||
},
|
||||
|
||||
util.createActionItem(
|
||||
|
@ -31,7 +31,7 @@ class SettingsProfileCard(util: SettingsUtil) : SettingsCard(util) {
|
||||
card.items.remove(item)
|
||||
card.items.add(index, getProfileItem())
|
||||
util.refresh()
|
||||
})
|
||||
}).show()
|
||||
}
|
||||
|
||||
override fun getItems() = listOf(
|
||||
|
@ -59,28 +59,28 @@ class SettingsRegisterCard(util: SettingsUtil) : SettingsCard(util) {
|
||||
text = R.string.menu_agenda_config,
|
||||
icon = CommunityMaterial.Icon.cmd_calendar_outline
|
||||
) {
|
||||
AgendaConfigDialog(activity, reloadOnDismiss = false)
|
||||
AgendaConfigDialog(activity, reloadOnDismiss = false).show()
|
||||
},
|
||||
|
||||
util.createActionItem(
|
||||
text = R.string.menu_grades_config,
|
||||
icon = CommunityMaterial.Icon3.cmd_numeric_5_box_outline
|
||||
) {
|
||||
GradesConfigDialog(activity, reloadOnDismiss = false)
|
||||
GradesConfigDialog(activity, reloadOnDismiss = false).show()
|
||||
},
|
||||
|
||||
util.createActionItem(
|
||||
text = R.string.menu_messages_config,
|
||||
icon = CommunityMaterial.Icon.cmd_calendar_outline
|
||||
) {
|
||||
MessagesConfigDialog(activity, reloadOnDismiss = false)
|
||||
MessagesConfigDialog(activity, reloadOnDismiss = false).show()
|
||||
},
|
||||
|
||||
util.createActionItem(
|
||||
text = R.string.menu_attendance_config,
|
||||
icon = CommunityMaterial.Icon.cmd_calendar_remove_outline
|
||||
) {
|
||||
AttendanceConfigDialog(activity, reloadOnDismiss = false)
|
||||
AttendanceConfigDialog(activity, reloadOnDismiss = false).show()
|
||||
},
|
||||
|
||||
util.createPropertyItem(
|
||||
@ -126,7 +126,7 @@ class SettingsRegisterCard(util: SettingsUtil) : SettingsCard(util) {
|
||||
BellSyncConfigDialog(activity, onChangeListener = {
|
||||
it.subText = getBellSync()
|
||||
util.refresh()
|
||||
})
|
||||
}).show()
|
||||
}
|
||||
).also {
|
||||
it.subText = getBellSync()
|
||||
|
@ -108,7 +108,7 @@ class SettingsSyncCard(util: SettingsUtil) : SettingsCard(util) {
|
||||
item.onCheckedChangedAction.onCheckedChanged(item, true)
|
||||
if (configGlobal.sync.enabled)
|
||||
util.refresh()
|
||||
})
|
||||
}).show()
|
||||
}
|
||||
).also {
|
||||
it.subTextChecked = activity.getSyncInterval(configGlobal.sync.interval)
|
||||
@ -124,7 +124,7 @@ class SettingsSyncCard(util: SettingsUtil) : SettingsCard(util) {
|
||||
subText = R.string.settings_profile_notifications_subtext,
|
||||
icon = CommunityMaterial.Icon2.cmd_filter_outline
|
||||
) {
|
||||
NotificationFilterDialog(activity)
|
||||
NotificationFilterDialog(activity).show()
|
||||
},
|
||||
|
||||
util.createPropertyActionItem(
|
||||
|
@ -54,7 +54,7 @@ class SettingsThemeCard(util: SettingsUtil) : SettingsCard(util) {
|
||||
subText = Themes.getThemeNameRes(),
|
||||
icon = CommunityMaterial.Icon3.cmd_palette_outline
|
||||
) {
|
||||
ThemeChooserDialog(activity)
|
||||
ThemeChooserDialog(activity).show()
|
||||
},
|
||||
|
||||
util.createActionItem(
|
||||
@ -62,7 +62,7 @@ class SettingsThemeCard(util: SettingsUtil) : SettingsCard(util) {
|
||||
subText = R.string.settings_about_language_subtext,
|
||||
icon = CommunityMaterial.Icon3.cmd_translate
|
||||
) {
|
||||
AppLanguageDialog(activity)
|
||||
AppLanguageDialog(activity).show()
|
||||
},
|
||||
|
||||
util.createPropertyItem(
|
||||
@ -81,7 +81,7 @@ class SettingsThemeCard(util: SettingsUtil) : SettingsCard(util) {
|
||||
text = R.string.settings_theme_mini_drawer_buttons_text,
|
||||
icon = CommunityMaterial.Icon2.cmd_format_list_checks
|
||||
) {
|
||||
MiniMenuConfigDialog(activity)
|
||||
MiniMenuConfigDialog(activity).show()
|
||||
},
|
||||
|
||||
util.createActionItem(
|
||||
|
@ -4,63 +4,77 @@
|
||||
|
||||
package pl.szczodrzynski.edziennik.ui.template
|
||||
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import android.view.LayoutInflater
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import pl.szczodrzynski.edziennik.App
|
||||
import pl.szczodrzynski.edziennik.R
|
||||
import pl.szczodrzynski.edziennik.databinding.DialogTemplateBinding
|
||||
import pl.szczodrzynski.edziennik.ext.onClick
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.base.BaseDialog
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.base.BindingDialog
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.base.ViewDialog
|
||||
|
||||
/**
|
||||
* This class represents a sample dialog using the new style.
|
||||
*
|
||||
* A dialog may subclass the [BaseDialog], [ViewDialog] or [BindingDialog].
|
||||
*
|
||||
* Fields and methods have the preferred order which should be used when writing new code.
|
||||
* The position of the first occurrence of duplicated methods should be used.
|
||||
* Multi-line methods should be followed by a blank line, one-liners may be just joined together.
|
||||
*
|
||||
* Constructor properties should be private.
|
||||
*
|
||||
* [onShow], when not used, should be placed just before the local variables, as a one-liner.
|
||||
* All other multi-line methods go below the local variables part.
|
||||
*/
|
||||
class TemplateDialog(
|
||||
val activity: AppCompatActivity,
|
||||
val onActionPerformed: (() -> Unit)? = null,
|
||||
val onShowListener: ((tag: String) -> Unit)? = null,
|
||||
val onDismissListener: ((tag: String) -> Unit)? = null
|
||||
) : CoroutineScope {
|
||||
companion object {
|
||||
private const val TAG = "TemplateDialog"
|
||||
}
|
||||
activity: AppCompatActivity,
|
||||
private val onActionPerformed: (() -> Unit)? = null,
|
||||
onShowListener: ((tag: String) -> Unit)? = null,
|
||||
onDismissListener: ((tag: String) -> Unit)? = null,
|
||||
) : BindingDialog<DialogTemplateBinding>(activity, onShowListener, onDismissListener) {
|
||||
|
||||
private lateinit var app: App
|
||||
private lateinit var b: DialogTemplateBinding
|
||||
private lateinit var dialog: AlertDialog
|
||||
override val TAG = "TemplateDialog"
|
||||
|
||||
private val job = Job()
|
||||
override val coroutineContext: CoroutineContext
|
||||
get() = job + Dispatchers.Main
|
||||
override fun getTitle(): CharSequence = "Template"
|
||||
override fun getTitleRes() = R.string.menu_template
|
||||
override fun inflate(layoutInflater: LayoutInflater) =
|
||||
DialogTemplateBinding.inflate(layoutInflater)
|
||||
|
||||
// override fun getTitle(): CharSequence = "Template"
|
||||
// override fun getTitleRes() = R.string.menu_template
|
||||
// override fun getMessage() = ""
|
||||
// override fun getMessageRes() = R.string.edziennik_progress_login_template_api
|
||||
// override fun getMessageFormat() =
|
||||
// R.string.card_update_text_format to listOf(
|
||||
// BuildConfig.VERSION_BASE,
|
||||
// "5.0",
|
||||
// )
|
||||
|
||||
// override fun getTitleRes() = R.string.menu_template
|
||||
override fun isCancelable() = true
|
||||
override fun getPositiveButtonText() = R.string.ok
|
||||
override fun getNeutralButtonText() = R.string.reset
|
||||
override fun getNegativeButtonText() = R.string.cancel
|
||||
|
||||
// getSingleChoiceItem / getMultiChoiceItems
|
||||
// getDefaultSelectedItem / getDefaultSelectedItems
|
||||
|
||||
// to convert a map of StringIDs to CharSequences
|
||||
// .mapKeys { (resId, _) -> activity.getString(resId) }
|
||||
|
||||
override suspend fun onShow() = Unit
|
||||
|
||||
// local variables go here
|
||||
|
||||
init { run {
|
||||
if (activity.isFinishing)
|
||||
return@run
|
||||
onShowListener?.invoke(TAG)
|
||||
app = activity.applicationContext as App
|
||||
b = DialogTemplateBinding.inflate(activity.layoutInflater)
|
||||
dialog = MaterialAlertDialogBuilder(activity)
|
||||
.setView(b.root)
|
||||
.setPositiveButton(R.string.close) { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
}
|
||||
.setNeutralButton(R.string.add, null)
|
||||
.setOnDismissListener {
|
||||
onDismissListener?.invoke(TAG)
|
||||
}
|
||||
.show()
|
||||
// onPositiveClick
|
||||
// onNeutralClick
|
||||
// onNegativeClick
|
||||
|
||||
dialog.getButton(AlertDialog.BUTTON_NEUTRAL)?.onClick {
|
||||
// do custom action on neutral button click
|
||||
// (does not dismiss the dialog)
|
||||
}
|
||||
// onSingleSelectionChanged
|
||||
// onMultiSelectionChanged
|
||||
|
||||
b.clickMe.onClick {
|
||||
onActionPerformed?.invoke()
|
||||
dialog.dismiss()
|
||||
}
|
||||
}}
|
||||
// getRootView
|
||||
// onBeforeShow
|
||||
// onShow
|
||||
// onDismiss
|
||||
}
|
||||
|
@ -5,19 +5,14 @@
|
||||
package pl.szczodrzynski.edziennik.ui.timetable
|
||||
|
||||
import android.content.Intent
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.mikepenz.iconics.IconicsDrawable
|
||||
import com.mikepenz.iconics.utils.colorInt
|
||||
import com.mikepenz.iconics.utils.sizeDp
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import pl.szczodrzynski.edziennik.App
|
||||
import pl.szczodrzynski.edziennik.R
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Lesson
|
||||
@ -27,6 +22,7 @@ import pl.szczodrzynski.edziennik.databinding.DialogLessonDetailsBinding
|
||||
import pl.szczodrzynski.edziennik.ext.onClick
|
||||
import pl.szczodrzynski.edziennik.ext.setText
|
||||
import pl.szczodrzynski.edziennik.ui.attendance.AttendanceDetailsDialog
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.base.BindingDialog
|
||||
import pl.szczodrzynski.edziennik.ui.event.EventDetailsDialog
|
||||
import pl.szczodrzynski.edziennik.ui.event.EventListAdapter
|
||||
import pl.szczodrzynski.edziennik.ui.event.EventManualDialog
|
||||
@ -34,26 +30,23 @@ import pl.szczodrzynski.edziennik.utils.BetterLink
|
||||
import pl.szczodrzynski.edziennik.utils.SimpleDividerItemDecoration
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
import pl.szczodrzynski.edziennik.utils.models.Week
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
class LessonDetailsDialog(
|
||||
val activity: AppCompatActivity,
|
||||
val lesson: LessonFull,
|
||||
val attendance: AttendanceFull? = null,
|
||||
val onShowListener: ((tag: String) -> Unit)? = null,
|
||||
val onDismissListener: ((tag: String) -> Unit)? = null
|
||||
) : CoroutineScope {
|
||||
companion object {
|
||||
private const val TAG = "LessonDetailsDialog"
|
||||
}
|
||||
activity: AppCompatActivity,
|
||||
private val lesson: LessonFull,
|
||||
private val attendance: AttendanceFull? = null,
|
||||
onShowListener: ((tag: String) -> Unit)? = null,
|
||||
onDismissListener: ((tag: String) -> Unit)? = null,
|
||||
) : BindingDialog<DialogLessonDetailsBinding>(activity, onShowListener, onDismissListener) {
|
||||
|
||||
private lateinit var app: App
|
||||
private lateinit var b: DialogLessonDetailsBinding
|
||||
private lateinit var dialog: AlertDialog
|
||||
override val TAG = "LessonDetailsDialog"
|
||||
|
||||
private val job = Job()
|
||||
override val coroutineContext: CoroutineContext
|
||||
get() = job + Dispatchers.Main
|
||||
override fun getTitleRes(): Int? = null
|
||||
override fun inflate(layoutInflater: LayoutInflater) =
|
||||
DialogLessonDetailsBinding.inflate(layoutInflater)
|
||||
|
||||
override fun getPositiveButtonText() = R.string.close
|
||||
override fun getNeutralButtonText() = R.string.add
|
||||
|
||||
private lateinit var adapter: EventListAdapter
|
||||
private val manager
|
||||
@ -61,44 +54,26 @@ class LessonDetailsDialog(
|
||||
private val attendanceManager
|
||||
get() = app.attendanceManager
|
||||
|
||||
init { run {
|
||||
if (activity.isFinishing)
|
||||
return@run
|
||||
onShowListener?.invoke(TAG)
|
||||
app = activity.applicationContext as App
|
||||
b = DialogLessonDetailsBinding.inflate(activity.layoutInflater)
|
||||
dialog = MaterialAlertDialogBuilder(activity)
|
||||
.setView(b.root)
|
||||
.setPositiveButton(R.string.close) { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
}
|
||||
.setNeutralButton(R.string.add, null)
|
||||
.setOnDismissListener {
|
||||
onDismissListener?.invoke(TAG)
|
||||
}
|
||||
.show()
|
||||
|
||||
dialog.getButton(AlertDialog.BUTTON_NEUTRAL)?.onClick {
|
||||
override suspend fun onNeutralClick(): Boolean {
|
||||
EventManualDialog(
|
||||
activity,
|
||||
lesson.profileId,
|
||||
defaultLesson = lesson,
|
||||
onShowListener = onShowListener,
|
||||
onDismissListener = onDismissListener
|
||||
)
|
||||
).show()
|
||||
return NO_DISMISS
|
||||
}
|
||||
|
||||
override suspend fun onShow() {
|
||||
if (App.devMode)
|
||||
b.lessonId.visibility = View.VISIBLE
|
||||
|
||||
update()
|
||||
}}
|
||||
|
||||
private fun update() {
|
||||
b.lesson = lesson
|
||||
val lessonDate = lesson.displayDate ?: return
|
||||
val lessonTime = lesson.displayStartTime ?: return
|
||||
b.lessonDate.text = Week.getFullDayName(lessonDate.weekDay) + ", " + lessonDate.formattedString
|
||||
b.lessonDate.text =
|
||||
Week.getFullDayName(lessonDate.weekDay) + ", " + lessonDate.formattedString
|
||||
|
||||
b.annotationVisible = manager.getAnnotation(activity, lesson, b.annotation)
|
||||
|
||||
@ -145,8 +120,7 @@ class LessonDetailsDialog(
|
||||
}
|
||||
activity.sendBroadcast(intent)
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
b.shiftedLayout.visibility = View.GONE
|
||||
}
|
||||
|
||||
@ -195,7 +169,12 @@ class LessonDetailsDialog(
|
||||
true
|
||||
}
|
||||
b.attendanceDetails.onClick {
|
||||
AttendanceDetailsDialog(activity, attendance, onShowListener, onDismissListener)
|
||||
AttendanceDetailsDialog(
|
||||
activity = activity,
|
||||
attendance = attendance,
|
||||
onShowListener = onShowListener,
|
||||
onDismissListener = onDismissListener,
|
||||
).show()
|
||||
}
|
||||
}
|
||||
|
||||
@ -213,7 +192,7 @@ class LessonDetailsDialog(
|
||||
it,
|
||||
onShowListener = onShowListener,
|
||||
onDismissListener = onDismissListener
|
||||
)
|
||||
).show()
|
||||
},
|
||||
onEventEditClick = {
|
||||
EventManualDialog(
|
||||
@ -222,11 +201,15 @@ class LessonDetailsDialog(
|
||||
editingEvent = it,
|
||||
onShowListener = onShowListener,
|
||||
onDismissListener = onDismissListener
|
||||
)
|
||||
).show()
|
||||
}
|
||||
)
|
||||
|
||||
app.db.eventDao().getAllByDateTime(lesson.profileId, lessonDate, lessonTime).observe(activity, Observer { events ->
|
||||
app.db.eventDao().getAllByDateTime(
|
||||
lesson.profileId,
|
||||
lessonDate,
|
||||
lessonTime
|
||||
).observe(activity) { events ->
|
||||
adapter.setAllItems(events)
|
||||
if (b.eventsView.adapter == null) {
|
||||
b.eventsView.adapter = adapter
|
||||
@ -246,7 +229,7 @@ class LessonDetailsDialog(
|
||||
b.eventsView.visibility = View.GONE
|
||||
b.eventsNoData.visibility = View.VISIBLE
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
lesson.displayTeacherName?.let { name ->
|
||||
lesson.displayTeacherId ?: return@let
|
||||
|
@ -225,7 +225,7 @@ class TimetableDayFragment : LazyFragment(), CoroutineScope {
|
||||
activity = activity,
|
||||
lesson = lessonObj as LessonFull,
|
||||
attendance = attendanceObj as AttendanceFull?
|
||||
)
|
||||
).show()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -189,7 +189,7 @@ class TimetableFragment : Fragment(), CoroutineScope {
|
||||
.withIcon(SzkolnyFont.Icon.szf_calendar_plus_outline)
|
||||
.withOnClickListener(View.OnClickListener {
|
||||
activity.bottomSheet.close()
|
||||
EventManualDialog(activity, App.profileId, defaultDate = pageSelection)
|
||||
EventManualDialog(activity, App.profileId, defaultDate = pageSelection).show()
|
||||
}),
|
||||
BottomSheetPrimaryItem(true)
|
||||
.withTitle(R.string.menu_generate_block_timetable)
|
||||
|
@ -65,7 +65,7 @@ class WebPushFragment : Fragment(), CoroutineScope {
|
||||
QrScannerDialog(activity, {
|
||||
b.tokenEditText.setText(it.crc32().toString(36).uppercase())
|
||||
pairBrowser(browserId = it)
|
||||
})
|
||||
}).show()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -71,7 +71,7 @@ class LessonDialogActivity : AppCompatActivity(), CoroutineScope {
|
||||
if (shownDialogs.isEmpty())
|
||||
finish()
|
||||
}
|
||||
)
|
||||
).show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -87,11 +87,15 @@ class UserActionManager(val app: App) {
|
||||
return
|
||||
// show captcha dialog
|
||||
// use passed onSuccess listener, else sync profile
|
||||
LibrusCaptchaDialog(activity, onSuccess = onSuccess ?: { code ->
|
||||
LibrusCaptchaDialog(
|
||||
activity = activity,
|
||||
onSuccess = onSuccess ?: { code ->
|
||||
EdziennikTask.syncProfile(profileId, arguments = JsonObject(
|
||||
"recaptchaCode" to code,
|
||||
"recaptchaTime" to System.currentTimeMillis()
|
||||
)).enqueue(activity)
|
||||
}, onFailure = onFailure)
|
||||
},
|
||||
onFailure = onFailure
|
||||
).show()
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user