[UI] Add SimpleDialog class, migrate app dialogs (#208)
Some checks failed
Schedule/dispatch / Build nightly release (APK) (push) Has been skipped
Schedule/dispatch / Check new changes (push) Failing after 21s

* Make onShow() abstract and onDismiss() suspend

* Add dialog suspend show method

* Add SimpleDialog, support text field and choice items in BaseDialog

* Migrate MaterialAlertDialogBuilder to SimpleDialog

* Remove dialog onShow and onDismiss listeners
This commit is contained in:
Kuba Szczodrzyński 2024-07-06 19:36:59 +02:00 committed by GitHub
parent 09f0c986e0
commit 6371d71b7a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
87 changed files with 1261 additions and 1387 deletions

View File

@ -22,7 +22,6 @@ import androidx.navigation.NavOptions
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import com.danimahardhika.cafebar.CafeBar import com.danimahardhika.cafebar.CafeBar
import com.danimahardhika.cafebar.CafeBarTheme import com.danimahardhika.cafebar.CafeBarTheme
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.jetradarmobile.snowfall.SnowfallView import com.jetradarmobile.snowfall.SnowfallView
import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial
import com.mikepenz.materialdrawer.model.DividerDrawerItem import com.mikepenz.materialdrawer.model.DividerDrawerItem
@ -77,12 +76,12 @@ import pl.szczodrzynski.edziennik.ext.keys
import pl.szczodrzynski.edziennik.ext.putExtras import pl.szczodrzynski.edziennik.ext.putExtras
import pl.szczodrzynski.edziennik.ext.resolveAttr import pl.szczodrzynski.edziennik.ext.resolveAttr
import pl.szczodrzynski.edziennik.ext.resolveString import pl.szczodrzynski.edziennik.ext.resolveString
import pl.szczodrzynski.edziennik.ext.setMessage
import pl.szczodrzynski.edziennik.ext.setTintColor import pl.szczodrzynski.edziennik.ext.setTintColor
import pl.szczodrzynski.edziennik.ext.shouldArchive import pl.szczodrzynski.edziennik.ext.shouldArchive
import pl.szczodrzynski.edziennik.ext.takePositive import pl.szczodrzynski.edziennik.ext.takePositive
import pl.szczodrzynski.edziennik.ext.toDrawable import pl.szczodrzynski.edziennik.ext.toDrawable
import pl.szczodrzynski.edziennik.ext.toImageHolder import pl.szczodrzynski.edziennik.ext.toImageHolder
import pl.szczodrzynski.edziennik.ui.base.dialog.SimpleDialog
import pl.szczodrzynski.edziennik.ui.dialogs.ChangelogDialog import pl.szczodrzynski.edziennik.ui.dialogs.ChangelogDialog
import pl.szczodrzynski.edziennik.ui.dialogs.ErrorDetailsDialog import pl.szczodrzynski.edziennik.ui.dialogs.ErrorDetailsDialog
import pl.szczodrzynski.edziennik.ui.dialogs.settings.ProfileConfigDialog import pl.szczodrzynski.edziennik.ui.dialogs.settings.ProfileConfigDialog
@ -457,37 +456,37 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|__*/ |__*/
private suspend fun syncCurrentFeature() { private suspend fun syncCurrentFeature() {
if (app.profile.archived) { if (app.profile.archived) {
MaterialAlertDialogBuilder(this) SimpleDialog<Unit>(this) {
.setTitle(R.string.profile_archived_title) title(R.string.profile_archived_title)
.setMessage( message(
R.string.profile_archived_text, R.string.profile_archived_text,
app.profile.studentSchoolYearStart, app.profile.studentSchoolYearStart,
app.profile.studentSchoolYearStart + 1 app.profile.studentSchoolYearStart + 1
) )
.setPositiveButton(R.string.ok, null) positive(R.string.ok)
.show() }.show()
swipeRefreshLayout.isRefreshing = false swipeRefreshLayout.isRefreshing = false
return return
} }
if (app.profile.shouldArchive()) { if (app.profile.shouldArchive()) {
MaterialAlertDialogBuilder(this) SimpleDialog<Unit>(this) {
.setTitle(R.string.profile_archiving_title) title(R.string.profile_archiving_title)
.setMessage( message(
R.string.profile_archiving_format, R.string.profile_archiving_format,
app.profile.dateYearEnd.formattedString app.profile.dateYearEnd.formattedString
) )
.setPositiveButton(R.string.ok, null) positive(R.string.ok)
.show() }.show()
} }
if (app.profile.isBeforeYear()) { if (app.profile.isBeforeYear()) {
MaterialAlertDialogBuilder(this) SimpleDialog<Unit>(this) {
.setTitle(R.string.profile_year_not_started_title) title(R.string.profile_year_not_started_title)
.setMessage( message(
R.string.profile_year_not_started_format, R.string.profile_year_not_started_format,
app.profile.dateSemester1Start.formattedString app.profile.dateSemester1Start.formattedString
) )
.setPositiveButton(R.string.ok, null) positive(R.string.ok)
.show() }.show()
swipeRefreshLayout.isRefreshing = false swipeRefreshLayout.isRefreshing = false
return return
} }
@ -625,10 +624,10 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
EventBus.getDefault().removeStickyEvent(event) EventBus.getDefault().removeStickyEvent(event)
if (app.config.sync.dontShowAppManagerDialog) if (app.config.sync.dontShowAppManagerDialog)
return return
MaterialAlertDialogBuilder(this) SimpleDialog<Unit>(this) {
.setTitle(R.string.app_manager_dialog_title) title(R.string.app_manager_dialog_title)
.setMessage(R.string.app_manager_dialog_text) message(R.string.app_manager_dialog_text)
.setPositiveButton(R.string.ok) { _, _ -> positive(R.string.ok) {
try { try {
for (intent in appManagerIntentList) { for (intent in appManagerIntentList) {
if (packageManager.resolveActivity(intent, if (packageManager.resolveActivity(intent,
@ -642,16 +641,16 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
startActivity(Intent(Settings.ACTION_SETTINGS)) startActivity(Intent(Settings.ACTION_SETTINGS))
} catch (e: Exception) { } catch (e: Exception) {
Timber.e(e) Timber.e(e)
Toast.makeText(this, R.string.app_manager_open_failed, Toast.LENGTH_SHORT) Toast.makeText(this@MainActivity, R.string.app_manager_open_failed, Toast.LENGTH_SHORT)
.show() .show()
} }
} }
} }
.setNeutralButton(R.string.dont_ask_again) { _, _ -> neutral(R.string.dont_ask_again) {
app.config.sync.dontShowAppManagerDialog = true app.config.sync.dontShowAppManagerDialog = true
} }
.setCancelable(false) cancelable(false)
.show() }.show()
} }
@Subscribe(threadMode = ThreadMode.MAIN) @Subscribe(threadMode = ThreadMode.MAIN)

View File

@ -6,9 +6,7 @@ package pl.szczodrzynski.edziennik.core.manager
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.text.TextUtils import android.text.TextUtils
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
@ -34,6 +32,8 @@ import pl.szczodrzynski.edziennik.ext.md5
import pl.szczodrzynski.edziennik.ext.resolveAttr import pl.szczodrzynski.edziennik.ext.resolveAttr
import pl.szczodrzynski.edziennik.ext.resolveColor import pl.szczodrzynski.edziennik.ext.resolveColor
import pl.szczodrzynski.edziennik.ext.toJsonObject import pl.szczodrzynski.edziennik.ext.toJsonObject
import pl.szczodrzynski.edziennik.ui.base.dialog.BaseDialog
import pl.szczodrzynski.edziennik.ui.base.dialog.SimpleDialog
import pl.szczodrzynski.edziennik.ui.main.BuildInvalidActivity import pl.szczodrzynski.edziennik.ui.main.BuildInvalidActivity
import pl.szczodrzynski.edziennik.utils.Utils import pl.szczodrzynski.edziennik.utils.Utils
import timber.log.Timber import timber.log.Timber
@ -174,18 +174,19 @@ class BuildManager(val app: App) : CoroutineScope {
) )
}.concat("\n\n") }.concat("\n\n")
MaterialAlertDialogBuilder(activity) SimpleDialog<Unit>(activity) {
.setTitle(R.string.build_details) title(R.string.build_details)
.setMessage(message) message(message)
.setPositiveButton(R.string.ok, null) positive(R.string.ok, null)
.setNeutralButton(R.string.build_dialog_open_repo) { _, _ -> neutral(R.string.build_dialog_open_repo) {
val url = if (gitRemote == null) val url = if (gitRemote == null)
"https://szkolny.eu/github/android" "https://szkolny.eu/github/android"
else else
"https://github.com/$gitRemote/tree/$gitHash" "https://github.com/$gitRemote/tree/$gitHash"
Utils.openUrl(activity, url) Utils.openUrl(activity, url)
} }
.show() show()
}
} }
enum class InvalidBuildReason( enum class InvalidBuildReason(
@ -294,11 +295,11 @@ class BuildManager(val app: App) : CoroutineScope {
return@launch return@launch
} }
val dialog = MaterialAlertDialogBuilder(activity) val dialog = SimpleDialog<Unit>(activity) {
.setTitle(R.string.please_wait) title(R.string.please_wait)
.setMessage(R.string.build_validate_progress) message(R.string.build_validate_progress)
.setCancelable(false) cancelable(false)
.show() }.show()
val isRepoValid = if (app.config.validation == "invalid$gitRemote$gitHash".md5()) val isRepoValid = if (app.config.validation == "invalid$gitRemote$gitHash".md5())
false false
@ -320,7 +321,7 @@ class BuildManager(val app: App) : CoroutineScope {
private fun invalidateBuild( private fun invalidateBuild(
activity: AppCompatActivity, activity: AppCompatActivity,
progressDialog: AlertDialog?, progressDialog: BaseDialog<*>?,
reason: InvalidBuildReason reason: InvalidBuildReason
) { ) {
progressDialog?.dismiss() progressDialog?.dismiss()

View File

@ -218,8 +218,6 @@ class NoteManager(private val app: App) {
activity = activity, activity = activity,
attendance = item, attendance = item,
showNotes = false, showNotes = false,
onShowListener = onShowListener,
onDismissListener = onDismissListener,
).show() ).show()
is NoticeFull -> return is NoticeFull -> return
is Date -> DayDialog( is Date -> DayDialog(
@ -227,29 +225,21 @@ class NoteManager(private val app: App) {
profileId = App.profileId, profileId = App.profileId,
date = item, date = item,
showNotes = false, showNotes = false,
onShowListener = onShowListener,
onDismissListener = onDismissListener,
).show() ).show()
is EventFull -> EventDetailsDialog( is EventFull -> EventDetailsDialog(
activity = activity, activity = activity,
event = item, event = item,
showNotes = false, showNotes = false,
onShowListener = onShowListener,
onDismissListener = onDismissListener,
).show() ).show()
is GradeFull -> GradeDetailsDialog( is GradeFull -> GradeDetailsDialog(
activity = activity, activity = activity,
grade = item, grade = item,
showNotes = false, showNotes = false,
onShowListener = onShowListener,
onDismissListener = onDismissListener,
).show() ).show()
is LessonFull -> LessonDetailsDialog( is LessonFull -> LessonDetailsDialog(
activity = activity, activity = activity,
lesson = item, lesson = item,
showNotes = false, showNotes = false,
onShowListener = onShowListener,
onDismissListener = onDismissListener,
).show() ).show()
is MessageFull -> return is MessageFull -> return
} }

View File

@ -12,7 +12,6 @@ import android.os.Build
import android.provider.Settings import android.provider.Settings
import androidx.annotation.StringRes import androidx.annotation.StringRes
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.qifan.powerpermission.coroutines.awaitAskPermissions import com.qifan.powerpermission.coroutines.awaitAskPermissions
import com.qifan.powerpermission.data.hasAllGranted import com.qifan.powerpermission.data.hasAllGranted
import com.qifan.powerpermission.data.hasPermanentDenied import com.qifan.powerpermission.data.hasPermanentDenied
@ -23,6 +22,7 @@ import kotlinx.coroutines.Job
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import pl.szczodrzynski.edziennik.App import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.R import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.ui.base.dialog.SimpleDialog
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
class PermissionManager(val app: App) : CoroutineScope { class PermissionManager(val app: App) : CoroutineScope {
@ -70,10 +70,10 @@ class PermissionManager(val app: App) : CoroutineScope {
onSuccess() onSuccess()
return@launch return@launch
} }
MaterialAlertDialogBuilder(activity) SimpleDialog<Unit>(activity) {
.setTitle(R.string.permissions_required) title(R.string.permissions_required)
.setMessage(permissionMessage) message(permissionMessage)
.setPositiveButton(R.string.ok) { _, _ -> positive(R.string.ok) {
requestPermission( requestPermission(
activity, activity,
permissionMessage, permissionMessage,
@ -82,22 +82,22 @@ class PermissionManager(val app: App) : CoroutineScope {
onSuccess onSuccess
) )
} }
.setNegativeButton(R.string.cancel, null) negative(R.string.cancel)
.show() }.show()
} }
result.hasPermanentDenied() -> { result.hasPermanentDenied() -> {
if (!isRequired) { if (!isRequired) {
onSuccess() onSuccess()
return@launch return@launch
} }
MaterialAlertDialogBuilder(activity) SimpleDialog<Unit>(activity) {
.setTitle(R.string.permissions_required) title(R.string.permissions_required)
.setMessage(R.string.permissions_denied) message(R.string.permissions_denied)
.setPositiveButton(R.string.ok) { _, _ -> positive(R.string.ok) {
openPermissionSettings(activity) openPermissionSettings(activity)
} }
.setNegativeButton(R.string.cancel, null) negative(R.string.cancel)
.show() }.show()
} }
} }
} }

View File

@ -287,8 +287,6 @@ class TextStylingManager(private val app: App) {
activity: AppCompatActivity, activity: AppCompatActivity,
textLayout: TextInputLayout, textLayout: TextInputLayout,
textEdit: TextInputKeyboardEdit, textEdit: TextInputKeyboardEdit,
onShowListener: ((tag: String) -> Unit)? = null,
onDismissListener: ((tag: String) -> Unit)? = null,
) { ) {
textLayout.endIconDrawable = CommunityMaterial.Icon3.cmd_open_in_new.toDrawable(activity) textLayout.endIconDrawable = CommunityMaterial.Icon3.cmd_open_in_new.toDrawable(activity)
textLayout.setEndIconOnClickListener { textLayout.setEndIconOnClickListener {
@ -298,8 +296,6 @@ class TextStylingManager(private val app: App) {
onSuccess = { onSuccess = {
textEdit.text = it textEdit.text = it
}, },
onShowListener,
onDismissListener
).show() ).show()
} }
} }

View File

@ -6,67 +6,14 @@ package pl.szczodrzynski.edziennik.ext
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.res.ColorStateList import android.content.res.ColorStateList
import android.text.InputType
import android.view.LayoutInflater
import androidx.annotation.StringRes
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.core.graphics.ColorUtils import androidx.core.graphics.ColorUtils
import androidx.core.view.ViewCompat import androidx.core.view.ViewCompat
import androidx.core.view.isVisible
import androidx.core.widget.addTextChangedListener
import com.google.android.material.color.MaterialColors import com.google.android.material.color.MaterialColors
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.dialog.MaterialDialogs import com.google.android.material.dialog.MaterialDialogs
import com.google.android.material.shape.MaterialShapeDrawable import com.google.android.material.shape.MaterialShapeDrawable
import com.google.android.material.textfield.TextInputEditText
import pl.szczodrzynski.edziennik.R import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.databinding.DialogEditTextBinding
fun MaterialAlertDialogBuilder.input(
message: CharSequence? = null,
type: Int = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_FLAG_MULTI_LINE,
hint: CharSequence? = null,
value: CharSequence? = null,
changeListener: ((editText: TextInputEditText, input: String) -> Boolean)? = null,
positiveButton: Int? = null,
positiveListener: ((editText: TextInputEditText, input: String) -> Boolean)? = null,
): MaterialAlertDialogBuilder {
val b = DialogEditTextBinding.inflate(LayoutInflater.from(context), null, false)
b.title.text = message
b.title.isVisible = message.isNotNullNorBlank()
b.text1.hint = hint
b.text1.inputType = type
b.text1.setText(value)
b.text1.addTextChangedListener { text ->
if (changeListener?.invoke(b.text1, text?.toString() ?: "") != false)
b.text1.error = null
}
if (positiveButton != null) {
setPositiveButton(positiveButton) { dialog, _ ->
if (positiveListener?.invoke(b.text1, b.text1.text?.toString() ?: "") != false)
dialog.dismiss()
}
}
setView(b.root)
return this
}
fun MaterialAlertDialogBuilder.setTitle(
@StringRes resId: Int,
vararg formatArgs: Any,
): MaterialAlertDialogBuilder {
setTitle(context.getString(resId, *formatArgs))
return this
}
fun MaterialAlertDialogBuilder.setMessage(
@StringRes resId: Int,
vararg formatArgs: Any,
): MaterialAlertDialogBuilder {
setMessage(context.getString(resId, *formatArgs))
return this
}
@SuppressLint("RestrictedApi") @SuppressLint("RestrictedApi")
fun AlertDialog.overlayBackgroundColor(color: Int, alpha: Int) { fun AlertDialog.overlayBackgroundColor(color: Int, alpha: Int) {

View File

@ -157,7 +157,7 @@ fun IIcon.toDrawable(
colorRes: Int? = null, colorRes: Int? = null,
colorAttr: Int = R.attr.colorOnBackground, colorAttr: Int = R.attr.colorOnBackground,
sizeDp: Int = 24, sizeDp: Int = 24,
) = toDrawable(activity, colorInt, colorRes, colorAttr, sizeDp) ) = toDrawable(app, colorInt, colorRes, colorAttr, sizeDp)
context(View) context(View)
fun IIcon.toDrawable( fun IIcon.toDrawable(

View File

@ -16,6 +16,7 @@ import androidx.lifecycle.Observer
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.greenrobot.eventbus.EventBus
import java.io.PrintWriter import java.io.PrintWriter
import java.io.StringWriter import java.io.StringWriter
@ -88,3 +89,13 @@ fun Long?.takePositive() = if (this == -1L || this == 0L) null else this
fun String?.takeValue() = if (this.isNullOrBlank()) null else this fun String?.takeValue() = if (this.isNullOrBlank()) null else this
fun Any?.ignore() = Unit fun Any?.ignore() = Unit
fun EventBus.registerSafe(subscriber: Any) = try {
EventBus.getDefault().register(subscriber)
} catch (_: Exception) {
}
fun EventBus.unregisterSafe(subscriber: Any) = try {
EventBus.getDefault().unregister(subscriber)
} catch (_: Exception) {
}

View File

@ -63,7 +63,7 @@ class AgendaFragment : BaseFragment<ViewBinding, MainActivity>(
.withIcon(CommunityMaterial.Icon.cmd_cog_outline) .withIcon(CommunityMaterial.Icon.cmd_cog_outline)
.withOnClickListener { .withOnClickListener {
activity.bottomSheet.close() activity.bottomSheet.close()
AgendaConfigDialog(activity, true, null, null).show() AgendaConfigDialog(activity, true).show()
}, },
BottomSheetPrimaryItem(true) BottomSheetPrimaryItem(true)
.withTitle(R.string.menu_agenda_change_view) .withTitle(R.string.menu_agenda_change_view)

View File

@ -39,11 +39,7 @@ class DayDialog(
private val date: Date, private val date: Date,
private val eventTypeId: Long? = null, private val eventTypeId: Long? = null,
private val showNotes: Boolean = false, private val showNotes: Boolean = false,
onShowListener: ((tag: String) -> Unit)? = null, ) : BindingDialog<DialogDayBinding>(activity) {
onDismissListener: ((tag: String) -> Unit)? = null,
) : BindingDialog<DialogDayBinding>(activity, onShowListener, onDismissListener) {
override val TAG = "DayDialog"
override fun getTitleRes(): Int? = null override fun getTitleRes(): Int? = null
override fun inflate(layoutInflater: LayoutInflater) = override fun inflate(layoutInflater: LayoutInflater) =
@ -59,8 +55,6 @@ class DayDialog(
activity, activity,
profileId, profileId,
defaultDate = date, defaultDate = date,
onShowListener = onShowListener,
onDismissListener = onDismissListener
).show() ).show()
return NO_DISMISS return NO_DISMISS
} }
@ -114,8 +108,6 @@ class DayDialog(
activity, activity,
profileId, profileId,
date, date,
onShowListener = onShowListener,
onDismissListener = onDismissListener
).show() ).show()
} }
} }
@ -139,8 +131,6 @@ class DayDialog(
activity, activity,
profileId, profileId,
date, date,
onShowListener = onShowListener,
onDismissListener = onDismissListener
).show() ).show()
} }
} }
@ -158,8 +148,6 @@ class DayDialog(
EventDetailsDialog( EventDetailsDialog(
activity, activity,
it, it,
onShowListener = onShowListener,
onDismissListener = onDismissListener
).show() ).show()
}, },
onEventEditClick = { onEventEditClick = {
@ -167,8 +155,6 @@ class DayDialog(
activity, activity,
it.profileId, it.profileId,
editingEvent = it, editingEvent = it,
onShowListener = onShowListener,
onDismissListener = onDismissListener
).show() ).show()
} }
) )
@ -209,8 +195,6 @@ class DayDialog(
b.notesButton.setupNotesButton( b.notesButton.setupNotesButton(
activity = activity, activity = activity,
owner = date, owner = date,
onShowListener = onShowListener,
onDismissListener = onDismissListener,
) )
b.legend.isVisible = showNotes b.legend.isVisible = showNotes
if (showNotes) if (showNotes)

View File

@ -15,14 +15,9 @@ class LessonChangesDialog(
activity: AppCompatActivity, activity: AppCompatActivity,
private val profileId: Int, private val profileId: Int,
private val defaultDate: Date, private val defaultDate: Date,
onShowListener: ((tag: String) -> Unit)? = null, ) : BindingDialog<DialogLessonChangeListBinding>(activity) {
onDismissListener: ((tag: String) -> Unit)? = null,
) : BindingDialog<DialogLessonChangeListBinding>(activity, onShowListener, onDismissListener) {
override val TAG = "LessonChangesDialog"
override fun getTitle(): String = defaultDate.formattedString override fun getTitle(): String = defaultDate.formattedString
override fun getTitleRes(): Int? = null
override fun inflate(layoutInflater: LayoutInflater) = override fun inflate(layoutInflater: LayoutInflater) =
DialogLessonChangeListBinding.inflate(layoutInflater) DialogLessonChangeListBinding.inflate(layoutInflater)
@ -39,8 +34,6 @@ class LessonChangesDialog(
LessonDetailsDialog( LessonDetailsDialog(
activity, activity,
it, it,
onShowListener = onShowListener,
onDismissListener = onDismissListener
).show() ).show()
} }
).apply { ).apply {

View File

@ -14,14 +14,9 @@ class TeacherAbsenceDialog(
activity: AppCompatActivity, activity: AppCompatActivity,
private val profileId: Int, private val profileId: Int,
private val date: Date, private val date: Date,
onShowListener: ((tag: String) -> Unit)? = null, ) : BindingDialog<DialogTeacherAbsenceListBinding>(activity) {
onDismissListener: ((tag: String) -> Unit)? = null,
) : BindingDialog<DialogTeacherAbsenceListBinding>(activity, onShowListener, onDismissListener) {
override val TAG = "TeacherAbsenceDialog"
override fun getTitle(): String = date.formattedString override fun getTitle(): String = date.formattedString
override fun getTitleRes(): Int? = null
override fun inflate(layoutInflater: LayoutInflater) = override fun inflate(layoutInflater: LayoutInflater) =
DialogTeacherAbsenceListBinding.inflate(layoutInflater) DialogTeacherAbsenceListBinding.inflate(layoutInflater)

View File

@ -22,11 +22,7 @@ class AttendanceDetailsDialog(
activity: AppCompatActivity, activity: AppCompatActivity,
private val attendance: AttendanceFull, private val attendance: AttendanceFull,
private val showNotes: Boolean = true, private val showNotes: Boolean = true,
onShowListener: ((tag: String) -> Unit)? = null, ) : BindingDialog<AttendanceDetailsDialogBinding>(activity) {
onDismissListener: ((tag: String) -> Unit)? = null,
) : BindingDialog<AttendanceDetailsDialogBinding>(activity, onShowListener, onDismissListener) {
override val TAG = "AttendanceDetailsDialog"
override fun getTitleRes(): Int? = null override fun getTitleRes(): Int? = null
override fun inflate(layoutInflater: LayoutInflater) = override fun inflate(layoutInflater: LayoutInflater) =
@ -34,7 +30,7 @@ class AttendanceDetailsDialog(
override fun getPositiveButtonText() = R.string.close override fun getPositiveButtonText() = R.string.close
override suspend fun onShow() { override suspend fun onBeforeShow(): Boolean {
val manager = app.attendanceManager val manager = app.attendanceManager
val attendanceColor = manager.getAttendanceColor(attendance) val attendanceColor = manager.getAttendanceColor(attendance)
@ -49,7 +45,7 @@ class AttendanceDetailsDialog(
BetterLink.attach( BetterLink.attach(
b.teacherName, b.teacherName,
teachers = mapOf(attendance.teacherId to name), teachers = mapOf(attendance.teacherId to name),
onActionSelected = dialog::dismiss onActionSelected = ::dismiss
) )
} }
@ -57,11 +53,10 @@ class AttendanceDetailsDialog(
b.notesButton.setupNotesButton( b.notesButton.setupNotesButton(
activity = activity, activity = activity,
owner = attendance, owner = attendance,
onShowListener = onShowListener,
onDismissListener = onDismissListener,
) )
b.legend.isVisible = showNotes b.legend.isVisible = showNotes
if (showNotes) if (showNotes)
NoteManager.setLegendText(attendance, b.legend) NoteManager.setLegendText(attendance, b.legend)
return true
} }
} }

View File

@ -38,7 +38,7 @@ class AttendanceFragment : PagerFragment<BasePagerFragmentBinding, MainActivity>
.withIcon(CommunityMaterial.Icon.cmd_cog_outline) .withIcon(CommunityMaterial.Icon.cmd_cog_outline)
.withOnClickListener { .withOnClickListener {
activity.bottomSheet.close() activity.bottomSheet.close()
AttendanceConfigDialog(activity, true, null, null).show() AttendanceConfigDialog(activity, true).show()
}, },
) )

View File

@ -4,88 +4,108 @@
package pl.szczodrzynski.edziennik.ui.base.dialog package pl.szczodrzynski.edziennik.ui.base.dialog
import android.text.Editable
import android.view.LayoutInflater
import android.view.View import android.view.View
import android.widget.TextView
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AlertDialog.* import androidx.appcompat.app.AlertDialog.BUTTON_NEGATIVE
import androidx.appcompat.app.AlertDialog.BUTTON_NEUTRAL
import androidx.appcompat.app.AlertDialog.BUTTON_POSITIVE
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.widget.addTextChangedListener
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.textfield.TextInputEditText
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.suspendCancellableCoroutine
import org.greenrobot.eventbus.EventBus
import pl.szczodrzynski.edziennik.App import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.databinding.DialogEditTextBinding
import pl.szczodrzynski.edziennik.ext.onClick import pl.szczodrzynski.edziennik.ext.onClick
import pl.szczodrzynski.edziennik.ext.setMessage import pl.szczodrzynski.edziennik.ext.registerSafe
import pl.szczodrzynski.edziennik.ext.resolveString
import pl.szczodrzynski.edziennik.ext.unregisterSafe
import pl.szczodrzynski.edziennik.utils.BetterLinkMovementMethod
import kotlin.coroutines.Continuation
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.resume
abstract class BaseDialog<I : Any>( abstract class BaseDialog<I : Any>(
internal val activity: AppCompatActivity, protected val activity: AppCompatActivity,
protected val onShowListener: ((tag: String) -> Unit)? = null,
protected val onDismissListener: ((tag: String) -> Unit)? = null,
) : CoroutineScope { ) : CoroutineScope {
companion object { companion object {
const val DISMISS = true const val DISMISS = true
const val NO_DISMISS = false const val NO_DISMISS = false
} }
@Suppress("PropertyName") internal val app = activity.applicationContext as App
abstract val TAG: String
protected lateinit var app: App
protected lateinit var dialog: AlertDialog protected lateinit var dialog: AlertDialog
private val job = Job() private var job = Job()
override val coroutineContext: CoroutineContext override val coroutineContext: CoroutineContext
get() = job + Dispatchers.Main get() = job + Dispatchers.Main
private var continuation: Continuation<BaseDialog<I>>? = null
private var button: Int? = null
private var items = emptyList<I>() private var items = emptyList<I>()
private var itemSelected: I? = null private var itemSelected: I? = null
private var itemStates = BooleanArray(0) private var itemStates = BooleanArray(0)
private var input: TextInputEditText? = null
protected open fun getTitle(): CharSequence? = null protected open fun getTitle(): CharSequence? = null
protected abstract fun getTitleRes(): Int? protected open fun getTitleRes(): Int? = null
protected open fun getMessage(): CharSequence? = null protected open fun getMessage(): CharSequence? = null
protected open fun getMessageRes(): Int? = null protected open fun getMessageRes(): Int? = null
protected open fun getMessageFormat(): Pair<Int, List<CharSequence>>? = null protected open fun getMessageFormat(): Pair<Int, List<CharSequence>>? = null
protected open fun getView(): View? = null protected open fun getView(): View? = null
open fun isCancelable() = true protected open fun isCancelable() = true
open fun getPositiveButtonText(): Int? = null protected open fun getPositiveButtonText(): Int? = null
open fun getNeutralButtonText(): Int? = null protected open fun getNeutralButtonText(): Int? = null
open fun getNegativeButtonText(): Int? = null protected open fun getNegativeButtonText(): Int? = null
protected open fun getItems(): Map<CharSequence, I>? = null
protected open fun getSingleChoiceItems(): Map<CharSequence, I>? = null protected open fun getSingleChoiceItems(): Map<CharSequence, I>? = null
protected open fun getMultiChoiceItems(): Map<CharSequence, I>? = null protected open fun getMultiChoiceItems(): Map<CharSequence, I>? = null
protected open fun getDefaultSelectedItem(): I? = null protected open fun getDefaultSelectedItem(): I? = null
protected open fun getDefaultSelectedItems(): Set<I> = emptySet() protected open fun getDefaultSelectedItems(): Set<I> = emptySet()
open suspend fun onPositiveClick() = true protected open fun getInputType(): Int? = null
open suspend fun onNeutralClick() = true protected open fun getInputHint(): CharSequence? = null
open suspend fun onNegativeClick() = true protected open fun getInputHintRes(): Int? = null
open suspend fun onSingleSelectionChanged(item: I?) = Unit protected open fun getInputValue(): CharSequence? = null
open suspend fun onMultiSelectionChanged(items: Set<I>) = Unit
protected open suspend fun onPositiveClick() = DISMISS
protected open suspend fun onNeutralClick() = DISMISS
protected open suspend fun onNegativeClick() = DISMISS
protected open suspend fun onItemClick(item: I) = DISMISS
protected open suspend fun onSingleSelectionChanged(item: I) = Unit
protected open suspend fun onMultiSelectionChanged(item: I, isChecked: Boolean) = Unit
protected open suspend fun onInputTextChanged(input: TextInputEditText, text: Editable?) = Unit
protected open suspend fun onBeforeShow() = true protected open suspend fun onBeforeShow() = true
protected abstract suspend fun onShow() protected open suspend fun onShow() = Unit
protected open fun onDismiss() = Unit protected open suspend fun onDismiss() = Unit
fun show() { fun show(): BaseDialog<I> {
if (activity.isFinishing) if (activity.isFinishing)
return return this
onShowListener?.invoke(TAG) job.cancel()
app = activity.applicationContext as App job = Job()
dialog = MaterialAlertDialogBuilder(activity) dialog = MaterialAlertDialogBuilder(activity)
.also(this::configure) .also(this::configure)
.setCancelable(isCancelable()) .setCancelable(isCancelable())
.setOnDismissListener { .setOnDismissListener {
onDismiss() launch {
onDismissListener?.invoke(TAG) dispatchOnDismiss()
job.cancel()
}
} }
.create() .create()
reload()
}
protected fun reload() {
launch { launch {
if (activity.isFinishing) if (activity.isFinishing)
return@launch return@launch
@ -93,10 +113,37 @@ abstract class BaseDialog<I : Any>(
dialog.dismiss() dialog.dismiss()
return@launch return@launch
} }
if (activity.isFinishing)
return@launch
dialog.show() dialog.show()
setButtons() setButtons()
onShow() dispatchOnShow()
} }
return this
}
suspend fun showModal() = suspendCancellableCoroutine {
it.invokeOnCancellation {
dismiss()
}
continuation = it
show()
}
private suspend fun dispatchOnShow() {
if (activity.isFinishing)
return
EventBus.getDefault().registerSafe(this)
onShow()
}
private suspend fun dispatchOnDismiss() {
if (activity.isFinishing)
return
onDismiss()
EventBus.getDefault().unregisterSafe(this)
continuation?.resume(this)
continuation = null
} }
private fun configure(md: MaterialAlertDialogBuilder) { private fun configure(md: MaterialAlertDialogBuilder) {
@ -106,6 +153,19 @@ abstract class BaseDialog<I : Any>(
getTitleRes()?.let { getTitleRes()?.let {
md.setTitle(it) md.setTitle(it)
} }
getMessage()?.let {
md.setMessage(it)
}
getMessageRes()?.let {
md.setMessage(it)
}
getMessageFormat()?.let { (stringId, formatArgs) ->
md.setMessage(activity.getString(stringId, *formatArgs.toTypedArray()))
}
getView()?.let {
md.setView(it)
}
getPositiveButtonText()?.let { getPositiveButtonText()?.let {
md.setPositiveButton(it, null) md.setPositiveButton(it, null)
} }
@ -116,26 +176,30 @@ abstract class BaseDialog<I : Any>(
md.setNegativeButton(it, null) md.setNegativeButton(it, null)
} }
getMessage()?.let { getItems()?.let { map ->
md.setMessage(it) md.setItems(map.keys.toTypedArray()) { _, which ->
button = null
launch {
itemSelected = items[which]
if (onItemClick(items[which]))
dismiss()
}
}
items = map.values.toList()
itemSelected = null
md.setMessage(null)
} }
getMessageRes()?.let {
md.setMessage(it)
}
getMessageFormat()?.let { (stringId, formatArgs) ->
md.setMessage(stringId, *formatArgs.toTypedArray())
}
getView()?.let {
md.setView(it)
}
getSingleChoiceItems()?.let { map -> getSingleChoiceItems()?.let { map ->
val default = getDefaultSelectedItem() val default = getDefaultSelectedItem()
val defaultIndex = map.values.indexOf(default) val defaultIndex = map.values.indexOf(default)
md.setSingleChoiceItems(map.keys.toTypedArray(), defaultIndex) { _, which -> md.setSingleChoiceItems(
map.keys.toTypedArray(),
defaultIndex
) { _, which ->
button = null
launch { launch {
itemSelected = items[which] itemSelected = items[which]
onSingleSelectionChanged(getSingleSelection()) onSingleSelectionChanged(items[which])
} }
} }
items = map.values.toList() items = map.values.toList()
@ -147,44 +211,71 @@ abstract class BaseDialog<I : Any>(
val defaultStates = map.values.map { val defaultStates = map.values.map {
it in default it in default
}.toBooleanArray() }.toBooleanArray()
md.setMultiChoiceItems(map.keys.toTypedArray(), md.setMultiChoiceItems(
defaultStates) { _, position, isChecked -> map.keys.toTypedArray(),
defaultStates
) { _, position, isChecked ->
button = null
launch { launch {
itemStates[position] = isChecked itemStates[position] = isChecked
onMultiSelectionChanged(getMultiSelection()) onMultiSelectionChanged(items[position], isChecked)
} }
} }
items = map.values.toList() items = map.values.toList()
itemStates = defaultStates itemStates = defaultStates
md.setMessage(null) md.setMessage(null)
} }
getInputType()?.let { inputType ->
val b = DialogEditTextBinding.inflate(LayoutInflater.from(activity), null, false)
b.text1.let {
it.inputType = inputType
it.hint = getInputHint() ?: getInputHintRes()?.resolveString(activity)
it.setText(getInputValue() ?: "")
it.addTextChangedListener {
launch {
onInputTextChanged(b.text1, it)
}
}
}
input = b.text1
md.setView(b.root)
}
} }
private fun setButtons() { private fun setButtons() {
dialog.getButton(BUTTON_POSITIVE)?.onClick { dialog.getButton(BUTTON_POSITIVE)?.onClick {
button = BUTTON_POSITIVE
launch { launch {
if (onPositiveClick()) if (onPositiveClick())
dialog.dismiss() dismiss()
} }
} }
dialog.getButton(BUTTON_NEUTRAL)?.onClick { dialog.getButton(BUTTON_NEUTRAL)?.onClick {
button = BUTTON_NEUTRAL
launch { launch {
if (onNeutralClick()) if (onNeutralClick())
dialog.dismiss() dismiss()
} }
} }
dialog.getButton(BUTTON_NEGATIVE)?.onClick { dialog.getButton(BUTTON_NEGATIVE)?.onClick {
button = BUTTON_NEGATIVE
launch { launch {
if (onNegativeClick()) if (onNegativeClick())
dialog.dismiss() dismiss()
} }
} }
dialog.findViewById<TextView>(android.R.id.message)?.movementMethod =
BetterLinkMovementMethod.getInstance()
} }
protected fun getSingleSelection() = itemSelected fun getButton() = button
protected fun getMultiSelection(): Set<I> { fun getItem() = itemSelected
fun getSingleSelection() = itemSelected
fun getMultiSelection(): Set<I> {
return itemStates.mapIndexed { position, isChecked -> return itemStates.mapIndexed { position, isChecked ->
if (isChecked) if (isChecked)
items[position] items[position]
@ -193,7 +284,9 @@ abstract class BaseDialog<I : Any>(
}.filterNotNull().toSet() }.filterNotNull().toSet()
} }
protected fun dismiss() { fun getInput(): TextInputEditText? = input
fun dismiss() {
dialog.dismiss() dialog.dismiss()
} }
} }

View File

@ -11,9 +11,7 @@ import androidx.viewbinding.ViewBinding
abstract class BindingDialog<B : ViewBinding>( abstract class BindingDialog<B : ViewBinding>(
activity: AppCompatActivity, activity: AppCompatActivity,
onShowListener: ((tag: String) -> Unit)? = null, ) : ViewDialog<View>(activity) {
onDismissListener: ((tag: String) -> Unit)? = null,
) : ViewDialog<View>(activity, onShowListener, onDismissListener) {
protected lateinit var b: B protected lateinit var b: B
protected abstract fun inflate(layoutInflater: LayoutInflater): B protected abstract fun inflate(layoutInflater: LayoutInflater): B

View File

@ -13,9 +13,7 @@ import pl.szczodrzynski.edziennik.R
abstract class ConfigDialog<B : ViewBinding>( abstract class ConfigDialog<B : ViewBinding>(
activity: AppCompatActivity, activity: AppCompatActivity,
private val reloadOnDismiss: Boolean = true, private val reloadOnDismiss: Boolean = true,
onShowListener: ((tag: String) -> Unit)? = null, ) : BindingDialog<B>(activity) {
onDismissListener: ((tag: String) -> Unit)? = null,
) : BindingDialog<B>(activity, onShowListener, onDismissListener) {
final override fun getPositiveButtonText() = R.string.ok final override fun getPositiveButtonText() = R.string.ok
final override suspend fun onShow() = Unit final override suspend fun onShow() = Unit
@ -32,10 +30,8 @@ abstract class ConfigDialog<B : ViewBinding>(
return true return true
} }
final override fun onDismiss() { final override suspend fun onDismiss() {
launch { saveConfig()
saveConfig()
}
if (reloadOnDismiss && activity is MainActivity) if (reloadOnDismiss && activity is MainActivity)
activity.reloadTarget() activity.reloadTarget()
} }

View File

@ -0,0 +1,258 @@
/*
* Copyright (c) Kuba Szczodrzyński 2024-7-5.
*/
package pl.szczodrzynski.edziennik.ui.base.dialog
import android.text.Editable
import android.text.InputType
import androidx.appcompat.app.AppCompatActivity
import com.google.android.material.textfield.TextInputEditText
import pl.szczodrzynski.edziennik.ext.resolveString
class SimpleDialog<I : Any>(
activity: AppCompatActivity,
config: SimpleDialog<I>.() -> Unit,
) : BaseDialog<I>(activity) {
init {
config()
}
private var title: CharSequence? = null
private var titleRes: Int? = null
private var message: CharSequence? = null
private var messageRes: Int? = null
private var messageFormat: Pair<Int, List<CharSequence>>? = null
private var isCancelable = true
private var positiveButtonText: Int? = null
private var neutralButtonText: Int? = null
private var negativeButtonText: Int? = null
private var items: Map<CharSequence, I>? = null
private var singleChoiceItems: Map<CharSequence, I>? = null
private var multiChoiceItems: Map<CharSequence, I>? = null
private var defaultSelectedItem: I? = null
private var defaultSelectedItems: Set<I>? = null
private var inputType: Int? = null
private var inputHint: CharSequence? = null
private var inputHintRes: Int? = null
private var inputValue: CharSequence? = null
private var onPositiveClick: (suspend () -> Unit)? = null
private var onNeutralClick: (suspend () -> Unit)? = null
private var onNegativeClick: (suspend () -> Unit)? = null
private var onItemClick: (suspend (item: I) -> Unit)? = null
private var onSingleSelectionChanged: (suspend (item: I) -> Unit)? = null
private var onMultiSelectionChanged: (suspend (item: I, isChecked: Boolean) -> Unit)? = null
private var onInputTextChanged: (suspend TextInputEditText.(text: Editable?) -> Unit)? = null
fun title(value: CharSequence) {
title = value
}
fun title(value: Int) {
titleRes = value
}
fun message(value: CharSequence) {
message = value
}
fun message(value: Int, vararg args: Any) {
if (args.isEmpty()) {
messageRes = value
} else {
messageFormat = value to args.map {
if (it is CharSequence) it else it.toString()
}
}
}
fun cancelable(value: Boolean) {
isCancelable = value
}
fun positive(text: Int, block: (suspend () -> Unit)? = null) {
positiveButtonText = text
onPositiveClick = block
}
fun neutral(text: Int, block: (suspend () -> Unit)? = null) {
neutralButtonText = text
onNeutralClick = block
}
fun negative(text: Int, block: (suspend () -> Unit)? = null) {
negativeButtonText = text
onNegativeClick = block
}
fun items(
items: Map<CharSequence, I>,
block: (suspend (item: I) -> Unit)? = null,
) {
this.items = items
onItemClick = block
}
fun itemsRes(
items: Map<Int, I>,
block: (suspend (item: I) -> Unit)? = null,
) {
this.items = items.mapKeys { (k, _) -> k.resolveString(activity) }
onItemClick = block
}
fun single(
items: Map<CharSequence, I>,
default: I? = null,
block: (suspend (item: I) -> Unit)? = null,
) {
singleChoiceItems = items
defaultSelectedItem = default
onSingleSelectionChanged = block
}
fun singleRes(
items: Map<Int, I>,
default: I? = null,
block: (suspend (item: I) -> Unit)? = null,
) {
singleChoiceItems = items.mapKeys { (k, _) -> k.resolveString(activity) }
defaultSelectedItem = default
onSingleSelectionChanged = block
}
fun multi(
items: Map<CharSequence, I>,
default: Set<I> = emptySet(),
block: (suspend (item: I, isChecked: Boolean) -> Unit)? = null,
) {
multiChoiceItems = items
defaultSelectedItems = default
onMultiSelectionChanged = block
}
fun multiRes(
items: Map<Int, I>,
default: Set<I> = emptySet(),
block: (suspend (item: I, isChecked: Boolean) -> Unit)? = null,
) {
singleChoiceItems = items.mapKeys { (k, _) -> k.resolveString(activity) }
defaultSelectedItems = default
onMultiSelectionChanged = block
}
fun items(
vararg items: Pair<CharSequence, I>,
block: (suspend (item: I) -> Unit)? = null,
) = items(items.toMap(), block)
fun itemsRes(
vararg items: Pair<Int, I>,
block: (suspend (item: I) -> Unit)? = null,
) = itemsRes(items.toMap(), block)
fun single(
vararg items: Pair<CharSequence, I>,
default: I? = null,
block: (suspend (item: I) -> Unit)? = null,
) = single(items.toMap(), default, block)
fun singleRes(
vararg items: Pair<Int, I>,
default: I? = null,
block: (suspend (item: I) -> Unit)? = null,
) = singleRes(items.toMap(), default, block)
fun multi(
vararg items: Pair<CharSequence, I>,
default: Set<I> = emptySet(),
block: (suspend (item: I, isChecked: Boolean) -> Unit)? = null,
) = multi(items.toMap(), default, block)
fun multiRes(
vararg items: Pair<Int, I>,
default: Set<I> = emptySet(),
block: (suspend (item: I, isChecked: Boolean) -> Unit)? = null,
) = multiRes(items.toMap(), default, block)
fun input(
type: Int = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_FLAG_MULTI_LINE,
hint: CharSequence? = null,
value: CharSequence? = null,
block: (suspend TextInputEditText.(text: Editable?) -> Unit)? = null,
) {
inputType = type
inputHint = hint
inputValue = value
onInputTextChanged = block
}
fun inputRes(
type: Int,
hint: Int? = null,
value: CharSequence? = null,
block: (suspend TextInputEditText.(text: Editable?) -> Unit)? = null,
) {
inputType = type
inputHintRes = hint
inputValue = value
onInputTextChanged = block
}
override fun getTitle() = title
override fun getTitleRes() = titleRes
override fun getMessage() = message
override fun getMessageRes() = messageRes
override fun getMessageFormat() = messageFormat
override fun isCancelable() = isCancelable
override fun getPositiveButtonText() = positiveButtonText
override fun getNeutralButtonText() = neutralButtonText
override fun getNegativeButtonText() = negativeButtonText
override fun getItems() = items
override fun getSingleChoiceItems() = singleChoiceItems
override fun getMultiChoiceItems() = multiChoiceItems
override fun getDefaultSelectedItem() = defaultSelectedItem
override fun getDefaultSelectedItems() = defaultSelectedItems ?: setOf()
override fun getInputType() = inputType
override fun getInputHint() = inputHint
override fun getInputHintRes() = inputHintRes
override fun getInputValue() = inputValue
override suspend fun onPositiveClick(): Boolean {
onPositiveClick?.invoke()
return DISMISS
}
override suspend fun onNeutralClick(): Boolean {
onNeutralClick?.invoke()
return DISMISS
}
override suspend fun onNegativeClick(): Boolean {
onNegativeClick?.invoke()
return DISMISS
}
override suspend fun onItemClick(item: I): Boolean {
onItemClick?.invoke(item)
return DISMISS
}
override suspend fun onSingleSelectionChanged(item: I) {
onSingleSelectionChanged?.invoke(item)
}
override suspend fun onMultiSelectionChanged(item: I, isChecked: Boolean) {
onMultiSelectionChanged?.invoke(item, isChecked)
}
override suspend fun onInputTextChanged(input: TextInputEditText, text: Editable?) {
onInputTextChanged?.let { input.it(text) }
}
}

View File

@ -9,9 +9,7 @@ import androidx.appcompat.app.AppCompatActivity
abstract class ViewDialog<V : View>( abstract class ViewDialog<V : View>(
activity: AppCompatActivity, activity: AppCompatActivity,
onShowListener: ((tag: String) -> Unit)? = null, ) : BaseDialog<Any>(activity) {
onDismissListener: ((tag: String) -> Unit)? = null
) : BaseDialog<Any>(activity, onShowListener, onDismissListener) {
protected lateinit var root: V protected lateinit var root: V
protected abstract fun getRootView(): V protected abstract fun getRootView(): V

View File

@ -20,7 +20,9 @@ import org.greenrobot.eventbus.EventBus
import pl.szczodrzynski.edziennik.App import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.MainActivity import pl.szczodrzynski.edziennik.MainActivity
import pl.szczodrzynski.edziennik.data.enums.MetadataType import pl.szczodrzynski.edziennik.data.enums.MetadataType
import pl.szczodrzynski.edziennik.ext.registerSafe
import pl.szczodrzynski.edziennik.ext.startCoroutineTimer import pl.szczodrzynski.edziennik.ext.startCoroutineTimer
import pl.szczodrzynski.edziennik.ext.unregisterSafe
import pl.szczodrzynski.edziennik.ui.login.LoginActivity import pl.szczodrzynski.edziennik.ui.login.LoginActivity
import pl.szczodrzynski.navlib.bottomsheet.items.IBottomSheetItem import pl.szczodrzynski.navlib.bottomsheet.items.IBottomSheetItem
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
@ -86,11 +88,7 @@ abstract class BaseFragment<B : ViewBinding, A : AppCompatActivity>(
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
try { EventBus.getDefault().registerSafe(this)
EventBus.getDefault().register(this)
} catch (_: Exception) {
}
if (!isAdded || isViewReady) if (!isAdded || isViewReady)
return return
isViewReady = true isViewReady = true
@ -109,10 +107,7 @@ abstract class BaseFragment<B : ViewBinding, A : AppCompatActivity>(
override fun onPause() { override fun onPause() {
super.onPause() super.onPause()
try { EventBus.getDefault().unregisterSafe(this)
EventBus.getDefault().unregister(this)
} catch (_: Exception) {
}
} }
final override fun onDestroyView() { final override fun onDestroyView() {

View File

@ -9,14 +9,13 @@ import android.content.ContextWrapper
import android.text.InputType import android.text.InputType
import android.util.AttributeSet import android.util.AttributeSet
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import pl.szczodrzynski.edziennik.R import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.data.db.AppDb import pl.szczodrzynski.edziennik.data.db.AppDb
import pl.szczodrzynski.edziennik.data.db.entity.Subject import pl.szczodrzynski.edziennik.data.db.entity.Subject
import pl.szczodrzynski.edziennik.ext.crc16 import pl.szczodrzynski.edziennik.ext.crc16
import pl.szczodrzynski.edziennik.ext.input import pl.szczodrzynski.edziennik.ui.base.dialog.SimpleDialog
import pl.szczodrzynski.edziennik.utils.TextInputDropDown import pl.szczodrzynski.edziennik.utils.TextInputDropDown
class SubjectDropdown : TextInputDropDown { class SubjectDropdown : TextInputDropDown {
@ -108,25 +107,25 @@ class SubjectDropdown : TextInputDropDown {
private fun customNameDialog() { private fun customNameDialog() {
activity ?: return activity ?: return
MaterialAlertDialogBuilder(activity!!) SimpleDialog<Unit>(activity!!) {
.setTitle("Własny przedmiot") title("Własny przedmiot")
.input( input(
hint = "Nazwa",
type = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE, type = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE,
positiveButton = R.string.ok, hint = "Nazwa",
positiveListener = { _, input -> )
customSubjectName = input positive(R.string.ok) {
select(Item( customSubjectName = getInput()?.text?.toString() ?: ""
select(
Item(
-1L * customSubjectName.crc16(), -1L * customSubjectName.crc16(),
customSubjectName, customSubjectName,
tag = customSubjectName tag = customSubjectName
)) )
onCustomSubjectSelected?.invoke(customSubjectName) )
true onCustomSubjectSelected?.invoke(customSubjectName)
} }
) negative(R.string.cancel)
.setNegativeButton(R.string.cancel, null) }.show()
.show()
} }
/** /**

View File

@ -26,11 +26,7 @@ class RecaptchaDialog(
private val onSuccess: (recaptchaCode: String) -> Unit, private val onSuccess: (recaptchaCode: String) -> Unit,
private val onFailure: (() -> Unit)? = null, private val onFailure: (() -> Unit)? = null,
private val onServerError: (() -> Unit)? = null, private val onServerError: (() -> Unit)? = null,
onShowListener: ((tag: String) -> Unit)? = null, ) : BindingDialog<RecaptchaDialogBinding>(activity) {
onDismissListener: ((tag: String) -> Unit)? = null,
) : BindingDialog<RecaptchaDialogBinding>(activity, onShowListener, onDismissListener) {
override val TAG = "RecaptchaDialog"
override fun getTitleRes(): Int? = null override fun getTitleRes(): Int? = null
override fun inflate(layoutInflater: LayoutInflater) = override fun inflate(layoutInflater: LayoutInflater) =
@ -72,7 +68,7 @@ class RecaptchaDialog(
b.image8.isChecked = false b.image8.isChecked = false
} }
override fun onDismiss() { override suspend fun onDismiss() {
if (!success) if (!success)
onFailure?.invoke() onFailure?.invoke()
} }

View File

@ -20,10 +20,7 @@ class RecaptchaPromptDialog(
private val onSuccess: (recaptchaCode: String) -> Unit, private val onSuccess: (recaptchaCode: String) -> Unit,
private val onCancel: (() -> Unit)?, private val onCancel: (() -> Unit)?,
private val onServerError: (() -> Unit)? = null, private val onServerError: (() -> Unit)? = null,
onShowListener: ((tag: String) -> Unit)? = null, ) : BindingDialog<RecaptchaViewBinding>(activity) {
onDismissListener: ((tag: String) -> Unit)? = null,
) : BindingDialog<RecaptchaViewBinding>(activity, onShowListener, onDismissListener) {
override val TAG = "RecaptchaPromptDialog"
override fun getTitleRes(): Int? = null override fun getTitleRes(): Int? = null
override fun inflate(layoutInflater: LayoutInflater) = override fun inflate(layoutInflater: LayoutInflater) =
@ -57,7 +54,7 @@ class RecaptchaPromptDialog(
b.progress.visibility = View.GONE b.progress.visibility = View.GONE
success = true success = true
onSuccess(recaptchaCode) onSuccess(recaptchaCode)
dialog.dismiss() dismiss()
}, },
onFailure = { onFailure = {
b.checkbox.background = checkboxBackground b.checkbox.background = checkboxBackground
@ -69,7 +66,7 @@ class RecaptchaPromptDialog(
} }
} }
override fun onDismiss() { override suspend fun onDismiss() {
if (!success) if (!success)
onCancel?.invoke() onCancel?.invoke()
} }

View File

@ -5,19 +5,16 @@
package pl.szczodrzynski.edziennik.ui.debug package pl.szczodrzynski.edziennik.ui.debug
import android.os.Bundle import android.os.Bundle
import android.os.Process
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.core.widget.doAfterTextChanged import androidx.core.widget.doAfterTextChanged
import androidx.sqlite.db.SimpleSQLiteQuery import androidx.sqlite.db.SimpleSQLiteQuery
import com.chuckerteam.chucker.api.Chucker import com.chuckerteam.chucker.api.Chucker
import com.chuckerteam.chucker.api.Chucker.SCREEN_HTTP import com.chuckerteam.chucker.api.Chucker.SCREEN_HTTP
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import pl.szczodrzynski.edziennik.App import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.MainActivity import pl.szczodrzynski.edziennik.MainActivity
import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.data.api.szkolny.interceptor.SignatureInterceptor import pl.szczodrzynski.edziennik.data.api.szkolny.interceptor.SignatureInterceptor
import pl.szczodrzynski.edziennik.data.config.Config import pl.szczodrzynski.edziennik.data.config.Config
import pl.szczodrzynski.edziennik.data.db.entity.EventType.Companion.SOURCE_DEFAULT import pl.szczodrzynski.edziennik.data.db.entity.EventType.Companion.SOURCE_DEFAULT
@ -34,9 +31,9 @@ import pl.szczodrzynski.edziennik.ext.startCoroutineTimer
import pl.szczodrzynski.edziennik.ext.takeValue import pl.szczodrzynski.edziennik.ext.takeValue
import pl.szczodrzynski.edziennik.ui.base.fragment.BaseFragment import pl.szczodrzynski.edziennik.ui.base.fragment.BaseFragment
import pl.szczodrzynski.edziennik.ui.dialogs.ProfileRemoveDialog import pl.szczodrzynski.edziennik.ui.dialogs.ProfileRemoveDialog
import pl.szczodrzynski.edziennik.ui.dialogs.RestartDialog
import pl.szczodrzynski.edziennik.utils.TextInputDropDown import pl.szczodrzynski.edziennik.utils.TextInputDropDown
import pl.szczodrzynski.fslogin.decode import pl.szczodrzynski.fslogin.decode
import kotlin.system.exitProcess
class LabPageFragment : BaseFragment<LabFragmentBinding, AppCompatActivity>( class LabPageFragment : BaseFragment<LabFragmentBinding, AppCompatActivity>(
inflater = LabFragmentBinding::inflate, inflater = LabFragmentBinding::inflate,
@ -100,16 +97,7 @@ class LabPageFragment : BaseFragment<LabFragmentBinding, AppCompatActivity>(
b.chucker.onChange { _, isChecked -> b.chucker.onChange { _, isChecked ->
app.config.enableChucker = isChecked app.config.enableChucker = isChecked
App.enableChucker = isChecked App.enableChucker = isChecked
MaterialAlertDialogBuilder(activity) RestartDialog(activity).show()
.setTitle("Restart")
.setMessage("Wymagany restart aplikacji")
.setPositiveButton(R.string.ok) { _, _ ->
Process.killProcess(Process.myPid())
Runtime.getRuntime().exit(0)
exitProcess(0)
}
.setCancelable(false)
.show()
} }
if (App.enableChucker) { if (App.enableChucker) {
@ -122,16 +110,7 @@ class LabPageFragment : BaseFragment<LabFragmentBinding, AppCompatActivity>(
b.disableDebug.onClick { b.disableDebug.onClick {
app.config.devMode = false app.config.devMode = false
App.devMode = false App.devMode = false
MaterialAlertDialogBuilder(activity) RestartDialog(activity).show()
.setTitle("Restart")
.setMessage("Wymagany restart aplikacji")
.setPositiveButton(R.string.ok) { _, _ ->
Process.killProcess(Process.myPid())
Runtime.getRuntime().exit(0)
exitProcess(0)
}
.setCancelable(false)
.show()
} }
b.unarchive.onClick { b.unarchive.onClick {

View File

@ -8,7 +8,6 @@ import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.gson.JsonArray import com.google.gson.JsonArray
import com.google.gson.JsonObject import com.google.gson.JsonObject
import com.google.gson.JsonParser import com.google.gson.JsonParser
@ -18,6 +17,7 @@ import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.data.api.models.ApiError import pl.szczodrzynski.edziennik.data.api.models.ApiError
import pl.szczodrzynski.edziennik.databinding.TemplateListPageFragmentBinding import pl.szczodrzynski.edziennik.databinding.TemplateListPageFragmentBinding
import pl.szczodrzynski.edziennik.ext.* import pl.szczodrzynski.edziennik.ext.*
import pl.szczodrzynski.edziennik.ui.base.dialog.SimpleDialog
import pl.szczodrzynski.edziennik.ui.base.fragment.BaseFragment import pl.szczodrzynski.edziennik.ui.base.fragment.BaseFragment
import pl.szczodrzynski.edziennik.ui.login.LoginActivity import pl.szczodrzynski.edziennik.ui.login.LoginActivity
import pl.szczodrzynski.edziennik.utils.SimpleDividerItemDecoration import pl.szczodrzynski.edziennik.utils.SimpleDividerItemDecoration
@ -73,17 +73,16 @@ class LabProfileFragment : BaseFragment<TemplateListPageFragmentBinding, AppComp
objVal.isBoolean -> objVal.asBoolean.toString() objVal.isBoolean -> objVal.asBoolean.toString()
else -> objVal.asString else -> objVal.asString
} }
is Enum<*> -> objVal.toString() is Enum<*> -> objVal.toString()
else -> objVal.toString() else -> objVal.toString()
} }
MaterialAlertDialogBuilder(activity) SimpleDialog<Unit>(activity) {
.setTitle(item.key) title(item.key)
.input( input(hint = "value", value = value)
hint = "value", positive(R.string.ok) {
value = value, val input = getInput()?.text?.toString() ?: return@positive
positiveButton = R.string.ok,
positiveListener = { _, input ->
when (parent) { when (parent) {
is JsonObject -> { is JsonObject -> {
val v = objVal as JsonPrimitive val v = objVal as JsonPrimitive
@ -102,6 +101,7 @@ class LabProfileFragment : BaseFragment<TemplateListPageFragmentBinding, AppComp
else else
app.config[objName] = input app.config[objName] = input
} }
else -> { else -> {
val field = parent::class.java.getDeclaredField(objName) val field = parent::class.java.getDeclaredField(objName)
field.isAccessible = true field.isAccessible = true
@ -127,12 +127,9 @@ class LabProfileFragment : BaseFragment<TemplateListPageFragmentBinding, AppComp
} }
showJson() showJson()
}
return@input true negative(R.string.cancel)
} }.show()
)
.setNegativeButton(R.string.cancel, null)
.show()
} }
catch (e: Exception) { catch (e: Exception) {
if (activity is MainActivity) if (activity is MainActivity)

View File

@ -6,24 +6,19 @@ package pl.szczodrzynski.edziennik.ui.dialogs
import android.view.LayoutInflater import android.view.LayoutInflater
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import kotlinx.coroutines.Job
import pl.szczodrzynski.edziennik.MainActivity import pl.szczodrzynski.edziennik.MainActivity
import pl.szczodrzynski.edziennik.R import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.databinding.DialogBellSyncBinding import pl.szczodrzynski.edziennik.databinding.DialogBellSyncBinding
import pl.szczodrzynski.edziennik.ext.resolveDrawable import pl.szczodrzynski.edziennik.ext.resolveDrawable
import pl.szczodrzynski.edziennik.ext.startCoroutineTimer import pl.szczodrzynski.edziennik.ext.startCoroutineTimer
import pl.szczodrzynski.edziennik.ui.base.dialog.BindingDialog import pl.szczodrzynski.edziennik.ui.base.dialog.BindingDialog
import pl.szczodrzynski.edziennik.ui.base.dialog.SimpleDialog
import pl.szczodrzynski.edziennik.utils.models.Time import pl.szczodrzynski.edziennik.utils.models.Time
class BellSyncDialog( class BellSyncDialog(
activity: AppCompatActivity, activity: AppCompatActivity,
private val bellTime: Time, private val bellTime: Time,
onShowListener: ((tag: String) -> Unit)? = null, ) : BindingDialog<DialogBellSyncBinding>(activity) {
onDismissListener: ((tag: String) -> Unit)? = null,
) : BindingDialog<DialogBellSyncBinding>(activity, onShowListener, onDismissListener) {
override val TAG = "BellSyncDialog"
override fun getTitleRes() = R.string.bell_sync_title override fun getTitleRes() = R.string.bell_sync_title
override fun inflate(layoutInflater: LayoutInflater) = override fun inflate(layoutInflater: LayoutInflater) =
@ -31,8 +26,6 @@ class BellSyncDialog(
override fun getNeutralButtonText() = R.string.cancel override fun getNeutralButtonText() = R.string.cancel
private var counterJob: Job? = null
private val actualBellDiff: Pair<Time, Int> private val actualBellDiff: Pair<Time, Int>
get() { get() {
val now = Time.getNow() val now = Time.getNow()
@ -48,30 +41,25 @@ class BellSyncDialog(
app.config.timetable.bellSyncDiff = bellDiff app.config.timetable.bellSyncDiff = bellDiff
app.config.timetable.bellSyncMultiplier = multiplier app.config.timetable.bellSyncMultiplier = multiplier
MaterialAlertDialogBuilder(activity) SimpleDialog<Unit>(activity) {
.setTitle(R.string.bell_sync_title) title(R.string.bell_sync_title)
.setMessage(app.getString(R.string.bell_sync_results, bellDiffText)) message(app.getString(R.string.bell_sync_results, bellDiffText))
.setPositiveButton(R.string.ok) { resultsDialog, _ -> positive(R.string.ok) {
resultsDialog.dismiss() this@BellSyncDialog.dismiss()
dialog.dismiss()
if (activity is MainActivity) activity.reloadTarget() if (activity is MainActivity) activity.reloadTarget()
} }
.show() }.show()
} }
if (Time.diff(Time.getNow(), bellTime) > Time(2, 0, 0)) { // Easter egg ^^ if (Time.diff(Time.getNow(), bellTime) > Time(2, 0, 0)) { // Easter egg ^^
b.bellSyncButton.setImageDrawable(R.drawable.ic_bell_wtf.resolveDrawable(app)) // wtf b.bellSyncButton.setImageDrawable(R.drawable.ic_bell_wtf.resolveDrawable(app)) // wtf
} }
counterJob = startCoroutineTimer(repeatMillis = 500) { startCoroutineTimer(repeatMillis = 500) {
val (bellDiff, multiplier) = actualBellDiff val (bellDiff, multiplier) = actualBellDiff
val bellDiffText = (if (multiplier == -1) '-' else '+') + bellDiff.stringHMS val bellDiffText = (if (multiplier == -1) '-' else '+') + bellDiff.stringHMS
b.bellSyncHowto.text = b.bellSyncHowto.text =
app.getString(R.string.bell_sync_howto, bellTime.stringHM, bellDiffText) app.getString(R.string.bell_sync_howto, bellTime.stringHM, bellDiffText)
} }
} }
override fun onDismiss() {
counterJob?.cancel()
}
} }

View File

@ -6,29 +6,26 @@ package pl.szczodrzynski.edziennik.ui.dialogs
import android.view.LayoutInflater import android.view.LayoutInflater
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import com.google.android.material.dialog.MaterialAlertDialogBuilder import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.* import kotlinx.coroutines.withContext
import pl.szczodrzynski.edziennik.App import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.MainActivity import pl.szczodrzynski.edziennik.MainActivity
import pl.szczodrzynski.edziennik.R import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.data.db.entity.Lesson import pl.szczodrzynski.edziennik.data.db.entity.Lesson
import pl.szczodrzynski.edziennik.databinding.DialogBellSyncTimeChooseBinding import pl.szczodrzynski.edziennik.databinding.DialogBellSyncTimeChooseBinding
import pl.szczodrzynski.edziennik.ui.base.dialog.BindingDialog import pl.szczodrzynski.edziennik.ui.base.dialog.BindingDialog
import pl.szczodrzynski.edziennik.ui.base.dialog.SimpleDialog
import pl.szczodrzynski.edziennik.utils.TextInputDropDown import pl.szczodrzynski.edziennik.utils.TextInputDropDown
import pl.szczodrzynski.edziennik.utils.models.Date import pl.szczodrzynski.edziennik.utils.models.Date
import pl.szczodrzynski.edziennik.utils.models.Time import pl.szczodrzynski.edziennik.utils.models.Time
class BellSyncTimeChooseDialog( class BellSyncTimeChooseDialog(
activity: AppCompatActivity, activity: AppCompatActivity,
onShowListener: ((tag: String) -> Unit)? = null, ) : BindingDialog<DialogBellSyncTimeChooseBinding>(activity) {
onDismissListener: ((tag: String) -> Unit)? = null,
) : BindingDialog<DialogBellSyncTimeChooseBinding>(activity, onShowListener, onDismissListener) {
companion object { companion object {
private const val MAX_DIFF_MINUTES = 10 private const val MAX_DIFF_MINUTES = 10
} }
override val TAG = "BellSyncTimeChooseDialog"
override fun getTitleRes() = R.string.bell_sync_title override fun getTitleRes() = R.string.bell_sync_title
override fun inflate(layoutInflater: LayoutInflater) = override fun inflate(layoutInflater: LayoutInflater) =
DialogBellSyncTimeChooseBinding.inflate(layoutInflater) DialogBellSyncTimeChooseBinding.inflate(layoutInflater)
@ -37,8 +34,6 @@ class BellSyncTimeChooseDialog(
override fun getNeutralButtonText() = R.string.reset override fun getNeutralButtonText() = R.string.reset
override fun getNegativeButtonText() = R.string.cancel override fun getNegativeButtonText() = R.string.cancel
override suspend fun onShow() = Unit
private val today = Date.getToday() private val today = Date.getToday()
private val selectedTime: Time? private val selectedTime: Time?
get() = b.timeDropdown.selected?.tag as Time? get() = b.timeDropdown.selected?.tag as Time?
@ -51,20 +46,19 @@ class BellSyncTimeChooseDialog(
} }
override suspend fun onNeutralClick(): Boolean { override suspend fun onNeutralClick(): Boolean {
MaterialAlertDialogBuilder(activity) SimpleDialog<Unit>(activity) {
.setTitle(R.string.bell_sync_title) title(R.string.bell_sync_title)
.setMessage(R.string.bell_sync_reset_confirm) message(R.string.bell_sync_reset_confirm)
.setPositiveButton(R.string.yes) { dialog, _ -> positive(R.string.yes) {
app.config.timetable.bellSyncDiff = null app.config.timetable.bellSyncDiff = null
app.config.timetable.bellSyncMultiplier = 0 app.config.timetable.bellSyncMultiplier = 0
this@BellSyncTimeChooseDialog.dismiss()
dialog.dismiss() this@BellSyncTimeChooseDialog.show()
reload()
if (activity is MainActivity) if (activity is MainActivity)
activity.reloadTarget() activity.reloadTarget()
} }
.setNegativeButton(R.string.no, null) negative(R.string.no)
.show() }.show()
return NO_DISMISS return NO_DISMISS
} }
@ -127,11 +121,11 @@ class BellSyncTimeChooseDialog(
if (!checkForLessons(timeItems.map { it.tag as Time })) { if (!checkForLessons(timeItems.map { it.tag as Time })) {
/* Synchronization not possible */ /* Synchronization not possible */
MaterialAlertDialogBuilder(activity) SimpleDialog<Unit>(activity) {
.setTitle(R.string.bell_sync_title) title(R.string.bell_sync_title)
.setMessage(R.string.bell_sync_cannot_now) message(R.string.bell_sync_cannot_now)
.setPositiveButton(R.string.ok, null) positive(R.string.ok)
.show() }.show()
return false return false
} else { } else {
b.timeDropdown.clear() b.timeDropdown.clear()

View File

@ -15,17 +15,11 @@ import pl.szczodrzynski.edziennik.utils.html.BetterHtml
class ChangelogDialog( class ChangelogDialog(
activity: AppCompatActivity, activity: AppCompatActivity,
onShowListener: ((tag: String) -> Unit)? = null, ) : ViewDialog<ScrollView>(activity) {
onDismissListener: ((tag: String) -> Unit)? = null,
) : ViewDialog<ScrollView>(activity, onShowListener, onDismissListener) {
override val TAG = "ChangelogDialog"
override fun getTitleRes() = R.string.whats_new override fun getTitleRes() = R.string.whats_new
override fun getPositiveButtonText() = R.string.close override fun getPositiveButtonText() = R.string.close
override suspend fun onShow() = Unit
override fun getRootView(): ScrollView { override fun getRootView(): ScrollView {
val textView = TextView(activity) val textView = TextView(activity)
textView.setPadding(24.dp, 24.dp, 24.dp, 0) textView.setPadding(24.dp, 24.dp, 24.dp, 0)

View File

@ -19,11 +19,7 @@ class ErrorDetailsDialog(
activity: AppCompatActivity, activity: AppCompatActivity,
private val errors: List<ApiError>, private val errors: List<ApiError>,
private val titleRes: Int = R.string.dialog_error_details_title, private val titleRes: Int = R.string.dialog_error_details_title,
onShowListener: ((tag: String) -> Unit)? = null, ) : BaseDialog<Any>(activity) {
onDismissListener: ((tag: String) -> Unit)? = null,
) : BaseDialog<Any>(activity, onShowListener, onDismissListener) {
override val TAG = "ErrorDetailsDialog"
override fun getTitleRes() = titleRes override fun getTitleRes() = titleRes
override fun getMessage() = errors.map { override fun getMessage() = errors.map {
@ -43,8 +39,6 @@ class ErrorDetailsDialog(
override fun getPositiveButtonText() = R.string.close override fun getPositiveButtonText() = R.string.close
override fun getNeutralButtonText() = R.string.report override fun getNeutralButtonText() = R.string.report
override suspend fun onShow() = Unit
private val api by lazy { SzkolnyApi(activity.applicationContext as App) } private val api by lazy { SzkolnyApi(activity.applicationContext as App) }
override suspend fun onBeforeShow(): Boolean { override suspend fun onBeforeShow(): Boolean {

View File

@ -18,11 +18,7 @@ class ProfileRemoveDialog(
val profileName: String, val profileName: String,
val noProfileRemoval: Boolean = false, val noProfileRemoval: Boolean = false,
val onRemove: (() -> Unit)? = null, val onRemove: (() -> Unit)? = null,
onShowListener: ((tag: String) -> Unit)? = null, ) : BaseDialog<Any>(activity) {
onDismissListener: ((tag: String) -> Unit)? = null,
) : BaseDialog<Any>(activity, onShowListener, onDismissListener) {
override val TAG = "ProfileRemoveDialog"
override fun getTitleRes() = R.string.profile_menu_remove_confirm override fun getTitleRes() = R.string.profile_menu_remove_confirm
override fun getMessageFormat() = override fun getMessageFormat() =
@ -35,8 +31,6 @@ class ProfileRemoveDialog(
override fun getPositiveButtonText() = R.string.remove override fun getPositiveButtonText() = R.string.remove
override fun getNeutralButtonText() = R.string.cancel override fun getNeutralButtonText() = R.string.cancel
override suspend fun onShow() = Unit
override suspend fun onPositiveClick(): Boolean { override suspend fun onPositiveClick(): Boolean {
withContext(Dispatchers.Default) { withContext(Dispatchers.Default) {
val profileObject = app.db.profileDao().getByIdNow(profileId) ?: return@withContext val profileObject = app.db.profileDao().getByIdNow(profileId) ?: return@withContext

View File

@ -13,11 +13,7 @@ import pl.szczodrzynski.edziennik.ui.base.dialog.ViewDialog
class QrScannerDialog( class QrScannerDialog(
activity: AppCompatActivity, activity: AppCompatActivity,
val onCodeScanned: (text: String) -> Unit, val onCodeScanned: (text: String) -> Unit,
onShowListener: ((tag: String) -> Unit)? = null, ) : ViewDialog<ZXingScannerView>(activity) {
onDismissListener: ((tag: String) -> Unit)? = null,
) : ViewDialog<ZXingScannerView>(activity, onShowListener, onDismissListener) {
override val TAG = "QrScannerDialog"
override fun getTitleRes() = R.string.qr_scanner_dialog_title override fun getTitleRes() = R.string.qr_scanner_dialog_title
override fun getPositiveButtonText() = R.string.close override fun getPositiveButtonText() = R.string.close
@ -31,13 +27,13 @@ class QrScannerDialog(
override suspend fun onShow() { override suspend fun onShow() {
root.setResultHandler { root.setResultHandler {
root.stopCamera() root.stopCamera()
dialog.dismiss() dismiss()
onCodeScanned(it.text) onCodeScanned(it.text)
} }
root.startCamera() root.startCamera()
} }
override fun onDismiss() { override suspend fun onDismiss() {
root.stopCamera() root.stopCamera()
} }
} }

View File

@ -0,0 +1,27 @@
/*
* Copyright (c) Kuba Szczodrzyński 2024-7-5.
*/
package pl.szczodrzynski.edziennik.ui.dialogs
import android.os.Process
import androidx.appcompat.app.AppCompatActivity
import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.ui.base.dialog.BaseDialog
import kotlin.system.exitProcess
class RestartDialog(
activity: AppCompatActivity,
) : BaseDialog<Unit>(activity) {
override fun getTitle() = "Restart"
override fun getMessage() = "Wymagany restart aplikacji"
override fun isCancelable() = false
override fun getPositiveButtonText() = R.string.ok
override suspend fun onPositiveClick(): Boolean {
Process.killProcess(Process.myPid())
Runtime.getRuntime().exit(0)
exitProcess(0)
}
}

View File

@ -22,11 +22,7 @@ class StyledTextDialog(
activity: AppCompatActivity, activity: AppCompatActivity,
val initialText: Editable?, val initialText: Editable?,
val onSuccess: (text: Editable) -> Unit, val onSuccess: (text: Editable) -> Unit,
onShowListener: ((tag: String) -> Unit)? = null, ) : BindingDialog<StyledTextDialogBinding>(activity) {
onDismissListener: ((tag: String) -> Unit)? = null,
) : BindingDialog<StyledTextDialogBinding>(activity, onShowListener, onDismissListener) {
override val TAG = "StyledTextDialog"
private lateinit var config: StylingConfig private lateinit var config: StylingConfig

View File

@ -15,16 +15,7 @@ import pl.szczodrzynski.edziennik.ui.base.dialog.ConfigDialog
class AgendaConfigDialog( class AgendaConfigDialog(
activity: AppCompatActivity, activity: AppCompatActivity,
reloadOnDismiss: Boolean = true, reloadOnDismiss: Boolean = true,
onShowListener: ((tag: String) -> Unit)? = null, ) : ConfigDialog<DialogConfigAgendaBinding>(activity, reloadOnDismiss) {
onDismissListener: ((tag: String) -> Unit)? = null,
) : ConfigDialog<DialogConfigAgendaBinding>(
activity,
reloadOnDismiss,
onShowListener,
onDismissListener,
) {
override val TAG = "AgendaConfigDialog"
override fun getTitleRes() = R.string.menu_agenda_config override fun getTitleRes() = R.string.menu_agenda_config
override fun inflate(layoutInflater: LayoutInflater) = override fun inflate(layoutInflater: LayoutInflater) =
@ -51,8 +42,6 @@ class AgendaConfigDialog(
b.eventSharingEnabled.isChecked = enabled b.eventSharingEnabled.isChecked = enabled
b.shareByDefault.isEnabled = enabled b.shareByDefault.isEnabled = enabled
}, },
onShowListener,
onDismissListener,
) )
if (isChecked) if (isChecked)
dialog.showEnableDialog() dialog.showEnableDialog()

View File

@ -10,10 +10,7 @@ import pl.szczodrzynski.edziennik.ui.base.dialog.BaseDialog
class AppLanguageDialog( class AppLanguageDialog(
activity: AppCompatActivity, activity: AppCompatActivity,
onShowListener: ((tag: String) -> Unit)? = null, ) : BaseDialog<Any>(activity) {
onDismissListener: ((tag: String) -> Unit)? = null,
) : BaseDialog<Any>(activity, onShowListener, onDismissListener) {
override val TAG = "AppLanguageDialog"
override fun getTitleRes() = R.string.app_language_dialog_title override fun getTitleRes() = R.string.app_language_dialog_title
override fun getMessage() = activity.getString(R.string.app_language_dialog_text) override fun getMessage() = activity.getString(R.string.app_language_dialog_text)
@ -29,8 +26,6 @@ class AppLanguageDialog(
override fun getDefaultSelectedItem() = app.config.ui.language override fun getDefaultSelectedItem() = app.config.ui.language
override suspend fun onShow() = Unit
override suspend fun onPositiveClick(): Boolean { override suspend fun onPositiveClick(): Boolean {
val language = getSingleSelection() as? String ?: return DISMISS val language = getSingleSelection() as? String ?: return DISMISS
if (language.isEmpty()) if (language.isEmpty())

View File

@ -14,16 +14,7 @@ import pl.szczodrzynski.edziennik.ui.base.dialog.ConfigDialog
class AttendanceConfigDialog( class AttendanceConfigDialog(
activity: AppCompatActivity, activity: AppCompatActivity,
reloadOnDismiss: Boolean = true, reloadOnDismiss: Boolean = true,
onShowListener: ((tag: String) -> Unit)? = null, ) : ConfigDialog<AttendanceConfigDialogBinding>(activity, reloadOnDismiss) {
onDismissListener: ((tag: String) -> Unit)? = null,
) : ConfigDialog<AttendanceConfigDialogBinding>(
activity,
reloadOnDismiss,
onShowListener,
onDismissListener,
) {
override val TAG = "AttendanceConfigDialog"
override fun getTitleRes() = R.string.menu_attendance_config override fun getTitleRes() = R.string.menu_attendance_config
override fun inflate(layoutInflater: LayoutInflater) = override fun inflate(layoutInflater: LayoutInflater) =

View File

@ -4,32 +4,33 @@
package pl.szczodrzynski.edziennik.ui.dialogs.settings package pl.szczodrzynski.edziennik.ui.dialogs.settings
import android.view.LayoutInflater import android.text.Editable
import android.text.InputType
import android.widget.Toast import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.widget.addTextChangedListener import com.google.android.material.textfield.TextInputEditText
import pl.szczodrzynski.edziennik.R import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.databinding.DialogEditTextBinding import pl.szczodrzynski.edziennik.ui.base.dialog.BaseDialog
import pl.szczodrzynski.edziennik.ui.base.dialog.BindingDialog
import pl.szczodrzynski.edziennik.utils.models.Time import pl.szczodrzynski.edziennik.utils.models.Time
class BellSyncConfigDialog( class BellSyncConfigDialog(
activity: AppCompatActivity, activity: AppCompatActivity,
private val onChangeListener: (() -> Unit)? = null, private val onChangeListener: (() -> Unit)? = null,
onShowListener: ((tag: String) -> Unit)? = null, ) : BaseDialog<Unit>(activity) {
onDismissListener: ((tag: String) -> Unit)? = null,
) : BindingDialog<DialogEditTextBinding>(activity, onShowListener, onDismissListener) {
override val TAG = "BellSyncConfigDialog"
override fun getTitleRes() = R.string.bell_sync_title override fun getTitleRes() = R.string.bell_sync_title
override fun inflate(layoutInflater: LayoutInflater) = override fun getMessageRes() = R.string.bell_sync_adjust_content
DialogEditTextBinding.inflate(layoutInflater)
override fun getPositiveButtonText() = R.string.ok override fun getPositiveButtonText() = R.string.ok
override fun getNeutralButtonText() = R.string.reset override fun getNeutralButtonText() = R.string.reset
override fun getNegativeButtonText() = R.string.cancel override fun getNegativeButtonText() = R.string.cancel
override fun getInputType() = InputType.TYPE_CLASS_TEXT
override fun getInputHint() = "±H:MM:SS"
override fun getInputValue() = app.config.timetable.bellSyncDiff?.let {
(if (app.config.timetable.bellSyncMultiplier == -1) "-" else "+") + it.stringHMS
} ?: "+0:00:00"
private fun parse(input: String): Pair<Time, Int>? { private fun parse(input: String): Pair<Time, Int>? {
if (input.length < 8) { if (input.length < 8) {
return null return null
@ -47,24 +48,17 @@ class BellSyncConfigDialog(
return time to multiplier return time to multiplier
} }
override suspend fun onShow() { override suspend fun onInputTextChanged(input: TextInputEditText, text: Editable?) {
b.title.setText(R.string.bell_sync_adjust_content) val value = text?.toString()
b.text1.hint = "±H:MM:SS" input.error =
b.text1.setText(app.config.timetable.bellSyncDiff?.let { if (value != null && parse(value) == null)
(if (app.config.timetable.bellSyncMultiplier == -1) "-" else "+") + it.stringHMS activity.getString(R.string.bell_sync_adjust_error)
} ?: "+0:00:00") else
b.text1.addTextChangedListener { text -> null
val input = text?.toString()
b.textInputLayout.error =
if (input != null && parse(input) == null)
activity.getString(R.string.bell_sync_adjust_error)
else
null
}
} }
override suspend fun onPositiveClick(): Boolean { override suspend fun onPositiveClick(): Boolean {
val input = b.text1.text?.toString() ?: return NO_DISMISS val input = getInput()?.text?.toString() ?: return NO_DISMISS
val parsed = parse(input) val parsed = parse(input)
if (parsed == null) { if (parsed == null) {
Toast.makeText(activity, R.string.bell_sync_adjust_error, Toast.LENGTH_SHORT).show() Toast.makeText(activity, R.string.bell_sync_adjust_error, Toast.LENGTH_SHORT).show()

View File

@ -8,15 +8,8 @@ import android.annotation.SuppressLint
import android.view.LayoutInflater import android.view.LayoutInflater
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.isVisible import androidx.core.view.isVisible
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import it.sephiroth.android.library.numberpicker.doOnStopTrackingTouch import it.sephiroth.android.library.numberpicker.doOnStopTrackingTouch
import pl.szczodrzynski.edziennik.R 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.base.dialog.ConfigDialog
import pl.szczodrzynski.edziennik.core.manager.GradesManager.Companion.COLOR_MODE_DEFAULT import pl.szczodrzynski.edziennik.core.manager.GradesManager.Companion.COLOR_MODE_DEFAULT
import pl.szczodrzynski.edziennik.core.manager.GradesManager.Companion.COLOR_MODE_WEIGHTED import pl.szczodrzynski.edziennik.core.manager.GradesManager.Companion.COLOR_MODE_WEIGHTED
import pl.szczodrzynski.edziennik.core.manager.GradesManager.Companion.ORDER_BY_DATE_DESC import pl.szczodrzynski.edziennik.core.manager.GradesManager.Companion.ORDER_BY_DATE_DESC
@ -26,20 +19,18 @@ import pl.szczodrzynski.edziennik.core.manager.GradesManager.Companion.YEAR_1_AV
import pl.szczodrzynski.edziennik.core.manager.GradesManager.Companion.YEAR_1_SEM_2_AVG import pl.szczodrzynski.edziennik.core.manager.GradesManager.Companion.YEAR_1_SEM_2_AVG
import pl.szczodrzynski.edziennik.core.manager.GradesManager.Companion.YEAR_1_SEM_2_SEM import pl.szczodrzynski.edziennik.core.manager.GradesManager.Companion.YEAR_1_SEM_2_SEM
import pl.szczodrzynski.edziennik.core.manager.GradesManager.Companion.YEAR_ALL_GRADES import pl.szczodrzynski.edziennik.core.manager.GradesManager.Companion.YEAR_ALL_GRADES
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.base.dialog.ConfigDialog
import pl.szczodrzynski.edziennik.ui.base.dialog.SimpleDialog
class GradesConfigDialog( class GradesConfigDialog(
activity: AppCompatActivity, activity: AppCompatActivity,
reloadOnDismiss: Boolean = true, reloadOnDismiss: Boolean = true,
onShowListener: ((tag: String) -> Unit)? = null, ) : ConfigDialog<DialogConfigGradesBinding>(activity, reloadOnDismiss) {
onDismissListener: ((tag: String) -> Unit)? = null,
) : ConfigDialog<DialogConfigGradesBinding>(
activity,
reloadOnDismiss,
onShowListener,
onDismissListener,
) {
override val TAG = "GradesConfigDialog"
override fun getTitleRes() = R.string.menu_grades_config override fun getTitleRes() = R.string.menu_grades_config
override fun inflate(layoutInflater: LayoutInflater) = override fun inflate(layoutInflater: LayoutInflater) =
@ -155,11 +146,11 @@ class GradesConfigDialog(
} }
b.averageWithoutWeightHelp.onClick { b.averageWithoutWeightHelp.onClick {
MaterialAlertDialogBuilder(activity) SimpleDialog<Unit>(activity) {
.setTitle(R.string.grades_config_average_without_weight) title(R.string.grades_config_average_without_weight)
.setMessage(R.string.grades_config_average_without_weight_message) message(R.string.grades_config_average_without_weight_message)
.setPositiveButton(R.string.ok, null) positive(R.string.ok)
.show() }.show()
} }
} }
} }

View File

@ -13,16 +13,7 @@ import pl.szczodrzynski.edziennik.ui.base.dialog.ConfigDialog
class MessagesConfigDialog( class MessagesConfigDialog(
activity: AppCompatActivity, activity: AppCompatActivity,
reloadOnDismiss: Boolean = true, reloadOnDismiss: Boolean = true,
onShowListener: ((tag: String) -> Unit)? = null, ) : ConfigDialog<MessagesConfigDialogBinding>(activity, reloadOnDismiss) {
onDismissListener: ((tag: String) -> Unit)? = null,
) : ConfigDialog<MessagesConfigDialogBinding>(
activity,
reloadOnDismiss,
onShowListener,
onDismissListener,
) {
override val TAG = "MessagesConfigDialog"
override fun getTitleRes() = R.string.menu_messages_config override fun getTitleRes() = R.string.menu_messages_config
override fun inflate(layoutInflater: LayoutInflater) = override fun inflate(layoutInflater: LayoutInflater) =

View File

@ -15,11 +15,7 @@ import pl.szczodrzynski.edziennik.ui.base.dialog.BaseDialog
class MiniMenuConfigDialog( class MiniMenuConfigDialog(
activity: AppCompatActivity, activity: AppCompatActivity,
onShowListener: ((tag: String) -> Unit)? = null, ) : BaseDialog<NavTarget>(activity) {
onDismissListener: ((tag: String) -> Unit)? = null,
) : BaseDialog<NavTarget>(activity, onShowListener, onDismissListener) {
override val TAG = "BellSyncTimeChooseDialog"
override fun getTitleRes() = R.string.settings_theme_mini_drawer_buttons_dialog_title 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 getMessageRes() = R.string.settings_theme_mini_drawer_buttons_dialog_text
@ -39,8 +35,6 @@ class MiniMenuConfigDialog(
override fun getDefaultSelectedItems() = app.config.ui.miniMenuButtons override fun getDefaultSelectedItems() = app.config.ui.miniMenuButtons
override suspend fun onShow() = Unit
override suspend fun onPositiveClick(): Boolean { override suspend fun onPositiveClick(): Boolean {
app.config.ui.miniMenuButtons = getMultiSelection() app.config.ui.miniMenuButtons = getMultiSelection()
if (activity is MainActivity) { if (activity is MainActivity) {

View File

@ -5,19 +5,15 @@
package pl.szczodrzynski.edziennik.ui.dialogs.settings package pl.szczodrzynski.edziennik.ui.dialogs.settings
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import pl.szczodrzynski.edziennik.R import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.data.enums.NotificationType import pl.szczodrzynski.edziennik.data.enums.NotificationType
import pl.szczodrzynski.edziennik.ext.resolveString import pl.szczodrzynski.edziennik.ext.resolveString
import pl.szczodrzynski.edziennik.ui.base.dialog.BaseDialog import pl.szczodrzynski.edziennik.ui.base.dialog.BaseDialog
import pl.szczodrzynski.edziennik.ui.base.dialog.SimpleDialog
class NotificationFilterDialog( class NotificationFilterDialog(
activity: AppCompatActivity, activity: AppCompatActivity,
onShowListener: ((tag: String) -> Unit)? = null, ) : BaseDialog<NotificationType>(activity) {
onDismissListener: ((tag: String) -> Unit)? = null,
) : BaseDialog<NotificationType>(activity, onShowListener, onDismissListener) {
override val TAG = "NotificationFilterDialog"
override fun getTitleRes() = R.string.dialog_notification_filter_title override fun getTitleRes() = R.string.dialog_notification_filter_title
override fun getMessageRes() = R.string.dialog_notification_filter_text override fun getMessageRes() = R.string.dialog_notification_filter_text
@ -33,8 +29,6 @@ class NotificationFilterDialog(
.filter { it.enabledByDefault != null && it !in app.profile.config.sync.notificationFilter } .filter { it.enabledByDefault != null && it !in app.profile.config.sync.notificationFilter }
.toSet() .toSet()
override suspend fun onShow() = Unit
override suspend fun onPositiveClick(): Boolean { override suspend fun onPositiveClick(): Boolean {
val enabledTypes = getMultiSelection() val enabledTypes = getMultiSelection()
val disabledTypes = NotificationType.values() val disabledTypes = NotificationType.values()
@ -43,15 +37,15 @@ class NotificationFilterDialog(
if (disabledTypes.any { it.enabledByDefault == true }) { if (disabledTypes.any { it.enabledByDefault == true }) {
// warn user when he tries to disable some notifications // warn user when he tries to disable some notifications
MaterialAlertDialogBuilder(activity) SimpleDialog<Unit>(activity) {
.setTitle(R.string.are_you_sure) title(R.string.are_you_sure)
.setMessage(R.string.notification_filter_warning) message(R.string.notification_filter_warning)
.setPositiveButton(R.string.ok) { _, _ -> positive(R.string.ok) {
app.profile.config.sync.notificationFilter = disabledTypes app.profile.config.sync.notificationFilter = disabledTypes
dismiss() this@NotificationFilterDialog.dismiss()
} }
.setNegativeButton(R.string.cancel, null) negative(R.string.cancel)
.show() }.show()
return NO_DISMISS return NO_DISMISS
} }

View File

@ -22,11 +22,7 @@ class ProfileConfigDialog(
activity: MainActivity, activity: MainActivity,
private val profile: Profile, private val profile: Profile,
private val onProfileSaved: ((profile: Profile) -> Unit)? = null, private val onProfileSaved: ((profile: Profile) -> Unit)? = null,
onShowListener: ((tag: String) -> Unit)? = null, ) : BindingDialog<DialogProfileConfigBinding>(activity) {
onDismissListener: ((tag: String) -> Unit)? = null,
) : BindingDialog<DialogProfileConfigBinding>(activity, onShowListener, onDismissListener) {
override val TAG = "ProfileConfigDialog"
override fun getTitleRes(): Int? = null override fun getTitleRes(): Int? = null
override fun inflate(layoutInflater: LayoutInflater) = override fun inflate(layoutInflater: LayoutInflater) =
@ -48,7 +44,7 @@ class ProfileConfigDialog(
R.attr.alertDialogStyle, R.attr.alertDialogStyle,
R.style.MaterialAlertDialog_Material3 R.style.MaterialAlertDialog_Material3
) )
val surface = MaterialColors.getColor(activity, R.attr.colorSurface, TAG) val surface = MaterialColors.getColor(activity, R.attr.colorSurface, 0)
shape.setCornerSize(18.dp.toFloat()) shape.setCornerSize(18.dp.toFloat())
shape.initializeElevationOverlay(activity) shape.initializeElevationOverlay(activity)
shape.fillColor = ColorStateList.valueOf(surface) shape.fillColor = ColorStateList.valueOf(surface)
@ -79,12 +75,12 @@ class ProfileConfigDialog(
b.logoutButton.onClick { b.logoutButton.onClick {
ProfileRemoveDialog(activity, profile.id, profile.name) { ProfileRemoveDialog(activity, profile.id, profile.name) {
profileRemoved = true profileRemoved = true
dialog.dismiss() dismiss()
}.show() }.show()
} }
} }
override fun onDismiss() { override suspend fun onDismiss() {
if (!profileRemoved && profileChanged) { if (!profileRemoved && profileChanged) {
app.profileSave(profile) app.profileSave(profile)
onProfileSaved?.invoke(profile) onProfileSaved?.invoke(profile)

View File

@ -4,66 +4,39 @@
package pl.szczodrzynski.edziennik.ui.dialogs.settings package pl.szczodrzynski.edziennik.ui.dialogs.settings
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.timepicker.MaterialTimePicker import com.google.android.material.timepicker.MaterialTimePicker
import com.google.android.material.timepicker.TimeFormat import com.google.android.material.timepicker.TimeFormat
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.R
import pl.szczodrzynski.edziennik.ext.resolveString
import pl.szczodrzynski.edziennik.ui.base.dialog.BaseDialog
import pl.szczodrzynski.edziennik.utils.models.Time import pl.szczodrzynski.edziennik.utils.models.Time
import kotlin.coroutines.CoroutineContext
class QuietHoursConfigDialog( class QuietHoursConfigDialog(
val activity: AppCompatActivity, activity: AppCompatActivity,
val onChangeListener: (() -> Unit)? = null, val onChangeListener: (() -> Unit)? = null,
val onShowListener: ((tag: String) -> Unit)? = null, ) : BaseDialog<Int>(activity) {
val onDismissListener: ((tag: String) -> Unit)? = null
) : CoroutineScope {
companion object { companion object {
private const val TAG = "QuietHoursConfigDialog" private const val TAG = "QuietHoursConfigDialog"
} }
private lateinit var app: App override fun getTitleRes() = R.string.settings_sync_quiet_hours_dialog_title
private lateinit var dialog: AlertDialog override fun getNegativeButtonText() = R.string.cancel
private val job = Job() override fun getItems(): Map<CharSequence, Int> = mapOf(
override val coroutineContext: CoroutineContext R.string.settings_sync_quiet_hours_set_beginning.resolveString(activity) to 0,
get() = job + Dispatchers.Main R.string.settings_sync_quiet_hours_set_end.resolveString(activity) to 1,
)
// local variables go here override suspend fun onItemClick(item: Int): Boolean {
when (item) {
init { run { 0 -> configStartTime()
if (activity.isFinishing) 1 -> configEndTime()
return@run }
onShowListener?.invoke(TAG) return NO_DISMISS
app = activity.applicationContext as App }
dialog = MaterialAlertDialogBuilder(activity)
.setTitle(R.string.settings_sync_quiet_hours_dialog_title)
.setItems(arrayOf(
activity.getString(R.string.settings_sync_quiet_hours_set_beginning),
activity.getString(R.string.settings_sync_quiet_hours_set_end)
)) { dialog, which ->
when (which) {
0 -> configStartTime()
1 -> configEndTime()
}
dialog.dismiss()
}
.setNegativeButton(R.string.cancel, null)
.setOnDismissListener {
onDismissListener?.invoke(TAG)
}
.show()
}}
private fun configStartTime() { private fun configStartTime() {
onShowListener?.invoke(TAG + "Start")
val time = app.config.sync.quietHoursStart ?: return val time = app.config.sync.quietHoursStart ?: return
val picker = MaterialTimePicker.Builder() val picker = MaterialTimePicker.Builder()
.setTitleText(R.string.settings_sync_quiet_hours_set_beginning) .setTitleText(R.string.settings_sync_quiet_hours_set_beginning)
@ -78,14 +51,9 @@ class QuietHoursConfigDialog(
app.config.sync.quietHoursStart = Time(picker.hour, picker.minute, 0) app.config.sync.quietHoursStart = Time(picker.hour, picker.minute, 0)
onChangeListener?.invoke() onChangeListener?.invoke()
} }
picker.addOnDismissListener {
onDismissListener?.invoke(TAG + "Start")
}
} }
private fun configEndTime() { private fun configEndTime() {
onShowListener?.invoke(TAG + "End")
val time = app.config.sync.quietHoursEnd ?: return val time = app.config.sync.quietHoursEnd ?: return
val picker = MaterialTimePicker.Builder() val picker = MaterialTimePicker.Builder()
.setTitleText(R.string.settings_sync_quiet_hours_set_end) .setTitleText(R.string.settings_sync_quiet_hours_set_end)
@ -100,8 +68,5 @@ class QuietHoursConfigDialog(
app.config.sync.quietHoursEnd = Time(picker.hour, picker.minute, 0) app.config.sync.quietHoursEnd = Time(picker.hour, picker.minute, 0)
onChangeListener?.invoke() onChangeListener?.invoke()
} }
picker.addOnDismissListener {
onDismissListener?.invoke(TAG + "End")
}
} }
} }

View File

@ -4,9 +4,7 @@
package pl.szczodrzynski.edziennik.ui.dialogs.settings package pl.szczodrzynski.edziennik.ui.dialogs.settings
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
@ -17,6 +15,8 @@ import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.data.api.szkolny.SzkolnyApi import pl.szczodrzynski.edziennik.data.api.szkolny.SzkolnyApi
import pl.szczodrzynski.edziennik.data.api.task.AppSync import pl.szczodrzynski.edziennik.data.api.task.AppSync
import pl.szczodrzynski.edziennik.data.db.entity.Profile import pl.szczodrzynski.edziennik.data.db.entity.Profile
import pl.szczodrzynski.edziennik.ui.base.dialog.BaseDialog
import pl.szczodrzynski.edziennik.ui.base.dialog.SimpleDialog
import pl.szczodrzynski.edziennik.utils.html.BetterHtml import pl.szczodrzynski.edziennik.utils.html.BetterHtml
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
@ -24,15 +24,10 @@ class RegistrationConfigDialog(
val activity: AppCompatActivity, val activity: AppCompatActivity,
val profile: Profile, val profile: Profile,
val onChangeListener: (suspend (enabled: Boolean) -> Unit)? = null, val onChangeListener: (suspend (enabled: Boolean) -> Unit)? = null,
val onShowListener: ((tag: String) -> Unit)? = null,
val onDismissListener: ((tag: String) -> Unit)? = null
) : CoroutineScope { ) : CoroutineScope {
companion object {
private const val TAG = "RegistrationEnableDialog"
}
private lateinit var app: App private lateinit var app: App
private lateinit var dialog: AlertDialog private lateinit var dialog: BaseDialog<*>
private val job = Job() private val job = Job()
override val coroutineContext: CoroutineContext override val coroutineContext: CoroutineContext
@ -47,75 +42,55 @@ class RegistrationConfigDialog(
}} }}
fun showEventShareDialog() { fun showEventShareDialog() {
onShowListener?.invoke(TAG + "EventShare") dialog = SimpleDialog<Unit>(activity) {
dialog = MaterialAlertDialogBuilder(activity) title(R.string.registration_config_event_sharing_title)
.setTitle(R.string.registration_config_event_sharing_title) message(R.string.registration_config_event_sharing_text)
.setMessage(R.string.registration_config_event_sharing_text) positive(R.string.i_agree) {
.setPositiveButton(R.string.i_agree) { _, _ ->
enableRegistration() enableRegistration()
} }
.setNegativeButton(R.string.cancel, null) negative(R.string.cancel)
.setOnDismissListener { }.show()
onDismissListener?.invoke(TAG + "EventShare")
}
.show()
} }
fun showNoteShareDialog() { fun showNoteShareDialog() {
onShowListener?.invoke(TAG + "NoteShare") dialog = SimpleDialog<Unit>(activity) {
dialog = MaterialAlertDialogBuilder(activity) title(R.string.registration_config_note_sharing_title)
.setTitle(R.string.registration_config_note_sharing_title) message(R.string.registration_config_note_sharing_text)
.setMessage(R.string.registration_config_note_sharing_text) positive(R.string.i_agree) {
.setPositiveButton(R.string.i_agree) { _, _ ->
enableRegistration() enableRegistration()
} }
.setNegativeButton(R.string.cancel, null) negative(R.string.cancel)
.setOnDismissListener { }.show()
onDismissListener?.invoke(TAG + "NoteShare")
}
.show()
} }
fun showEnableDialog() { fun showEnableDialog() {
onShowListener?.invoke(TAG + "Enable") dialog = SimpleDialog<Unit>(activity) {
dialog = MaterialAlertDialogBuilder(activity) title(R.string.registration_config_title)
.setTitle(R.string.registration_config_title) message(BetterHtml.fromHtml(activity, R.string.registration_config_enable_text))
.setMessage(BetterHtml.fromHtml(activity, R.string.registration_config_enable_text)) positive(R.string.i_agree) {
.setPositiveButton(R.string.i_agree) { _, _ ->
enableRegistration() enableRegistration()
} }
.setNegativeButton(R.string.i_disagree, null) negative(R.string.i_disagree)
.setOnDismissListener { }.show()
onDismissListener?.invoke(TAG + "Enable")
}
.show()
} }
fun showDisableDialog() { fun showDisableDialog() {
onShowListener?.invoke(TAG + "Disable") dialog = SimpleDialog<Unit>(activity) {
dialog = MaterialAlertDialogBuilder(activity) title(R.string.registration_config_title)
.setTitle(R.string.registration_config_title) message(R.string.registration_config_disable_text)
.setMessage(R.string.registration_config_disable_text) positive(R.string.ok) {
.setPositiveButton(R.string.ok) { _, _ ->
disableRegistration() disableRegistration()
} }
.setNegativeButton(R.string.cancel, null) negative(R.string.cancel)
.setOnDismissListener { }.show()
onDismissListener?.invoke(TAG + "Disable")
}
.show()
} }
private fun enableRegistration() = launch { private fun enableRegistration() = launch {
onShowListener?.invoke(TAG + "Enabling") dialog = SimpleDialog<Unit>(activity) {
dialog = MaterialAlertDialogBuilder(activity) title(R.string.please_wait)
.setTitle(R.string.please_wait) message(R.string.registration_config_enable_progress_text)
.setMessage(R.string.registration_config_enable_progress_text) cancelable(false)
.setCancelable(false) }.show()
.setOnDismissListener {
onDismissListener?.invoke(TAG + "Enabling")
}
.show()
withContext(Dispatchers.Default) { withContext(Dispatchers.Default) {
profile.registration = Profile.REGISTRATION_ENABLED profile.registration = Profile.REGISTRATION_ENABLED
@ -140,15 +115,11 @@ class RegistrationConfigDialog(
} }
private fun disableRegistration() = launch { private fun disableRegistration() = launch {
onShowListener?.invoke(TAG + "Disabling") dialog = SimpleDialog<Unit>(activity) {
dialog = MaterialAlertDialogBuilder(activity) title(R.string.please_wait)
.setTitle(R.string.please_wait) message(R.string.registration_config_disable_progress_text)
.setMessage(R.string.registration_config_disable_progress_text) cancelable(false)
.setCancelable(false) }.show()
.setOnDismissListener {
onDismissListener?.invoke(TAG + "Disabling")
}
.show()
withContext(Dispatchers.Default) { withContext(Dispatchers.Default) {
profile.registration = Profile.REGISTRATION_DISABLED profile.registration = Profile.REGISTRATION_DISABLED

View File

@ -6,42 +6,27 @@ package pl.szczodrzynski.edziennik.ui.dialogs.settings
import android.text.InputType import android.text.InputType
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import pl.szczodrzynski.edziennik.R import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.data.db.entity.Profile import pl.szczodrzynski.edziennik.data.db.entity.Profile
import pl.szczodrzynski.edziennik.ext.input import pl.szczodrzynski.edziennik.ext.takeValue
import pl.szczodrzynski.edziennik.ui.base.dialog.BaseDialog
class StudentNumberDialog( class StudentNumberDialog(
val activity: AppCompatActivity, activity: AppCompatActivity,
val profile: Profile, val profile: Profile,
val onShowListener: ((tag: String) -> Unit)? = null, ) : BaseDialog<Unit>(activity) {
val onDismissListener: ((tag: String) -> Unit)? = null
) {
companion object {
private const val TAG = "StudentNumberDialog"
}
init { run { override fun getTitleRes() = R.string.card_lucky_number_set_title
if (activity.isFinishing) override fun getMessageRes() = R.string.card_lucky_number_set_text
return@run override fun getPositiveButtonText() = R.string.ok
onShowListener?.invoke(TAG) override fun getNegativeButtonText() = R.string.cancel
MaterialAlertDialogBuilder(activity)
.setTitle(R.string.card_lucky_number_set_title) override fun getInputType() = InputType.TYPE_CLASS_NUMBER
.input( override fun getInputValue() = profile.studentNumber.takeValue()?.toString()
message = activity.getString(R.string.card_lucky_number_set_text),
type = InputType.TYPE_CLASS_NUMBER, override suspend fun onPositiveClick(): Boolean {
hint = null, profile.studentNumber = getInput()?.text?.toString()?.toIntOrNull() ?: -1
value = if (profile.studentNumber == -1) null else profile.studentNumber.toString(), app.profileSave(profile)
positiveButton = R.string.ok, return DISMISS
positiveListener = { _, input -> }
profile.studentNumber = input.toIntOrNull() ?: -1
true
}
)
.setNegativeButton(R.string.cancel, null)
.setOnDismissListener {
onDismissListener?.invoke(TAG)
}
.show()
}}
} }

View File

@ -14,11 +14,7 @@ import pl.szczodrzynski.edziennik.ui.base.dialog.BaseDialog
class SyncIntervalDialog( class SyncIntervalDialog(
activity: AppCompatActivity, activity: AppCompatActivity,
private val onChangeListener: (() -> Unit)? = null, private val onChangeListener: (() -> Unit)? = null,
onShowListener: ((tag: String) -> Unit)? = null, ) : BaseDialog<Any>(activity) {
onDismissListener: ((tag: String) -> Unit)? = null,
) : BaseDialog<Any>(activity, onShowListener, onDismissListener) {
override val TAG = "SyncIntervalDialog"
override fun getTitleRes() = R.string.settings_sync_sync_interval_dialog_title override fun getTitleRes() = R.string.settings_sync_sync_interval_dialog_title
override fun getMessageRes() = R.string.settings_sync_sync_interval_dialog_text override fun getMessageRes() = R.string.settings_sync_sync_interval_dialog_text
@ -39,8 +35,6 @@ class SyncIntervalDialog(
override fun getDefaultSelectedItem() = app.config.sync.interval.toLong() override fun getDefaultSelectedItem() = app.config.sync.interval.toLong()
override suspend fun onShow() = Unit
override suspend fun onPositiveClick(): Boolean { override suspend fun onPositiveClick(): Boolean {
val interval = getSingleSelection() as? Long ?: return DISMISS val interval = getSingleSelection() as? Long ?: return DISMISS
app.config.sync.interval = interval.toInt() app.config.sync.interval = interval.toInt()

View File

@ -11,11 +11,7 @@ import pl.szczodrzynski.edziennik.ui.base.dialog.BaseDialog
class ThemeChooserDialog( class ThemeChooserDialog(
activity: AppCompatActivity, activity: AppCompatActivity,
onShowListener: ((tag: String) -> Unit)? = null, ) : BaseDialog<Theme>(activity) {
onDismissListener: ((tag: String) -> Unit)? = null,
) : BaseDialog<Theme>(activity, onShowListener, onDismissListener) {
override val TAG = "ThemeChooserDialog"
override fun getTitleRes() = R.string.settings_theme_theme_text override fun getTitleRes() = R.string.settings_theme_theme_text
override fun getPositiveButtonText() = R.string.ok override fun getPositiveButtonText() = R.string.ok
@ -26,8 +22,6 @@ class ThemeChooserDialog(
override fun getDefaultSelectedItem() = app.uiManager.themeColor override fun getDefaultSelectedItem() = app.uiManager.themeColor
override suspend fun onShow() = Unit
override suspend fun onPositiveClick(): Boolean { override suspend fun onPositiveClick(): Boolean {
val themeColor = getSingleSelection() ?: return DISMISS val themeColor = getSingleSelection() ?: return DISMISS
if (app.uiManager.themeColor != themeColor) { if (app.uiManager.themeColor != themeColor) {

View File

@ -15,16 +15,7 @@ import pl.szczodrzynski.edziennik.ui.timetable.TimetableFragment
class TimetableConfigDialog( class TimetableConfigDialog(
activity: AppCompatActivity, activity: AppCompatActivity,
reloadOnDismiss: Boolean = true, reloadOnDismiss: Boolean = true,
onShowListener: ((tag: String) -> Unit)? = null, ) : ConfigDialog<TimetableConfigDialogBinding>(activity, reloadOnDismiss) {
onDismissListener: ((tag: String) -> Unit)? = null,
) : ConfigDialog<TimetableConfigDialogBinding>(
activity,
reloadOnDismiss,
onShowListener,
onDismissListener,
) {
override val TAG = "TimetableConfigDialog"
override fun getTitleRes() = R.string.menu_timetable_config override fun getTitleRes() = R.string.menu_timetable_config
override fun inflate(layoutInflater: LayoutInflater) = override fun inflate(layoutInflater: LayoutInflater) =

View File

@ -19,11 +19,7 @@ import pl.szczodrzynski.edziennik.utils.Utils
class RegisterUnavailableDialog( class RegisterUnavailableDialog(
activity: AppCompatActivity, activity: AppCompatActivity,
private val status: RegisterAvailabilityStatus, private val status: RegisterAvailabilityStatus,
onShowListener: ((tag: String) -> Unit)? = null, ) : BindingDialog<DialogRegisterUnavailableBinding>(activity) {
onDismissListener: ((tag: String) -> Unit)? = null,
) : BindingDialog<DialogRegisterUnavailableBinding>(activity, onShowListener, onDismissListener) {
override val TAG = "RegisterUnavailableDialog"
override fun getTitleRes(): Int? = null override fun getTitleRes(): Int? = null
override fun inflate(layoutInflater: LayoutInflater) = override fun inflate(layoutInflater: LayoutInflater) =
@ -43,8 +39,6 @@ class RegisterUnavailableDialog(
activity = activity, activity = activity,
update = update, update = update,
mandatory = update != null && update.versionCode >= status.minVersionCode, mandatory = update != null && update.versionCode >= status.minVersionCode,
onShowListener = onShowListener,
onDismissListener = onDismissListener
).show() ).show()
return false return false
} }

View File

@ -12,16 +12,9 @@ class ServerMessageDialog(
activity: AppCompatActivity, activity: AppCompatActivity,
private val titleText: String, private val titleText: String,
private val messageText: CharSequence, private val messageText: CharSequence,
onShowListener: ((tag: String) -> Unit)? = null, ) : BaseDialog<Any>(activity) {
onDismissListener: ((tag: String) -> Unit)? = null,
) : BaseDialog<Any>(activity, onShowListener, onDismissListener) {
override val TAG = "ServerMessageDialog"
override fun getTitle() = titleText override fun getTitle() = titleText
override fun getTitleRes(): Int? = null
override fun getMessage() = messageText override fun getMessage() = messageText
override fun getPositiveButtonText() = R.string.close override fun getPositiveButtonText() = R.string.close
override suspend fun onShow() = Unit
} }

View File

@ -19,11 +19,7 @@ import pl.szczodrzynski.edziennik.ui.messages.list.MessagesFragment
class SyncViewListDialog( class SyncViewListDialog(
activity: MainActivity, activity: MainActivity,
private val currentNavTarget: NavTarget, private val currentNavTarget: NavTarget,
onShowListener: ((tag: String) -> Unit)? = null, ) : BaseDialog<FeatureType>(activity) {
onDismissListener: ((tag: String) -> Unit)? = null,
) : BaseDialog<FeatureType>(activity, onShowListener, onDismissListener) {
override val TAG = "SyncViewListDialog"
override fun getTitleRes() = R.string.dialog_sync_view_list_title override fun getTitleRes() = R.string.dialog_sync_view_list_title
override fun getPositiveButtonText() = R.string.ok override fun getPositiveButtonText() = R.string.ok
@ -44,8 +40,6 @@ class SyncViewListDialog(
else -> currentNavTarget.featureType?.let { setOf(it) } ?: getMultiChoiceItems().values.toSet() else -> currentNavTarget.featureType?.let { setOf(it) } ?: getMultiChoiceItems().values.toSet()
} }
override suspend fun onShow() = Unit
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
override suspend fun onPositiveClick(): Boolean { override suspend fun onPositiveClick(): Boolean {
val selected = getMultiSelection() val selected = getMultiSelection()

View File

@ -18,11 +18,7 @@ class UpdateAvailableDialog(
activity: AppCompatActivity, activity: AppCompatActivity,
private val update: Update?, private val update: Update?,
private val mandatory: Boolean = update?.updateMandatory ?: false, private val mandatory: Boolean = update?.updateMandatory ?: false,
onShowListener: ((tag: String) -> Unit)? = null, ) : BaseDialog<Any>(activity) {
onDismissListener: ((tag: String) -> Unit)? = null,
) : BaseDialog<Any>(activity, onShowListener, onDismissListener) {
override val TAG = "UpdateAvailableDialog"
override fun getTitleRes() = R.string.update_available_title override fun getTitleRes() = R.string.update_available_title
override fun getMessageFormat(): Pair<Int, List<CharSequence>> { override fun getMessageFormat(): Pair<Int, List<CharSequence>> {
@ -40,8 +36,6 @@ class UpdateAvailableDialog(
override fun getPositiveButtonText() = R.string.update_available_button override fun getPositiveButtonText() = R.string.update_available_button
override fun getNeutralButtonText() = if (mandatory) null else R.string.update_available_later override fun getNeutralButtonText() = if (mandatory) null else R.string.update_available_later
override suspend fun onShow() = Unit
override suspend fun onPositiveClick(): Boolean { override suspend fun onPositiveClick(): Boolean {
if (update == null || update.isOnGooglePlay) if (update == null || update.isOnGooglePlay)
Utils.openGooglePlay(activity) Utils.openGooglePlay(activity)

View File

@ -9,7 +9,6 @@ import android.database.CursorIndexOutOfBoundsException
import android.view.LayoutInflater import android.view.LayoutInflater
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.getSystemService import androidx.core.content.getSystemService
import kotlinx.coroutines.Job
import org.greenrobot.eventbus.EventBus import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode import org.greenrobot.eventbus.ThreadMode
@ -26,11 +25,7 @@ class UpdateProgressDialog(
activity: AppCompatActivity, activity: AppCompatActivity,
private val update: Update, private val update: Update,
private val downloadId: Long, private val downloadId: Long,
onShowListener: ((tag: String) -> Unit)? = null, ) : BindingDialog<UpdateProgressDialogBinding>(activity) {
onDismissListener: ((tag: String) -> Unit)? = null,
) : BindingDialog<UpdateProgressDialogBinding>(activity, onShowListener, onDismissListener) {
override val TAG = "UpdateProgressDialog"
override fun getTitleRes() = R.string.notification_downloading_update override fun getTitleRes() = R.string.notification_downloading_update
override fun inflate(layoutInflater: LayoutInflater) = override fun inflate(layoutInflater: LayoutInflater) =
@ -39,8 +34,6 @@ class UpdateProgressDialog(
override fun isCancelable() = false override fun isCancelable() = false
override fun getNegativeButtonText() = R.string.cancel override fun getNegativeButtonText() = R.string.cancel
private var timerJob: Job? = null
override suspend fun onShow() { override suspend fun onShow() {
EventBus.getDefault().register(this) EventBus.getDefault().register(this)
b.update = update b.update = update
@ -49,8 +42,7 @@ class UpdateProgressDialog(
val downloadManager = app.getSystemService<DownloadManager>() ?: return val downloadManager = app.getSystemService<DownloadManager>() ?: return
val query = DownloadManager.Query().setFilterById(downloadId) val query = DownloadManager.Query().setFilterById(downloadId)
timerJob?.cancel() startCoroutineTimer(repeatMillis = 100L) {
timerJob = startCoroutineTimer(repeatMillis = 100L) {
try { try {
val cursor = downloadManager.query(query) val cursor = downloadManager.query(query)
cursor.moveToFirst() cursor.moveToFirst()
@ -65,11 +57,6 @@ class UpdateProgressDialog(
} }
} }
override fun onDismiss() {
EventBus.getDefault().unregister(this)
timerJob?.cancel()
}
override suspend fun onNegativeClick(): Boolean { override suspend fun onNegativeClick(): Boolean {
val downloadManager = app.getSystemService<DownloadManager>() ?: return NO_DISMISS val downloadManager = app.getSystemService<DownloadManager>() ?: return NO_DISMISS
downloadManager.remove(downloadId) downloadManager.remove(downloadId)

View File

@ -11,24 +11,38 @@ import android.provider.CalendarContract.Events
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.widget.Toast import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.isVisible import androidx.core.view.isVisible
import com.google.android.material.color.MaterialColors import com.google.android.material.color.MaterialColors
import com.google.android.material.dialog.MaterialAlertDialogBuilder import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.* import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.greenrobot.eventbus.EventBus import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode import org.greenrobot.eventbus.ThreadMode
import pl.szczodrzynski.edziennik.* import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.MainActivity
import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.data.api.edziennik.EdziennikTask import pl.szczodrzynski.edziennik.data.api.edziennik.EdziennikTask
import pl.szczodrzynski.edziennik.data.api.events.EventGetEvent import pl.szczodrzynski.edziennik.data.api.events.EventGetEvent
import pl.szczodrzynski.edziennik.data.api.szkolny.SzkolnyApi import pl.szczodrzynski.edziennik.data.api.szkolny.SzkolnyApi
import pl.szczodrzynski.edziennik.data.db.full.EventFull import pl.szczodrzynski.edziennik.data.db.full.EventFull
import pl.szczodrzynski.edziennik.databinding.DialogEventDetailsBinding
import pl.szczodrzynski.edziennik.ext.*
import pl.szczodrzynski.edziennik.data.enums.NavTarget import pl.szczodrzynski.edziennik.data.enums.NavTarget
import pl.szczodrzynski.edziennik.databinding.DialogEventDetailsBinding
import pl.szczodrzynski.edziennik.ext.Bundle
import pl.szczodrzynski.edziennik.ext.asColoredSpannable
import pl.szczodrzynski.edziennik.ext.attachToastHint
import pl.szczodrzynski.edziennik.ext.concat
import pl.szczodrzynski.edziennik.ext.isNotNullNorBlank
import pl.szczodrzynski.edziennik.ext.onChange
import pl.szczodrzynski.edziennik.ext.onClick
import pl.szczodrzynski.edziennik.ext.putExtras
import pl.szczodrzynski.edziennik.ext.resolveAttr
import pl.szczodrzynski.edziennik.ext.setText
import pl.szczodrzynski.edziennik.ext.setTintColor
import pl.szczodrzynski.edziennik.ui.base.dialog.BaseDialog
import pl.szczodrzynski.edziennik.ui.base.dialog.BindingDialog import pl.szczodrzynski.edziennik.ui.base.dialog.BindingDialog
import pl.szczodrzynski.edziennik.ui.base.dialog.SimpleDialog
import pl.szczodrzynski.edziennik.ui.notes.setupNotesButton import pl.szczodrzynski.edziennik.ui.notes.setupNotesButton
import pl.szczodrzynski.edziennik.ui.timetable.TimetableFragment import pl.szczodrzynski.edziennik.ui.timetable.TimetableFragment
import pl.szczodrzynski.edziennik.utils.BetterLink import pl.szczodrzynski.edziennik.utils.BetterLink
@ -40,11 +54,7 @@ class EventDetailsDialog(
// this event is observed for changes // this event is observed for changes
private var event: EventFull, private var event: EventFull,
private val showNotes: Boolean = true, private val showNotes: Boolean = true,
onShowListener: ((tag: String) -> Unit)? = null, ) : BindingDialog<DialogEventDetailsBinding>(activity) {
onDismissListener: ((tag: String) -> Unit)? = null,
) : BindingDialog<DialogEventDetailsBinding>(activity, onShowListener, onDismissListener) {
override val TAG = "EventDetailsDialog"
override fun getTitleRes(): Int? = null override fun getTitleRes(): Int? = null
override fun inflate(layoutInflater: LayoutInflater) = override fun inflate(layoutInflater: LayoutInflater) =
@ -53,7 +63,6 @@ class EventDetailsDialog(
override fun getPositiveButtonText() = R.string.close override fun getPositiveButtonText() = R.string.close
override fun getNeutralButtonText() = if (event.addedManually) R.string.remove else null override fun getNeutralButtonText() = if (event.addedManually) R.string.remove else null
private var removeEventDialog: AlertDialog? = null
private val eventShared = event.sharedBy != null private val eventShared = event.sharedBy != null
private val eventOwn = event.sharedBy == "self" private val eventOwn = event.sharedBy == "self"
private val manager private val manager
@ -63,18 +72,13 @@ class EventDetailsDialog(
SzkolnyApi(app) SzkolnyApi(app)
} }
private var progressDialog: AlertDialog? = null private var progressDialog: BaseDialog<*>? = null
override suspend fun onNeutralClick(): Boolean { override suspend fun onNeutralClick(): Boolean {
showRemoveEventDialog() showRemoveEventDialog()
return NO_DISMISS return NO_DISMISS
} }
override suspend fun onBeforeShow(): Boolean {
EventBus.getDefault().register(this)
return true
}
override suspend fun onShow() { override suspend fun onShow() {
// watch the event for changes // watch the event for changes
app.db.eventDao().getById(event.profileId, event.id).observe(activity) { app.db.eventDao().getById(event.profileId, event.id).observe(activity) {
@ -83,8 +87,7 @@ class EventDetailsDialog(
} }
} }
override fun onDismiss() { override suspend fun onDismiss() {
EventBus.getDefault().unregister(this@EventDetailsDialog)
progressDialog?.dismiss() progressDialog?.dismiss()
} }
@ -150,22 +153,22 @@ class EventDetailsDialog(
b.checkDoneButton.onChange { _, isChecked -> b.checkDoneButton.onChange { _, isChecked ->
if (isChecked && !event.isDone) { if (isChecked && !event.isDone) {
b.checkDoneButton.isChecked = false b.checkDoneButton.isChecked = false
MaterialAlertDialogBuilder(activity) SimpleDialog<Unit>(activity) {
.setTitle(R.string.event_mark_as_done_title) title(R.string.event_mark_as_done_title)
.setMessage(R.string.event_mark_as_done_text) message(R.string.event_mark_as_done_text)
.setPositiveButton(R.string.ok) { _, _ -> positive(R.string.ok) {
event.isDone = isChecked event.isDone = true
launch(Dispatchers.Default) { withContext(Dispatchers.IO) {
app.db.eventDao().replace(event) app.db.eventDao().replace(event)
}
update()
b.checkDoneButton.isChecked = true
} }
.setNegativeButton(R.string.cancel, null) update()
.show() b.checkDoneButton.isChecked = true
}
negative(R.string.cancel)
}.show()
} }
else if (!isChecked && event.isDone) { else if (!isChecked && event.isDone) {
event.isDone = isChecked event.isDone = false
launch(Dispatchers.Default) { launch(Dispatchers.Default) {
app.db.eventDao().replace(event) app.db.eventDao().replace(event)
} }
@ -183,15 +186,13 @@ class EventDetailsDialog(
editingEvent = event, editingEvent = event,
onSaveListener = { onSaveListener = {
if (it == null) { if (it == null) {
dialog.dismiss() dismiss()
return@EventManualDialog return@EventManualDialog
} }
// this should not be needed as the event is observed by the ID // this should not be needed as the event is observed by the ID
// event = it // event = it
// update() // update()
}, },
onShowListener = onShowListener,
onDismissListener = onDismissListener
).show() ).show()
} }
b.editButton.attachToastHint(R.string.hint_edit_event) b.editButton.attachToastHint(R.string.hint_edit_event)
@ -204,7 +205,7 @@ class EventDetailsDialog(
// GO TO TIMETABLE // GO TO TIMETABLE
b.goToTimetableButton.onClick { b.goToTimetableButton.onClick {
dialog.dismiss() dismiss()
val dateStr = event.date.stringY_m_d val dateStr = event.date.stringY_m_d
val intent = val intent =
@ -235,13 +236,13 @@ class EventDetailsDialog(
} }
b.downloadButton.attachToastHint(R.string.hint_download_again) b.downloadButton.attachToastHint(R.string.hint_download_again)
BetterLink.attach(b.topic, onActionSelected = dialog::dismiss) BetterLink.attach(b.topic, onActionSelected = ::dismiss)
event.teacherName?.let { name -> event.teacherName?.let { name ->
BetterLink.attach( BetterLink.attach(
b.teacherName, b.teacherName,
teachers = mapOf(event.teacherId to name), teachers = mapOf(event.teacherId to name),
onActionSelected = dialog::dismiss onActionSelected = ::dismiss
) )
} }
@ -260,7 +261,7 @@ class EventDetailsDialog(
b.bodyTitle.isVisible = true b.bodyTitle.isVisible = true
b.bodyProgressBar.isVisible = false b.bodyProgressBar.isVisible = false
b.body.isVisible = true b.body.isVisible = true
BetterLink.attach(b.body, onActionSelected = dialog::dismiss) BetterLink.attach(b.body, onActionSelected = ::dismiss)
} }
if (event.attachmentIds.isNullOrEmpty() || event.attachmentNames.isNullOrEmpty()) { if (event.attachmentIds.isNullOrEmpty() || event.attachmentNames.isNullOrEmpty()) {
@ -281,8 +282,6 @@ class EventDetailsDialog(
b.notesButton.setupNotesButton( b.notesButton.setupNotesButton(
activity = activity, activity = activity,
owner = event, owner = event,
onShowListener = onShowListener,
onDismissListener = onDismissListener,
) )
} }
@ -299,11 +298,11 @@ class EventDetailsDialog(
return return
} }
progressDialog = MaterialAlertDialogBuilder(activity) progressDialog = SimpleDialog<Unit>(activity) {
.setTitle(R.string.please_wait) title(R.string.please_wait)
.setMessage(R.string.event_removing_text) message(R.string.event_removing_text)
.setCancelable(false) cancelable(false)
.show() }.show()
} }
private fun showRemoveEventDialog() { private fun showRemoveEventDialog() {
@ -312,22 +311,14 @@ class EventDetailsDialog(
eventShared && !eventOwn -> "\n\n"+activity.getString(R.string.dialog_event_manual_remove_shared) eventShared && !eventOwn -> "\n\n"+activity.getString(R.string.dialog_event_manual_remove_shared)
else -> "" else -> ""
} }
removeEventDialog = MaterialAlertDialogBuilder(activity) SimpleDialog<Unit>(activity) {
.setTitle(R.string.are_you_sure) title(R.string.are_you_sure)
.setMessage(activity.getString(R.string.dialog_register_event_manual_remove_confirmation)+shareNotice) message(activity.getString(R.string.dialog_register_event_manual_remove_confirmation) + shareNotice)
.setPositiveButton(R.string.yes, null) positive(R.string.yes) {
.setNegativeButton(R.string.no) { dialog, _ -> dialog.dismiss() } removeEvent()
.create() }
.apply { negative(R.string.no)
setOnShowListener { dialog -> }.show()
val positiveButton = (dialog as AlertDialog).getButton(AlertDialog.BUTTON_POSITIVE)
positiveButton?.setOnClickListener {
removeEvent()
}
}
show()
}
} }
private fun removeEvent() { private fun removeEvent() {
@ -364,8 +355,7 @@ class EventDetailsDialog(
} }
} }
removeEventDialog?.dismiss() dismiss()
dialog.dismiss()
Toast.makeText(activity, R.string.removed, Toast.LENGTH_SHORT).show() Toast.makeText(activity, R.string.removed, Toast.LENGTH_SHORT).show()
} }

View File

@ -8,33 +8,32 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.widget.Toast import android.widget.Toast
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AlertDialog.BUTTON_POSITIVE
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import com.google.android.material.color.MaterialColors import com.google.android.material.color.MaterialColors
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.jaredrummler.android.colorpicker.ColorPickerDialog import com.jaredrummler.android.colorpicker.ColorPickerDialog
import com.jaredrummler.android.colorpicker.ColorPickerDialogListener import com.jaredrummler.android.colorpicker.ColorPickerDialogListener
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode import org.greenrobot.eventbus.ThreadMode
import pl.szczodrzynski.edziennik.R import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.data.config.AppData import pl.szczodrzynski.edziennik.core.manager.TextStylingManager.HtmlMode.SIMPLE
import pl.szczodrzynski.edziennik.core.manager.TextStylingManager.StylingConfigBase
import pl.szczodrzynski.edziennik.data.api.edziennik.EdziennikTask import pl.szczodrzynski.edziennik.data.api.edziennik.EdziennikTask
import pl.szczodrzynski.edziennik.data.api.events.ApiTaskAllFinishedEvent import pl.szczodrzynski.edziennik.data.api.events.ApiTaskAllFinishedEvent
import pl.szczodrzynski.edziennik.data.api.events.ApiTaskErrorEvent import pl.szczodrzynski.edziennik.data.api.events.ApiTaskErrorEvent
import pl.szczodrzynski.edziennik.data.api.events.ApiTaskFinishedEvent import pl.szczodrzynski.edziennik.data.api.events.ApiTaskFinishedEvent
import pl.szczodrzynski.edziennik.data.api.szkolny.SzkolnyApi import pl.szczodrzynski.edziennik.data.api.szkolny.SzkolnyApi
import pl.szczodrzynski.edziennik.data.config.AppData
import pl.szczodrzynski.edziennik.data.db.entity.Event import pl.szczodrzynski.edziennik.data.db.entity.Event
import pl.szczodrzynski.edziennik.data.db.entity.Metadata import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.entity.Profile import pl.szczodrzynski.edziennik.data.db.entity.Profile
import pl.szczodrzynski.edziennik.data.db.entity.Subject import pl.szczodrzynski.edziennik.data.db.entity.Subject
import pl.szczodrzynski.edziennik.data.enums.FeatureType
import pl.szczodrzynski.edziennik.data.enums.MetadataType
import pl.szczodrzynski.edziennik.data.db.full.EventFull import pl.szczodrzynski.edziennik.data.db.full.EventFull
import pl.szczodrzynski.edziennik.data.db.full.LessonFull import pl.szczodrzynski.edziennik.data.db.full.LessonFull
import pl.szczodrzynski.edziennik.data.enums.FeatureType
import pl.szczodrzynski.edziennik.data.enums.MetadataType
import pl.szczodrzynski.edziennik.databinding.DialogEventManualV2Binding import pl.szczodrzynski.edziennik.databinding.DialogEventManualV2Binding
import pl.szczodrzynski.edziennik.ext.JsonObject import pl.szczodrzynski.edziennik.ext.JsonObject
import pl.szczodrzynski.edziennik.ext.appendView import pl.szczodrzynski.edziennik.ext.appendView
@ -44,13 +43,13 @@ import pl.szczodrzynski.edziennik.ext.onClick
import pl.szczodrzynski.edziennik.ext.removeFromParent import pl.szczodrzynski.edziennik.ext.removeFromParent
import pl.szczodrzynski.edziennik.ext.setText import pl.szczodrzynski.edziennik.ext.setText
import pl.szczodrzynski.edziennik.ext.setTintColor import pl.szczodrzynski.edziennik.ext.setTintColor
import pl.szczodrzynski.edziennik.ui.base.dialog.BaseDialog
import pl.szczodrzynski.edziennik.ui.base.dialog.BindingDialog import pl.szczodrzynski.edziennik.ui.base.dialog.BindingDialog
import pl.szczodrzynski.edziennik.ui.dialogs.settings.RegistrationConfigDialog import pl.szczodrzynski.edziennik.ui.base.dialog.SimpleDialog
import pl.szczodrzynski.edziennik.ui.base.views.TimeDropdown.Companion.DISPLAY_LESSONS import pl.szczodrzynski.edziennik.ui.base.views.TimeDropdown.Companion.DISPLAY_LESSONS
import pl.szczodrzynski.edziennik.ui.dialogs.settings.RegistrationConfigDialog
import pl.szczodrzynski.edziennik.utils.Anim import pl.szczodrzynski.edziennik.utils.Anim
import pl.szczodrzynski.edziennik.utils.html.BetterHtml import pl.szczodrzynski.edziennik.utils.html.BetterHtml
import pl.szczodrzynski.edziennik.core.manager.TextStylingManager.HtmlMode.SIMPLE
import pl.szczodrzynski.edziennik.core.manager.TextStylingManager.StylingConfigBase
import pl.szczodrzynski.edziennik.utils.models.Date import pl.szczodrzynski.edziennik.utils.models.Date
import pl.szczodrzynski.edziennik.utils.models.Time import pl.szczodrzynski.edziennik.utils.models.Time
@ -64,11 +63,7 @@ class EventManualDialog(
private val defaultType: Long? = null, private val defaultType: Long? = null,
private val editingEvent: EventFull? = null, private val editingEvent: EventFull? = null,
private val onSaveListener: ((event: EventFull?) -> Unit)? = null, private val onSaveListener: ((event: EventFull?) -> Unit)? = null,
onShowListener: ((tag: String) -> Unit)? = null, ) : BindingDialog<DialogEventManualV2Binding>(activity) {
onDismissListener: ((tag: String) -> Unit)? = null,
) : BindingDialog<DialogEventManualV2Binding>(activity, onShowListener, onDismissListener) {
override val TAG = "EventManualDialog"
override fun getTitleRes() = R.string.dialog_event_manual_title override fun getTitleRes() = R.string.dialog_event_manual_title
override fun inflate(layoutInflater: LayoutInflater) = override fun inflate(layoutInflater: LayoutInflater) =
@ -94,10 +89,10 @@ class EventManualDialog(
SzkolnyApi(app) SzkolnyApi(app)
} }
private var enqueuedWeekDialog: AlertDialog? = null private var enqueuedWeekDialog: BaseDialog<*>? = null
private var enqueuedWeekStart = Date.getToday() private var enqueuedWeekStart = Date.getToday()
private var progressDialog: AlertDialog? = null private var progressDialog: BaseDialog<*>? = null
override suspend fun onPositiveClick(): Boolean { override suspend fun onPositiveClick(): Boolean {
saveEvent() saveEvent()
@ -109,13 +104,7 @@ class EventManualDialog(
return NO_DISMISS return NO_DISMISS
} }
override suspend fun onBeforeShow(): Boolean { override suspend fun onDismiss() {
EventBus.getDefault().register(this@EventManualDialog)
return true
}
override fun onDismiss() {
EventBus.getDefault().unregister(this@EventManualDialog)
enqueuedWeekDialog?.dismiss() enqueuedWeekDialog?.dismiss()
progressDialog?.dismiss() progressDialog?.dismiss()
} }
@ -145,8 +134,6 @@ class EventManualDialog(
activity = activity, activity = activity,
textLayout = b.topicLayout, textLayout = b.topicLayout,
textEdit = b.topic, textEdit = b.topic,
onShowListener = onShowListener,
onDismissListener = onDismissListener,
) )
stylingConfig = StylingConfigBase(editText = b.topic, htmlMode = SIMPLE) stylingConfig = StylingConfigBase(editText = b.topic, htmlMode = SIMPLE)
@ -187,11 +174,11 @@ class EventManualDialog(
return return
} }
val weekStart = date.weekStart val weekStart = date.weekStart
enqueuedWeekDialog = MaterialAlertDialogBuilder(activity) enqueuedWeekDialog = SimpleDialog<Unit>(activity) {
.setTitle(R.string.please_wait) title(R.string.please_wait)
.setMessage(R.string.timetable_syncing_text) message(R.string.timetable_syncing_text)
.setCancelable(false) cancelable(false)
.show() }.show()
enqueuedWeekStart = weekStart enqueuedWeekStart = weekStart
@ -209,11 +196,11 @@ class EventManualDialog(
return return
} }
progressDialog = MaterialAlertDialogBuilder(activity) progressDialog = SimpleDialog<Unit>(activity) {
.setTitle(R.string.please_wait) title(R.string.please_wait)
.setMessage(R.string.event_sharing_text) message(R.string.event_sharing_text)
.setCancelable(false) cancelable(false)
.show() }.show()
} }
private fun showRemovingProgressDialog() { private fun showRemovingProgressDialog() {
@ -221,11 +208,11 @@ class EventManualDialog(
return return
} }
progressDialog = MaterialAlertDialogBuilder(activity) progressDialog = SimpleDialog<Unit>(activity) {
.setTitle(R.string.please_wait) title(R.string.please_wait)
.setMessage(R.string.event_removing_text) message(R.string.event_removing_text)
.setCancelable(false) cancelable(false)
.show() }.show()
} }
@Subscribe(threadMode = ThreadMode.MAIN) @Subscribe(threadMode = ThreadMode.MAIN)
@ -399,22 +386,14 @@ class EventManualDialog(
editingShared && !editingOwn -> "\n\n"+activity.getString(R.string.dialog_event_manual_remove_shared) editingShared && !editingOwn -> "\n\n"+activity.getString(R.string.dialog_event_manual_remove_shared)
else -> "" else -> ""
} }
removeEventDialog = MaterialAlertDialogBuilder(activity) SimpleDialog<Unit>(activity) {
.setTitle(R.string.are_you_sure) title(R.string.are_you_sure)
.setMessage(activity.getString(R.string.dialog_register_event_manual_remove_confirmation)+shareNotice) message(activity.getString(R.string.dialog_register_event_manual_remove_confirmation) + shareNotice)
.setPositiveButton(R.string.yes, null) positive(R.string.yes) {
.setNegativeButton(R.string.no) { dialog, _ -> dialog.dismiss() } removeEvent()
.create() }
.apply { negative(R.string.no)
setOnShowListener { dialog -> }.show()
val positiveButton = (dialog as AlertDialog).getButton(BUTTON_POSITIVE)
positiveButton?.setOnClickListener {
removeEvent()
}
}
show()
}
} }
private fun saveEvent() { private fun saveEvent() {

View File

@ -24,11 +24,7 @@ class GradeDetailsDialog(
activity: AppCompatActivity, activity: AppCompatActivity,
private val grade: GradeFull, private val grade: GradeFull,
private val showNotes: Boolean = true, private val showNotes: Boolean = true,
onShowListener: ((tag: String) -> Unit)? = null, ) : BindingDialog<DialogGradeDetailsBinding>(activity) {
onDismissListener: ((tag: String) -> Unit)? = null,
) : BindingDialog<DialogGradeDetailsBinding>(activity, onShowListener, onDismissListener) {
override val TAG = "GradeDetailsDialog"
override fun getTitleRes(): Int? = null override fun getTitleRes(): Int? = null
override fun inflate(layoutInflater: LayoutInflater) = override fun inflate(layoutInflater: LayoutInflater) =
@ -67,7 +63,7 @@ class GradeDetailsDialog(
BetterLink.attach( BetterLink.attach(
b.teacherName, b.teacherName,
teachers = mapOf(grade.teacherId to name), teachers = mapOf(grade.teacherId to name),
onActionSelected = dialog::dismiss onActionSelected = ::dismiss
) )
} }
@ -98,8 +94,6 @@ class GradeDetailsDialog(
b.notesButton.setupNotesButton( b.notesButton.setupNotesButton(
activity = activity, activity = activity,
owner = grade, owner = grade,
onShowListener = onShowListener,
onDismissListener = onDismissListener,
) )
b.legend.isVisible = showNotes b.legend.isVisible = showNotes
if (showNotes) if (showNotes)

View File

@ -45,7 +45,7 @@ class GradesListFragment : BaseFragment<GradesListFragmentBinding, MainActivity>
.withIcon(CommunityMaterial.Icon.cmd_cog_outline) .withIcon(CommunityMaterial.Icon.cmd_cog_outline)
.withOnClickListener { .withOnClickListener {
activity.bottomSheet.close() activity.bottomSheet.close()
GradesConfigDialog(activity, true, null, null).show() GradesConfigDialog(activity, true).show()
}, },
) )

View File

@ -14,14 +14,14 @@ import com.daimajia.swipe.SwipeLayout
import com.mikepenz.iconics.view.IconicsImageView import com.mikepenz.iconics.view.IconicsImageView
import pl.szczodrzynski.edziennik.App import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.R import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.ui.grades.editor.GradesEditorFragment.Companion.modifyGradeChooser
import pl.szczodrzynski.edziennik.utils.Colors.gradeNameToColor import pl.szczodrzynski.edziennik.utils.Colors.gradeNameToColor
import java.text.DecimalFormat import java.text.DecimalFormat
class GradesEditorAdapter( class GradesEditorAdapter(
private val mContext: Context, private val mContext: Context,
private val gradeList: List<GradesEditorFragment.EditorGrade>, private val gradeList: List<GradesEditorFragment.EditorGrade>,
private val listener: OnGradeActionListener private val fragment: GradesEditorFragment,
private val listener: OnGradeActionListener,
) : RecyclerView.Adapter<GradesEditorAdapter.ViewHolder>() { ) : RecyclerView.Adapter<GradesEditorAdapter.ViewHolder>() {
interface OnGradeActionListener { interface OnGradeActionListener {
@ -94,7 +94,7 @@ class GradesEditorAdapter(
holder.buttonRemove.setOnClickListener { listener.onClickRemove(editorGrade.id) } holder.buttonRemove.setOnClickListener { listener.onClickRemove(editorGrade.id) }
holder.buttonEdit.setOnClickListener { v -> modifyGradeChooser(v, editorGrade) { listener.onClickEdit(editorGrade.id) } } holder.buttonEdit.setOnClickListener { v -> fragment.modifyGradeChooser(v, editorGrade) { listener.onClickEdit(editorGrade.id) } }
} }
override fun getItemCount(): Int { override fun getItemCount(): Int {

View File

@ -8,7 +8,6 @@ import android.view.View
import androidx.appcompat.widget.PopupMenu import androidx.appcompat.widget.PopupMenu
import androidx.lifecycle.Observer import androidx.lifecycle.Observer
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import pl.szczodrzynski.edziennik.App import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.MainActivity import pl.szczodrzynski.edziennik.MainActivity
import pl.szczodrzynski.edziennik.R import pl.szczodrzynski.edziennik.R
@ -21,7 +20,7 @@ import pl.szczodrzynski.edziennik.databinding.FragmentGradesEditorBinding
import pl.szczodrzynski.edziennik.ext.getFloat import pl.szczodrzynski.edziennik.ext.getFloat
import pl.szczodrzynski.edziennik.ext.getInt import pl.szczodrzynski.edziennik.ext.getInt
import pl.szczodrzynski.edziennik.ext.getLong import pl.szczodrzynski.edziennik.ext.getLong
import pl.szczodrzynski.edziennik.ext.input import pl.szczodrzynski.edziennik.ui.base.dialog.SimpleDialog
import pl.szczodrzynski.edziennik.ui.base.fragment.BaseFragment import pl.szczodrzynski.edziennik.ui.base.fragment.BaseFragment
import pl.szczodrzynski.edziennik.utils.Colors import pl.szczodrzynski.edziennik.utils.Colors
import timber.log.Timber import timber.log.Timber
@ -59,11 +58,13 @@ class GradesEditorFragment : BaseFragment<FragmentGradesEditorBinding, MainActiv
semester = arguments.getInt("semester", 1) semester = arguments.getInt("semester", 1)
if (subjectId == -1L) { if (subjectId == -1L) {
MaterialAlertDialogBuilder(activity) SimpleDialog<Unit>(activity) {
.setTitle(R.string.error_occured) title(R.string.error_occured)
.setMessage(R.string.error_no_subject_id) message(R.string.error_no_subject_id)
.setPositiveButton(R.string.ok) { _, _ -> activity.navigateUp() } positive(R.string.ok) {
.show() activity.navigateUp()
}
}.show()
return return
} }
@ -78,7 +79,7 @@ class GradesEditorFragment : BaseFragment<FragmentGradesEditorBinding, MainActiv
b.listView.setHasFixedSize(false) b.listView.setHasFixedSize(false)
b.listView.isNestedScrollingEnabled = false b.listView.isNestedScrollingEnabled = false
b.listView.layoutManager = LinearLayoutManager(context) b.listView.layoutManager = LinearLayoutManager(context)
b.listView.adapter = GradesEditorAdapter(context!!, editorGrades, object : GradesEditorAdapter.OnGradeActionListener { b.listView.adapter = GradesEditorAdapter(requireContext(), editorGrades, this, object : GradesEditorAdapter.OnGradeActionListener {
override fun onClickRemove(gradeId: Long) { override fun onClickRemove(gradeId: Long) {
gradeSumSemester = 0f gradeSumSemester = 0f
gradeCountSemester = 0f gradeCountSemester = 0f
@ -179,11 +180,13 @@ class GradesEditorFragment : BaseFragment<FragmentGradesEditorBinding, MainActiv
app.db.subjectDao().getById(App.profileId, subjectId).observe(this, Observer { subject -> app.db.subjectDao().getById(App.profileId, subjectId).observe(this, Observer { subject ->
if (subject == null || subject.id == -1L) { if (subject == null || subject.id == -1L) {
MaterialAlertDialogBuilder(activity) SimpleDialog<Unit>(activity) {
.setTitle(R.string.error_occured) title(R.string.error_occured)
.setMessage(R.string.error_no_subject_id) message(R.string.error_no_subject_id)
.setPositiveButton(R.string.ok) { _, _ -> activity.navigateUp() } positive(R.string.ok) {
.show() activity.navigateUp()
}
}.show()
return@Observer return@Observer
} }
@ -248,98 +251,92 @@ class GradesEditorFragment : BaseFragment<FragmentGradesEditorBinding, MainActiv
var weight: Float var weight: Float
) )
companion object { fun modifyGradeChooser(v: View, editorGrade: EditorGrade, callback: () -> Unit) {
fun modifyGradeChooser(v: View, editorGrade: EditorGrade, callback: () -> Unit) { val popup = PopupMenu(v.context, v)
val popup = PopupMenu(v.context, v) popup.menu.add(0, 0, 0, R.string.grades_editor_change_grade)
popup.menu.add(0, 0, 0, R.string.grades_editor_change_grade) popup.menu.add(0, 1, 1, R.string.grades_editor_change_weight)
popup.menu.add(0, 1, 1, R.string.grades_editor_change_weight)
popup.setOnMenuItemClickListener { item -> popup.setOnMenuItemClickListener { item ->
if (item.itemId == 0) { if (item.itemId == 0) {
modifyGradeName(v, editorGrade, callback) modifyGradeName(v, editorGrade, callback)
}
if (item.itemId == 1) {
modifyGradeWeight(v, editorGrade, callback)
}
true
} }
if (item.itemId == 1) {
popup.show()
}
fun addGradeHandler(v: View, editorGrade: EditorGrade, callback: () -> Unit) {
modifyGradeName(v, editorGrade) {
modifyGradeWeight(v, editorGrade, callback) modifyGradeWeight(v, editorGrade, callback)
} }
true
} }
fun modifyGradeName(v: View, editorGrade: EditorGrade, callback: () -> Unit) { popup.show()
val popup = PopupMenu(v.context, v) }
popup.menu.add(0, 75, 0, "1-")
popup.menu.add(0, 100, 1, "1")
popup.menu.add(0, 150, 2, "1+")
popup.menu.add(0, 175, 3, "2-")
popup.menu.add(0, 200, 4, "2")
popup.menu.add(0, 250, 5, "2+")
popup.menu.add(0, 275, 6, "3-")
popup.menu.add(0, 300, 7, "3")
popup.menu.add(0, 350, 8, "3+")
popup.menu.add(0, 375, 9, "4-")
popup.menu.add(0, 400, 10, "4")
popup.menu.add(0, 450, 11, "4+")
popup.menu.add(0, 475, 12, "5-")
popup.menu.add(0, 500, 13, "5")
popup.menu.add(0, 550, 14, "5+")
popup.menu.add(0, 575, 15, "6-")
popup.menu.add(0, 600, 16, "6")
popup.menu.add(0, 650, 17, "6+")
popup.menu.add(0, 0, 18, "0")
popup.setOnMenuItemClickListener { item -> fun addGradeHandler(v: View, editorGrade: EditorGrade, callback: () -> Unit) {
editorGrade.name = item.title.toString() modifyGradeName(v, editorGrade) {
editorGrade.value = item.itemId.toFloat() / 100 modifyGradeWeight(v, editorGrade, callback)
callback()
true
}
popup.show()
}
fun modifyGradeWeight(v: View, editorGrade: EditorGrade, callback: () -> Unit) {
val popup = PopupMenu(v.context, v)
for (i in 0..6) {
popup.menu.add(0, i, i, v.context.getString(R.string.grades_editor_weight_format, DecimalFormat("#.##").format(i.toLong())))
}
popup.menu.add(1, 100, 100, v.context.getString(R.string.grades_editor_weight_other))
popup.setOnMenuItemClickListener { item ->
if (item.itemId == 100) {
MaterialAlertDialogBuilder(v.context)
.setTitle(R.string.grades_editor_add_grade_title)
.input(
message = v.context.getString(R.string.grades_editor_add_grade_weight),
type = InputType.TYPE_NUMBER_FLAG_SIGNED,
positiveButton = R.string.ok,
positiveListener = { _, input ->
try {
editorGrade.weight = input.toFloat()
callback()
} catch (e: Exception) {
Timber.e(e)
}
true
}
)
.setNegativeButton(R.string.cancel, null)
.show()
} else {
editorGrade.weight = item.itemId.toFloat()
callback()
}
true
}
popup.show()
} }
} }
fun modifyGradeName(v: View, editorGrade: EditorGrade, callback: () -> Unit) {
val popup = PopupMenu(v.context, v)
popup.menu.add(0, 75, 0, "1-")
popup.menu.add(0, 100, 1, "1")
popup.menu.add(0, 150, 2, "1+")
popup.menu.add(0, 175, 3, "2-")
popup.menu.add(0, 200, 4, "2")
popup.menu.add(0, 250, 5, "2+")
popup.menu.add(0, 275, 6, "3-")
popup.menu.add(0, 300, 7, "3")
popup.menu.add(0, 350, 8, "3+")
popup.menu.add(0, 375, 9, "4-")
popup.menu.add(0, 400, 10, "4")
popup.menu.add(0, 450, 11, "4+")
popup.menu.add(0, 475, 12, "5-")
popup.menu.add(0, 500, 13, "5")
popup.menu.add(0, 550, 14, "5+")
popup.menu.add(0, 575, 15, "6-")
popup.menu.add(0, 600, 16, "6")
popup.menu.add(0, 650, 17, "6+")
popup.menu.add(0, 0, 18, "0")
popup.setOnMenuItemClickListener { item ->
editorGrade.name = item.title.toString()
editorGrade.value = item.itemId.toFloat() / 100
callback()
true
}
popup.show()
}
fun modifyGradeWeight(v: View, editorGrade: EditorGrade, callback: () -> Unit) {
val popup = PopupMenu(v.context, v)
for (i in 0..6) {
popup.menu.add(0, i, i, v.context.getString(R.string.grades_editor_weight_format, DecimalFormat("#.##").format(i.toLong())))
}
popup.menu.add(1, 100, 100, v.context.getString(R.string.grades_editor_weight_other))
popup.setOnMenuItemClickListener { item ->
if (item.itemId == 100) {
SimpleDialog<Unit>(activity) {
title(R.string.grades_editor_add_grade_title)
message(R.string.grades_editor_add_grade_weight)
input(InputType.TYPE_NUMBER_FLAG_SIGNED)
positive(R.string.ok) {
try {
editorGrade.weight = getInput()?.text?.toString()?.toFloat() ?: 0.0f
callback()
} catch (e: Exception) {
Timber.e(e)
}
}
negative(R.string.cancel)
}.show()
} else {
editorGrade.weight = item.itemId.toFloat()
callback()
}
true
}
popup.show()
}
} }

View File

@ -10,11 +10,11 @@ import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import pl.szczodrzynski.edziennik.App import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.R import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.databinding.GradesItemStatsBinding import pl.szczodrzynski.edziennik.databinding.GradesItemStatsBinding
import pl.szczodrzynski.edziennik.ext.onClick import pl.szczodrzynski.edziennik.ext.onClick
import pl.szczodrzynski.edziennik.ui.base.dialog.SimpleDialog
import pl.szczodrzynski.edziennik.ui.dialogs.settings.GradesConfigDialog import pl.szczodrzynski.edziennik.ui.dialogs.settings.GradesConfigDialog
import pl.szczodrzynski.edziennik.ui.grades.GradesAdapter import pl.szczodrzynski.edziennik.ui.grades.GradesAdapter
import pl.szczodrzynski.edziennik.ui.grades.models.GradesStats import pl.szczodrzynski.edziennik.ui.grades.models.GradesStats
@ -95,11 +95,11 @@ class StatsViewHolder(
b.disclaimer.isVisible = !b.noData.isVisible b.disclaimer.isVisible = !b.noData.isVisible
b.helpButton.onClick { b.helpButton.onClick {
MaterialAlertDialogBuilder(activity) SimpleDialog<Unit>(activity) {
.setTitle(R.string.grades_stats_help_title) title(R.string.grades_stats_help_title)
.setMessage(R.string.grades_stats_help_text) message(R.string.grades_stats_help_text)
.setPositiveButton(R.string.ok, null) positive(R.string.ok)
.show() }.show()
} }
b.customValueDivider.isVisible = manager.dontCountEnabled || manager.plusValue != null || manager.minusValue != null b.customValueDivider.isVisible = manager.dontCountEnabled || manager.plusValue != null || manager.minusValue != null

View File

@ -18,11 +18,7 @@ import pl.szczodrzynski.edziennik.ui.home.HomeCard.Companion.CARD_TIMETABLE
class HomeConfigDialog( class HomeConfigDialog(
activity: AppCompatActivity, activity: AppCompatActivity,
private val reloadOnDismiss: Boolean = true, private val reloadOnDismiss: Boolean = true,
onShowListener: ((tag: String) -> Unit)? = null, ) : BaseDialog<Any>(activity) {
onDismissListener: ((tag: String) -> Unit)? = null,
) : BaseDialog<Any>(activity, onShowListener, onDismissListener) {
override val TAG = "HomeConfigDialog"
override fun getTitleRes() = R.string.home_configure_add_remove override fun getTitleRes() = R.string.home_configure_add_remove
override fun getPositiveButtonText() = R.string.ok override fun getPositiveButtonText() = R.string.ok
@ -42,8 +38,6 @@ class HomeConfigDialog(
.map { it.cardId } .map { it.cardId }
.toSet() .toSet()
override suspend fun onShow() = Unit
private var configChanged = false private var configChanged = false
override suspend fun onPositiveClick(): Boolean { override suspend fun onPositiveClick(): Boolean {
@ -59,11 +53,11 @@ class HomeConfigDialog(
return DISMISS return DISMISS
} }
override suspend fun onMultiSelectionChanged(items: Set<Any>) { override suspend fun onMultiSelectionChanged(item: Any, isChecked: Boolean) {
configChanged = true configChanged = true
} }
override fun onDismiss() { override suspend fun onDismiss() {
if (configChanged && reloadOnDismiss && activity is MainActivity) if (configChanged && reloadOnDismiss && activity is MainActivity)
activity.reloadTarget() activity.reloadTarget()
} }

View File

@ -91,9 +91,7 @@ class HomeFragment : BaseFragment<FragmentHomeBinding, MainActivity>(
.withIcon(SzkolnyFont.Icon.szf_clipboard_list_outline) .withIcon(SzkolnyFont.Icon.szf_clipboard_list_outline)
.withOnClickListener { .withOnClickListener {
activity.bottomSheet.close() activity.bottomSheet.close()
StudentNumberDialog(activity, app.profile) { StudentNumberDialog(activity, app.profile).show()
app.profileSave()
}
}, },
BottomSheetSeparatorItem(true), BottomSheetSeparatorItem(true),
BottomSheetPrimaryItem(true) BottomSheetPrimaryItem(true)

View File

@ -9,16 +9,21 @@ import android.view.ViewGroup
import android.widget.FrameLayout import android.widget.FrameLayout
import androidx.core.view.plusAssign import androidx.core.view.plusAssign
import androidx.core.view.setMargins import androidx.core.view.setMargins
import com.google.android.material.dialog.MaterialAlertDialogBuilder import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.* import kotlinx.coroutines.Dispatchers
import pl.szczodrzynski.edziennik.* import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.MainActivity
import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.data.db.entity.Profile import pl.szczodrzynski.edziennik.data.db.entity.Profile
import pl.szczodrzynski.edziennik.data.enums.NavTarget
import pl.szczodrzynski.edziennik.databinding.CardHomeArchiveBinding import pl.szczodrzynski.edziennik.databinding.CardHomeArchiveBinding
import pl.szczodrzynski.edziennik.ext.dp import pl.szczodrzynski.edziennik.ext.dp
import pl.szczodrzynski.edziennik.ext.onClick import pl.szczodrzynski.edziennik.ext.onClick
import pl.szczodrzynski.edziennik.ext.setMessage
import pl.szczodrzynski.edziennik.ext.setText import pl.szczodrzynski.edziennik.ext.setText
import pl.szczodrzynski.edziennik.data.enums.NavTarget import pl.szczodrzynski.edziennik.ui.base.dialog.SimpleDialog
import pl.szczodrzynski.edziennik.ui.home.HomeCard import pl.szczodrzynski.edziennik.ui.home.HomeCard
import pl.szczodrzynski.edziennik.ui.home.HomeCardAdapter import pl.szczodrzynski.edziennik.ui.home.HomeCardAdapter
import pl.szczodrzynski.edziennik.ui.home.HomeFragment import pl.szczodrzynski.edziennik.ui.home.HomeFragment
@ -61,14 +66,17 @@ class HomeArchiveCard(
} }
} }
if (profile == null) { if (profile == null) {
MaterialAlertDialogBuilder(activity) SimpleDialog<Unit>(activity) {
.setTitle(R.string.home_archive_close_no_target_title) title(R.string.home_archive_close_no_target_title)
.setMessage(R.string.home_archive_close_no_target_text, this@HomeArchiveCard.profile.name) message(
.setPositiveButton(R.string.ok) { _, _ -> R.string.home_archive_close_no_target_text,
activity.drawer.profileSelectionOpen() this@HomeArchiveCard.profile.name
activity.drawer.open() )
} positive(R.string.ok) {
.show() activity.drawer.profileSelectionOpen()
activity.drawer.open()
}
}.show()
return@launch return@launch
} }
activity.navigate(profile = profile) activity.navigate(profile = profile)

View File

@ -31,6 +31,7 @@ import pl.szczodrzynski.edziennik.ui.home.HomeCard
import pl.szczodrzynski.edziennik.ui.home.HomeCardAdapter import pl.szczodrzynski.edziennik.ui.home.HomeCardAdapter
import pl.szczodrzynski.edziennik.ui.home.HomeFragment import pl.szczodrzynski.edziennik.ui.home.HomeFragment
import pl.szczodrzynski.edziennik.utils.models.Date import pl.szczodrzynski.edziennik.utils.models.Date
import timber.log.Timber
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
class HomeLuckyNumberCard( class HomeLuckyNumberCard(
@ -101,14 +102,14 @@ class HomeLuckyNumberCard(
}) })
holder.root.onClick { holder.root.onClick {
StudentNumberDialog(activity, profile, onDismissListener = { this@HomeLuckyNumberCard.launch {
app.profileSave(profile) StudentNumberDialog(activity, profile).showModal()
val newSubTextRes = if (profile.studentNumber == -1) val newSubTextRes = if (profile.studentNumber == -1)
R.string.home_lucky_number_details_click_to_set R.string.home_lucky_number_details_click_to_set
else else
R.string.home_lucky_number_details R.string.home_lucky_number_details
b.subText.setText(newSubTextRes, profile.studentNumber) b.subText.setText(newSubTextRes, profile.studentNumber)
}) }
} }
}} }}

View File

@ -10,7 +10,6 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.navigation.NavOptions import androidx.navigation.NavOptions
import androidx.navigation.Navigation import androidx.navigation.Navigation
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
@ -20,6 +19,7 @@ import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.data.api.models.ApiError import pl.szczodrzynski.edziennik.data.api.models.ApiError
import pl.szczodrzynski.edziennik.data.db.entity.LoginStore import pl.szczodrzynski.edziennik.data.db.entity.LoginStore
import pl.szczodrzynski.edziennik.databinding.LoginActivityBinding import pl.szczodrzynski.edziennik.databinding.LoginActivityBinding
import pl.szczodrzynski.edziennik.ui.base.dialog.SimpleDialog
import pl.szczodrzynski.edziennik.ui.main.ErrorSnackbar import pl.szczodrzynski.edziennik.ui.main.ErrorSnackbar
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
@ -72,15 +72,15 @@ class LoginActivity : AppCompatActivity(), CoroutineScope {
return return
} }
if (destination.id == R.id.loginSummaryFragment) { if (destination.id == R.id.loginSummaryFragment) {
MaterialAlertDialogBuilder(this) SimpleDialog<Unit>(this) {
.setTitle(R.string.are_you_sure) title(R.string.are_you_sure)
.setMessage(R.string.login_cancel_confirmation) message(R.string.login_cancel_confirmation)
.setPositiveButton(R.string.yes) { _, _ -> positive(R.string.yes) {
setResult(Activity.RESULT_CANCELED) setResult(Activity.RESULT_CANCELED)
finish() finish()
} }
.setNegativeButton(R.string.no, null) negative(R.string.no)
.show() }.show()
return return
} }
nav.navigateUp() nav.navigateUp()

View File

@ -16,25 +16,31 @@ import android.view.ViewGroup
import android.view.animation.AccelerateDecelerateInterpolator import android.view.animation.AccelerateDecelerateInterpolator
import android.view.animation.Animation import android.view.animation.Animation
import android.view.animation.RotateAnimation import android.view.animation.RotateAnimation
import android.widget.TextView
import android.widget.Toast import android.widget.Toast
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import com.google.android.material.dialog.MaterialAlertDialogBuilder import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.* import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import pl.szczodrzynski.edziennik.App import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.R import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.core.manager.AvailabilityManager.Error.Type
import pl.szczodrzynski.edziennik.data.enums.LoginMode import pl.szczodrzynski.edziennik.data.enums.LoginMode
import pl.szczodrzynski.edziennik.data.enums.LoginType import pl.szczodrzynski.edziennik.data.enums.LoginType
import pl.szczodrzynski.edziennik.databinding.LoginChooserFragmentBinding import pl.szczodrzynski.edziennik.databinding.LoginChooserFragmentBinding
import pl.szczodrzynski.edziennik.ext.* import pl.szczodrzynski.edziennik.ext.Bundle
import pl.szczodrzynski.edziennik.ext.onClick
import pl.szczodrzynski.edziennik.ext.resolveColor
import pl.szczodrzynski.edziennik.ext.setText
import pl.szczodrzynski.edziennik.ext.setTintColor
import pl.szczodrzynski.edziennik.ui.base.dialog.SimpleDialog
import pl.szczodrzynski.edziennik.ui.dialogs.sync.RegisterUnavailableDialog import pl.szczodrzynski.edziennik.ui.dialogs.sync.RegisterUnavailableDialog
import pl.szczodrzynski.edziennik.ui.feedback.FeedbackActivity import pl.szczodrzynski.edziennik.ui.feedback.FeedbackActivity
import pl.szczodrzynski.edziennik.utils.BetterLinkMovementMethod
import pl.szczodrzynski.edziennik.utils.SimpleDividerItemDecoration import pl.szczodrzynski.edziennik.utils.SimpleDividerItemDecoration
import pl.szczodrzynski.edziennik.utils.html.BetterHtml import pl.szczodrzynski.edziennik.utils.html.BetterHtml
import pl.szczodrzynski.edziennik.core.manager.AvailabilityManager.Error.Type
import pl.szczodrzynski.edziennik.utils.models.Date import pl.szczodrzynski.edziennik.utils.models.Date
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
@ -252,19 +258,15 @@ class LoginChooserFragment : Fragment(), CoroutineScope {
} }
if (!app.config.privacyPolicyAccepted) { if (!app.config.privacyPolicyAccepted) {
MaterialAlertDialogBuilder(activity) SimpleDialog<Unit>(activity) {
.setTitle(R.string.privacy_policy) title(R.string.privacy_policy)
.setMessage(BetterHtml.fromHtml(activity, R.string.privacy_policy_dialog_html)) message(BetterHtml.fromHtml(activity, R.string.privacy_policy_dialog_html))
.setPositiveButton(R.string.i_agree) { _, _ -> positive(R.string.i_agree) {
app.config.privacyPolicyAccepted = true app.config.privacyPolicyAccepted = true
onLoginModeClicked(loginType, loginMode) onLoginModeClicked(loginType, loginMode)
} }
.setNegativeButton(R.string.i_disagree, null) negative(R.string.i_disagree)
.show() }.show()
.also { dialog ->
dialog.findViewById<TextView>(android.R.id.message)?.movementMethod =
BetterLinkMovementMethod.getInstance()
}
return return
} }
@ -273,14 +275,14 @@ class LoginChooserFragment : Fragment(), CoroutineScope {
return@launch return@launch
if (loginMode.isTesting || loginMode.isDevOnly) { if (loginMode.isTesting || loginMode.isDevOnly) {
MaterialAlertDialogBuilder(activity) SimpleDialog<Unit>(activity) {
.setTitle(R.string.login_chooser_testing_title) title(R.string.login_chooser_testing_title)
.setMessage(R.string.login_chooser_testing_text) message(R.string.login_chooser_testing_text)
.setPositiveButton(R.string.ok) { _, _ -> positive(R.string.ok) {
navigateToLoginMode(loginType, loginMode) navigateToLoginMode(loginType, loginMode)
} }
.setNegativeButton(R.string.cancel, null) negative(R.string.cancel)
.show() }.show()
return@launch return@launch
} }

View File

@ -5,13 +5,11 @@
package pl.szczodrzynski.edziennik.ui.login package pl.szczodrzynski.edziennik.ui.login
import android.os.Bundle import android.os.Bundle
import android.os.Process
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import coil.load import coil.load
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
@ -20,8 +18,9 @@ import pl.szczodrzynski.edziennik.BuildConfig
import pl.szczodrzynski.edziennik.R import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.databinding.LoginPrizeFragmentBinding import pl.szczodrzynski.edziennik.databinding.LoginPrizeFragmentBinding
import pl.szczodrzynski.edziennik.ext.onClick import pl.szczodrzynski.edziennik.ext.onClick
import pl.szczodrzynski.edziennik.ui.base.dialog.SimpleDialog
import pl.szczodrzynski.edziennik.ui.dialogs.RestartDialog
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
import kotlin.system.exitProcess
class LoginPrizeFragment : Fragment(), CoroutineScope { class LoginPrizeFragment : Fragment(), CoroutineScope {
companion object { companion object {
@ -50,29 +49,20 @@ class LoginPrizeFragment : Fragment(), CoroutineScope {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
b.button.load("https://szkolny.eu/game/button.png") b.button.load("https://szkolny.eu/game/button.png")
b.button.onClick { b.button.onClick {
MaterialAlertDialogBuilder(activity) SimpleDialog<Unit>(activity) {
.setTitle(R.string.are_you_sure) title(R.string.are_you_sure)
.setMessage(R.string.dev_mode_enable_warning) message(R.string.dev_mode_enable_warning)
.setPositiveButton(R.string.yes) { _, _ -> positive(R.string.yes) {
app.config.devMode = true app.config.devMode = true
App.devMode = true App.devMode = true
MaterialAlertDialogBuilder(activity) RestartDialog(activity).show()
.setTitle("Restart") }
.setMessage("Wymagany restart aplikacji") negative(R.string.no) {
.setPositiveButton(R.string.ok) { _, _ -> app.config.devMode = BuildConfig.DEBUG
Process.killProcess(Process.myPid()) App.devMode = BuildConfig.DEBUG
Runtime.getRuntime().exit(0) activity.finish()
exitProcess(0) }
} }.show()
.setCancelable(false)
.show()
}
.setNegativeButton(R.string.no) { _, _ ->
app.config.devMode = BuildConfig.DEBUG
App.devMode = BuildConfig.DEBUG
activity.finish()
}
.show()
} }
} }
} }

View File

@ -9,7 +9,6 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
@ -19,6 +18,7 @@ import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode import org.greenrobot.eventbus.ThreadMode
import pl.szczodrzynski.edziennik.App import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.R import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.core.manager.UserActionManager
import pl.szczodrzynski.edziennik.data.api.ERROR_REQUIRES_USER_ACTION import pl.szczodrzynski.edziennik.data.api.ERROR_REQUIRES_USER_ACTION
import pl.szczodrzynski.edziennik.data.api.LOGIN_NO_ARGUMENTS import pl.szczodrzynski.edziennik.data.api.LOGIN_NO_ARGUMENTS
import pl.szczodrzynski.edziennik.data.api.edziennik.EdziennikTask import pl.szczodrzynski.edziennik.data.api.edziennik.EdziennikTask
@ -32,7 +32,7 @@ import pl.szczodrzynski.edziennik.data.enums.LoginType
import pl.szczodrzynski.edziennik.databinding.LoginProgressFragmentBinding import pl.szczodrzynski.edziennik.databinding.LoginProgressFragmentBinding
import pl.szczodrzynski.edziennik.ext.getEnum import pl.szczodrzynski.edziennik.ext.getEnum
import pl.szczodrzynski.edziennik.ext.joinNotNullStrings import pl.szczodrzynski.edziennik.ext.joinNotNullStrings
import pl.szczodrzynski.edziennik.core.manager.UserActionManager import pl.szczodrzynski.edziennik.ui.base.dialog.SimpleDialog
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
import kotlin.math.max import kotlin.math.max
@ -101,12 +101,14 @@ class LoginProgressFragment : Fragment(), CoroutineScope {
fun onFirstLoginFinishedEvent(event: FirstLoginFinishedEvent) { fun onFirstLoginFinishedEvent(event: FirstLoginFinishedEvent) {
EventBus.getDefault().removeStickyEvent(event) EventBus.getDefault().removeStickyEvent(event)
if (event.profileList.isEmpty()) { if (event.profileList.isEmpty()) {
MaterialAlertDialogBuilder(activity) SimpleDialog<Unit>(activity) {
.setTitle(R.string.login_account_no_students) title(R.string.login_account_no_students)
.setMessage(R.string.login_account_no_students_text) message(R.string.login_account_no_students_text)
.setPositiveButton(R.string.ok, null) positive(R.string.ok) {
.setOnDismissListener { nav.navigateUp() } nav.navigateUp()
.show() }
cancelable(false)
}.show()
return return
} }

View File

@ -10,15 +10,16 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import pl.szczodrzynski.edziennik.* import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.databinding.LoginSummaryFragmentBinding import pl.szczodrzynski.edziennik.databinding.LoginSummaryFragmentBinding
import pl.szczodrzynski.edziennik.ext.Bundle import pl.szczodrzynski.edziennik.ext.Bundle
import pl.szczodrzynski.edziennik.ext.onChange import pl.szczodrzynski.edziennik.ext.onChange
import pl.szczodrzynski.edziennik.ext.onClick import pl.szczodrzynski.edziennik.ext.onClick
import pl.szczodrzynski.edziennik.ui.base.dialog.SimpleDialog
import pl.szczodrzynski.edziennik.utils.SimpleDividerItemDecoration import pl.szczodrzynski.edziennik.utils.SimpleDividerItemDecoration
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
@ -64,12 +65,14 @@ class LoginSummaryFragment : Fragment(), CoroutineScope {
b.registerMeSwitch.onChange { _, isChecked -> b.registerMeSwitch.onChange { _, isChecked ->
if (isChecked) if (isChecked)
return@onChange return@onChange
MaterialAlertDialogBuilder(activity) SimpleDialog<Unit>(activity) {
.setTitle(R.string.login_summary_unregister_title) title(R.string.login_summary_unregister_title)
.setMessage(R.string.login_summary_unregister_text) message(R.string.login_summary_unregister_text)
.setPositiveButton(R.string.ok, null) positive(R.string.ok)
.setNegativeButton(R.string.cancel) { _, _ -> b.registerMeSwitch.isChecked = true } negative(R.string.cancel) {
.show() b.registerMeSwitch.isChecked = true
}
}.show()
} }
b.anotherButton.onClick { b.anotherButton.onClick {

View File

@ -9,21 +9,37 @@ import android.graphics.drawable.BitmapDrawable
import android.text.style.AbsoluteSizeSpan import android.text.style.AbsoluteSizeSpan
import android.text.style.ForegroundColorSpan import android.text.style.ForegroundColorSpan
import android.widget.Toast import android.widget.Toast
import com.google.android.material.dialog.MaterialAlertDialogBuilder import androidx.appcompat.app.AppCompatActivity
import com.hootsuite.nachos.ChipConfiguration import com.hootsuite.nachos.ChipConfiguration
import com.hootsuite.nachos.NachoTextView import com.hootsuite.nachos.NachoTextView
import com.hootsuite.nachos.chip.ChipInfo import com.hootsuite.nachos.chip.ChipInfo
import com.hootsuite.nachos.chip.ChipSpan import com.hootsuite.nachos.chip.ChipSpan
import com.hootsuite.nachos.chip.ChipSpanChipCreator import com.hootsuite.nachos.chip.ChipSpanChipCreator
import pl.szczodrzynski.edziennik.* import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.data.db.entity.Teacher import pl.szczodrzynski.edziennik.data.db.entity.Teacher
import pl.szczodrzynski.edziennik.ext.* import pl.szczodrzynski.edziennik.ext.asSpannable
import pl.szczodrzynski.edziennik.ext.concat
import pl.szczodrzynski.edziennik.ext.dp
import pl.szczodrzynski.edziennik.ext.resolveAttr
import pl.szczodrzynski.edziennik.ext.toColorStateList
import pl.szczodrzynski.edziennik.ui.base.dialog.SimpleDialog
import pl.szczodrzynski.edziennik.ui.messages.MessagesUtils import pl.szczodrzynski.edziennik.ui.messages.MessagesUtils
import pl.szczodrzynski.edziennik.utils.Colors import pl.szczodrzynski.edziennik.utils.Colors
import pl.szczodrzynski.navlib.elevateSurface import pl.szczodrzynski.navlib.elevateSurface
import kotlin.collections.List
import kotlin.collections.firstOrNull
import kotlin.collections.forEach
import kotlin.collections.listOf
import kotlin.collections.listOfNotNull
import kotlin.collections.mutableListOf
import kotlin.collections.mutableMapOf
import kotlin.collections.mutableSetOf
import kotlin.collections.plusAssign
import kotlin.collections.set
import kotlin.collections.sortedBy
class MessagesComposeChipCreator( class MessagesComposeChipCreator(
private val context: Context, private val activity: AppCompatActivity,
private val nacho: NachoTextView, private val nacho: NachoTextView,
private val teacherList: List<Teacher>, private val teacherList: List<Teacher>,
) : ChipSpanChipCreator() { ) : ChipSpanChipCreator() {
@ -69,14 +85,12 @@ class MessagesComposeChipCreator(
else else
adapter.originalList adapter.originalList
val category = mutableListOf<Teacher>() val multiChoiceItems = mutableMapOf<CharSequence, Teacher>()
val categoryNames = mutableListOf<CharSequence>() val defaultSelectedItems = mutableSetOf<Teacher>()
val categoryCheckedItems = mutableListOf<Boolean>()
teachers.forEach { teacher -> teachers.forEach { teacher ->
if (!teacher.isType(type)) if (!teacher.isType(type))
return@forEach return@forEach
category += teacher
val name = teacher.fullName val name = teacher.fullName
val description = when (type) { val description = when (type) {
Teacher.TYPE_TEACHER -> null Teacher.TYPE_TEACHER -> null
@ -94,7 +108,7 @@ class MessagesComposeChipCreator(
Teacher.TYPE_SPECIALIST -> null Teacher.TYPE_SPECIALIST -> null
else -> teacher.typeDescription else -> teacher.typeDescription
} }
categoryNames += listOfNotNull( val displayName = listOfNotNull(
name.asSpannable( name.asSpannable(
ForegroundColorSpan(textColorPrimary) ForegroundColorSpan(textColorPrimary)
), ),
@ -103,21 +117,19 @@ class MessagesComposeChipCreator(
AbsoluteSizeSpan(14.dp) AbsoluteSizeSpan(14.dp)
) )
).concat("\n") ).concat("\n")
multiChoiceItems[displayName] = teacher
// check the teacher if already added as a recipient // check the teacher if already added as a recipient
categoryCheckedItems += nacho.allChips.firstOrNull { it.data == teacher } != null if (nacho.allChips.firstOrNull { it.data == teacher } != null)
defaultSelectedItems += teacher
} }
MaterialAlertDialogBuilder(context) SimpleDialog<Teacher>(activity) {
.setTitle("Dodaj odbiorców - " + Teacher.typeName(context, type)) title("Dodaj odbiorców - " + Teacher.typeName(context, type))
//.setMessage(getString(R.string.messages_compose_recipients_text_format, Teacher.typeName(activity, type))) message(R.string.messages_compose_recipients_text_format, Teacher.typeName(activity, type))
.setPositiveButton("OK", null) positive(R.string.ok)
.setNeutralButton("Anuluj", null) negative(R.string.cancel)
.setMultiChoiceItems( multi(multiChoiceItems, defaultSelectedItems) { teacher, isChecked ->
categoryNames.toTypedArray(),
categoryCheckedItems.toBooleanArray()
) { _, which, isChecked ->
val teacher = category[which]
if (isChecked) { if (isChecked) {
val chipInfoList = mutableListOf<ChipInfo>() val chipInfoList = mutableListOf<ChipInfo>()
teacher.image = teacher.image =
@ -131,13 +143,13 @@ class MessagesComposeChipCreator(
} }
} }
} }
.show() }.show()
return null return null
} }
override fun configureChip(chip: ChipSpan, chipConfiguration: ChipConfiguration) { override fun configureChip(chip: ChipSpan, chipConfiguration: ChipConfiguration) {
super.configureChip(chip, chipConfiguration) super.configureChip(chip, chipConfiguration)
chip.setBackgroundColor(elevateSurface(context, 8).toColorStateList()) chip.setBackgroundColor(elevateSurface(activity, 8).toColorStateList())
chip.setTextColor(android.R.attr.textColorPrimary.resolveAttr(context)) chip.setTextColor(android.R.attr.textColorPrimary.resolveAttr(activity))
} }
} }

View File

@ -4,20 +4,20 @@
package pl.szczodrzynski.edziennik.ui.messages.compose package pl.szczodrzynski.edziennik.ui.messages.compose
import android.content.Context import androidx.appcompat.app.AppCompatActivity
import com.hootsuite.nachos.NachoTextView import com.hootsuite.nachos.NachoTextView
import com.hootsuite.nachos.chip.ChipSpan import com.hootsuite.nachos.chip.ChipSpan
import com.hootsuite.nachos.tokenizer.SpanChipTokenizer import com.hootsuite.nachos.tokenizer.SpanChipTokenizer
import pl.szczodrzynski.edziennik.data.db.entity.Teacher import pl.szczodrzynski.edziennik.data.db.entity.Teacher
class MessagesComposeChipTokenizer( class MessagesComposeChipTokenizer(
context: Context, activity: AppCompatActivity,
nacho: NachoTextView, nacho: NachoTextView,
teacherList: List<Teacher>, teacherList: List<Teacher>,
) : SpanChipTokenizer<ChipSpan>( ) : SpanChipTokenizer<ChipSpan>(
context, activity,
MessagesComposeChipCreator( MessagesComposeChipCreator(
context = context, activity = activity,
nacho = nacho, nacho = nacho,
teacherList = teacherList teacherList = teacherList
), ),

View File

@ -12,7 +12,6 @@ import android.widget.ScrollView
import android.widget.Toast import android.widget.Toast
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.core.widget.addTextChangedListener import androidx.core.widget.addTextChangedListener
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -39,6 +38,7 @@ import pl.szczodrzynski.edziennik.data.enums.NavTarget
import pl.szczodrzynski.edziennik.databinding.MessagesComposeFragmentBinding import pl.szczodrzynski.edziennik.databinding.MessagesComposeFragmentBinding
import pl.szczodrzynski.edziennik.ext.Bundle import pl.szczodrzynski.edziennik.ext.Bundle
import pl.szczodrzynski.edziennik.ext.DAY import pl.szczodrzynski.edziennik.ext.DAY
import pl.szczodrzynski.edziennik.ui.base.dialog.SimpleDialog
import pl.szczodrzynski.edziennik.ui.base.fragment.BaseFragment import pl.szczodrzynski.edziennik.ui.base.fragment.BaseFragment
import pl.szczodrzynski.edziennik.ui.dialogs.settings.MessagesConfigDialog import pl.szczodrzynski.edziennik.ui.dialogs.settings.MessagesConfigDialog
import pl.szczodrzynski.edziennik.ui.messages.list.MessagesFragment import pl.szczodrzynski.edziennik.ui.messages.list.MessagesFragment
@ -75,7 +75,7 @@ class MessagesComposeFragment : BaseFragment<MessagesComposeFragmentBinding, Mai
.withIcon(CommunityMaterial.Icon.cmd_cog_outline) .withIcon(CommunityMaterial.Icon.cmd_cog_outline)
.withOnClickListener { .withOnClickListener {
activity.bottomSheet.close() activity.bottomSheet.close()
MessagesConfigDialog(activity, false, null, null).show() MessagesConfigDialog(activity, false).show()
} }
) )
@ -251,18 +251,18 @@ class MessagesComposeFragment : BaseFragment<MessagesComposeFragmentBinding, Mai
} }
private fun saveDraftDialog() { private fun saveDraftDialog() {
MaterialAlertDialogBuilder(activity) SimpleDialog<Unit>(activity) {
.setTitle(R.string.messages_compose_save_draft_title) title(R.string.messages_compose_save_draft_title)
.setMessage(R.string.messages_compose_save_draft_text) message(R.string.messages_compose_save_draft_text)
.setPositiveButton(R.string.save) { _, _ -> positive(R.string.save) {
saveDraft() saveDraft()
MessagesFragment.pageSelection = Message.TYPE_DRAFT MessagesFragment.pageSelection = Message.TYPE_DRAFT
activity.navigate(navTarget = NavTarget.MESSAGES, skipBeforeNavigate = true) activity.navigate(navTarget = NavTarget.MESSAGES, skipBeforeNavigate = true)
} }
.setNegativeButton(R.string.discard) { _, _ -> negative(R.string.discard) {
activity.resumePausedNavigation() activity.resumePausedNavigation()
} }
.show() }.show()
} }
private fun saveDraft() { private fun saveDraft() {
@ -279,19 +279,21 @@ class MessagesComposeFragment : BaseFragment<MessagesComposeFragmentBinding, Mai
} }
private fun discardDraftDialog() { private fun discardDraftDialog() {
MaterialAlertDialogBuilder(activity) SimpleDialog<Unit>(activity) {
.setTitle(R.string.messages_compose_discard_draft_title) title(R.string.messages_compose_discard_draft_title)
.setMessage(R.string.messages_compose_discard_draft_text) message(R.string.messages_compose_discard_draft_text)
.setPositiveButton(R.string.remove) { _, _ -> positive(R.string.remove) {
launch { if (draftMessageId != null)
if (draftMessageId != null) manager.deleteDraft(App.profileId, draftMessageId!!)
manager.deleteDraft(App.profileId, draftMessageId!!) Toast.makeText(
Toast.makeText(activity, R.string.messages_compose_draft_discarded, Toast.LENGTH_SHORT).show() activity,
activity.navigateUp(skipBeforeNavigate = true) R.string.messages_compose_draft_discarded,
} Toast.LENGTH_SHORT
).show()
activity.navigateUp(skipBeforeNavigate = true)
} }
.setNegativeButton(R.string.cancel, null) negative(R.string.cancel)
.show() }.show()
} }
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
@ -389,14 +391,15 @@ class MessagesComposeFragment : BaseFragment<MessagesComposeFragmentBinding, Mai
activity.bottomSheet.hideKeyboard() activity.bottomSheet.hideKeyboard()
MaterialAlertDialogBuilder(activity) SimpleDialog<Unit>(activity) {
.setTitle(R.string.messages_compose_confirm_title) title(R.string.messages_compose_confirm_title)
.setMessage(R.string.messages_compose_confirm_text) message(R.string.messages_compose_confirm_text)
.setPositiveButton(R.string.send) { _, _ -> positive(R.string.send) {
EdziennikTask.messageSend(App.profileId, recipients, subject.trim(), body).enqueue(activity) EdziennikTask.messageSend(App.profileId, recipients, subject.trim(), body)
} .enqueue(activity)
.setNegativeButton(R.string.cancel, null) }
.show() negative(R.string.cancel)
}
} }
override fun onResume() { override fun onResume() {

View File

@ -33,7 +33,7 @@ class MessagesFragment : PagerFragment<BasePagerFragmentBinding, MainActivity>(
.withIcon(CommunityMaterial.Icon.cmd_cog_outline) .withIcon(CommunityMaterial.Icon.cmd_cog_outline)
.withOnClickListener { .withOnClickListener {
activity.bottomSheet.close() activity.bottomSheet.close()
MessagesConfigDialog(activity, false, null, null).show() MessagesConfigDialog(activity, false).show()
} }
) )

View File

@ -8,7 +8,6 @@ import android.os.Bundle
import android.view.View import android.view.View
import android.widget.Toast import android.widget.Toast
import androidx.core.view.isVisible import androidx.core.view.isVisible
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.greenrobot.eventbus.EventBus import org.greenrobot.eventbus.EventBus
@ -28,6 +27,7 @@ import pl.szczodrzynski.edziennik.ext.attachToastHint
import pl.szczodrzynski.edziennik.ext.get import pl.szczodrzynski.edziennik.ext.get
import pl.szczodrzynski.edziennik.ext.isNotNullNorEmpty import pl.szczodrzynski.edziennik.ext.isNotNullNorEmpty
import pl.szczodrzynski.edziennik.ext.onClick import pl.szczodrzynski.edziennik.ext.onClick
import pl.szczodrzynski.edziennik.ui.base.dialog.SimpleDialog
import pl.szczodrzynski.edziennik.ui.base.fragment.BaseFragment import pl.szczodrzynski.edziennik.ui.base.fragment.BaseFragment
import pl.szczodrzynski.edziennik.ui.dialogs.settings.MessagesConfigDialog import pl.szczodrzynski.edziennik.ui.dialogs.settings.MessagesConfigDialog
import pl.szczodrzynski.edziennik.ui.messages.MessagesUtils import pl.szczodrzynski.edziennik.ui.messages.MessagesUtils
@ -51,7 +51,7 @@ class MessageFragment : BaseFragment<MessageFragmentBinding, MainActivity>(
.withIcon(CommunityMaterial.Icon.cmd_cog_outline) .withIcon(CommunityMaterial.Icon.cmd_cog_outline)
.withOnClickListener { .withOnClickListener {
activity.bottomSheet.close() activity.bottomSheet.close()
MessagesConfigDialog(activity, false, null, null).show() MessagesConfigDialog(activity, false).show()
} }
) )
@ -91,18 +91,20 @@ class MessageFragment : BaseFragment<MessageFragmentBinding, MainActivity>(
)) ))
} }
b.deleteButton.onClick { b.deleteButton.onClick {
MaterialAlertDialogBuilder(activity) SimpleDialog<Unit>(activity) {
.setTitle(R.string.messages_delete_confirmation) title(R.string.messages_delete_confirmation)
.setMessage(R.string.messages_delete_confirmation_text) message(R.string.messages_delete_confirmation_text)
.setPositiveButton(R.string.ok) { _, _ -> positive(R.string.ok) {
launch { manager.markAsDeleted(message)
manager.markAsDeleted(message) Toast.makeText(
Toast.makeText(activity, "Wiadomość przeniesiona do usuniętych", Toast.LENGTH_SHORT).show() activity,
activity.navigateUp() "Wiadomość przeniesiona do usuniętych",
} Toast.LENGTH_SHORT
} ).show()
.setNegativeButton(R.string.cancel, null) activity.navigateUp()
.show() }
negative(R.string.cancel)
}.show()
} }
b.downloadButton.isVisible = App.devMode b.downloadButton.isVisible = App.devMode
b.downloadButton.onClick { b.downloadButton.onClick {
@ -209,8 +211,6 @@ class MessageFragment : BaseFragment<MessageFragmentBinding, MainActivity>(
b.notesButton.setupNotesButton( b.notesButton.setupNotesButton(
activity = activity, activity = activity,
owner = message, owner = message,
onShowListener = null,
onDismissListener = null,
) )
} }

View File

@ -20,11 +20,7 @@ class NoteDetailsDialog(
activity: AppCompatActivity, activity: AppCompatActivity,
private val owner: Noteable?, private val owner: Noteable?,
private var note: Note, private var note: Note,
onShowListener: ((tag: String) -> Unit)? = null, ) : BindingDialog<NoteDetailsDialogBinding>(activity) {
onDismissListener: ((tag: String) -> Unit)? = null,
) : BindingDialog<NoteDetailsDialogBinding>(activity, onShowListener, onDismissListener) {
override val TAG = "NoteDetailsDialog"
override fun getTitleRes(): Int? = null override fun getTitleRes(): Int? = null
override fun inflate(layoutInflater: LayoutInflater) = override fun inflate(layoutInflater: LayoutInflater) =
@ -41,8 +37,6 @@ class NoteDetailsDialog(
activity = activity, activity = activity,
owner = owner, owner = owner,
editingNote = note, editingNote = note,
onShowListener = onShowListener,
onDismissListener = onDismissListener,
).show() ).show()
return NO_DISMISS return NO_DISMISS
} }

View File

@ -4,10 +4,9 @@
package pl.szczodrzynski.edziennik.ui.notes package pl.szczodrzynski.edziennik.ui.notes
import android.content.DialogInterface.BUTTON_POSITIVE
import android.view.LayoutInflater import android.view.LayoutInflater
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
@ -21,11 +20,11 @@ import pl.szczodrzynski.edziennik.databinding.NoteEditorDialogBinding
import pl.szczodrzynski.edziennik.ext.isNotNullNorBlank import pl.szczodrzynski.edziennik.ext.isNotNullNorBlank
import pl.szczodrzynski.edziennik.ext.resolveString import pl.szczodrzynski.edziennik.ext.resolveString
import pl.szczodrzynski.edziennik.ext.toDrawable import pl.szczodrzynski.edziennik.ext.toDrawable
import pl.szczodrzynski.edziennik.ui.base.dialog.BaseDialog
import pl.szczodrzynski.edziennik.ui.base.dialog.BindingDialog import pl.szczodrzynski.edziennik.ui.base.dialog.BindingDialog
import pl.szczodrzynski.edziennik.ui.base.dialog.SimpleDialog
import pl.szczodrzynski.edziennik.ui.dialogs.settings.RegistrationConfigDialog import pl.szczodrzynski.edziennik.ui.dialogs.settings.RegistrationConfigDialog
import pl.szczodrzynski.edziennik.utils.TextInputDropDown import pl.szczodrzynski.edziennik.utils.TextInputDropDown
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine
class NoteEditorDialog( class NoteEditorDialog(
activity: AppCompatActivity, activity: AppCompatActivity,
@ -35,11 +34,7 @@ class NoteEditorDialog(
owner?.getNoteOwnerProfileId() owner?.getNoteOwnerProfileId()
?: editingNote?.profileId ?: editingNote?.profileId
?: 0, ?: 0,
onShowListener: ((tag: String) -> Unit)? = null, ) : BindingDialog<NoteEditorDialogBinding>(activity) {
onDismissListener: ((tag: String) -> Unit)? = null,
) : BindingDialog<NoteEditorDialogBinding>(activity, onShowListener, onDismissListener) {
override val TAG = "NoteEditorDialog"
override fun getTitleRes(): Int? = null override fun getTitleRes(): Int? = null
override fun inflate(layoutInflater: LayoutInflater) = override fun inflate(layoutInflater: LayoutInflater) =
@ -57,7 +52,7 @@ class NoteEditorDialog(
private val textStylingManager private val textStylingManager
get() = app.textStylingManager get() = app.textStylingManager
private var progressDialog: AlertDialog? = null private var progressDialog: BaseDialog<*>? = null
override suspend fun onPositiveClick(): Boolean { override suspend fun onPositiveClick(): Boolean {
val profile = withContext(Dispatchers.IO) { val profile = withContext(Dispatchers.IO) {
@ -75,14 +70,16 @@ class NoteEditorDialog(
} }
if (note.isShared || editingNote?.isShared == true) { if (note.isShared || editingNote?.isShared == true) {
progressDialog = MaterialAlertDialogBuilder(activity) progressDialog = SimpleDialog<Unit>(activity) {
.setTitle(R.string.please_wait) title(R.string.please_wait)
.setMessage(when (note.isShared) { message(
true -> R.string.notes_editor_progress_sharing when (note.isShared) {
false -> R.string.notes_editor_progress_unsharing true -> R.string.notes_editor_progress_sharing
}) false -> R.string.notes_editor_progress_unsharing
.setCancelable(false) }
.show() )
cancelable(false)
}.show()
} }
val success = manager.saveNote( val success = manager.saveNote(
@ -98,25 +95,21 @@ class NoteEditorDialog(
override suspend fun onNeutralClick(): Boolean { override suspend fun onNeutralClick(): Boolean {
// editingNote cannot be null, as the button is visible // editingNote cannot be null, as the button is visible
val confirmation = suspendCoroutine<Boolean> { cont -> val confirmation = SimpleDialog<Unit>(activity) {
var result = false title(R.string.are_you_sure)
MaterialAlertDialogBuilder(activity) message(R.string.notes_editor_confirmation_text)
.setTitle(R.string.are_you_sure) positive(R.string.yes)
.setMessage(R.string.notes_editor_confirmation_text) negative(R.string.no)
.setPositiveButton(R.string.yes) { _, _ -> result = true } }.showModal().getButton()
.setNegativeButton(R.string.no, null) if (confirmation != BUTTON_POSITIVE)
.setOnDismissListener { cont.resume(result) }
.show()
}
if (!confirmation)
return NO_DISMISS return NO_DISMISS
if (editingNote?.isShared == true) { if (editingNote?.isShared == true) {
progressDialog = MaterialAlertDialogBuilder(activity) progressDialog = SimpleDialog<Unit>(activity) {
.setTitle(R.string.please_wait) title(R.string.please_wait)
.setMessage(R.string.notes_editor_progress_unsharing) message(R.string.notes_editor_progress_unsharing)
.setCancelable(false) cancelable(false)
.show() }.show()
} }
val success = manager.deleteNote(activity, editingNote ?: return NO_DISMISS) val success = manager.deleteNote(activity, editingNote ?: return NO_DISMISS)
@ -154,15 +147,11 @@ class NoteEditorDialog(
activity = activity, activity = activity,
textLayout = b.topicLayout, textLayout = b.topicLayout,
textEdit = b.topic, textEdit = b.topic,
onShowListener = onShowListener,
onDismissListener = onDismissListener,
) )
textStylingManager.attachToField( textStylingManager.attachToField(
activity = activity, activity = activity,
textLayout = b.bodyLayout, textLayout = b.bodyLayout,
textEdit = b.body, textEdit = b.body,
onShowListener = onShowListener,
onDismissListener = onDismissListener,
) )
} }

View File

@ -17,11 +17,7 @@ import pl.szczodrzynski.edziennik.utils.SimpleDividerItemDecoration
class NoteListDialog( class NoteListDialog(
activity: AppCompatActivity, activity: AppCompatActivity,
private val owner: Noteable, private val owner: Noteable,
onShowListener: ((tag: String) -> Unit)? = null, ) : BindingDialog<NoteListDialogBinding>(activity) {
onDismissListener: ((tag: String) -> Unit)? = null,
) : BindingDialog<NoteListDialogBinding>(activity, onShowListener, onDismissListener) {
override val TAG = "NoteListDialog"
override fun getTitleRes(): Int? = null override fun getTitleRes(): Int? = null
override fun inflate(layoutInflater: LayoutInflater) = override fun inflate(layoutInflater: LayoutInflater) =
@ -40,8 +36,6 @@ class NoteListDialog(
activity = activity, activity = activity,
owner = owner, owner = owner,
editingNote = null, editingNote = null,
onShowListener = onShowListener,
onDismissListener = onDismissListener,
).show() ).show()
return NO_DISMISS return NO_DISMISS
} }
@ -56,8 +50,6 @@ class NoteListDialog(
activity = activity, activity = activity,
owner = owner, owner = owner,
note = it, note = it,
onShowListener = onShowListener,
onDismissListener = onDismissListener,
).show() ).show()
}, },
onNoteEditClick = { onNoteEditClick = {
@ -65,8 +57,6 @@ class NoteListDialog(
activity = activity, activity = activity,
owner = owner, owner = owner,
editingNote = it, editingNote = it,
onShowListener = onShowListener,
onDismissListener = onDismissListener,
).show() ).show()
}, },
) )

View File

@ -21,8 +21,6 @@ import pl.szczodrzynski.edziennik.ext.toDrawable
fun MaterialButton.setupNotesButton( fun MaterialButton.setupNotesButton(
activity: AppCompatActivity, activity: AppCompatActivity,
owner: Noteable, owner: Noteable,
onShowListener: ((tag: String) -> Unit)? = null,
onDismissListener: ((tag: String) -> Unit)? = null,
) { ) {
if (!isVisible) if (!isVisible)
return return
@ -41,8 +39,6 @@ fun MaterialButton.setupNotesButton(
NoteListDialog( NoteListDialog(
activity = activity, activity = activity,
owner = owner, owner = owner,
onShowListener = onShowListener,
onDismissListener = onDismissListener,
).show() ).show()
} }
} }

View File

@ -141,7 +141,7 @@ class SettingsSyncCard(util: SettingsUtil) : SettingsCard(util) {
item.subTextChecked = getQuietHours() item.subTextChecked = getQuietHours()
item.isChecked = configGlobal.sync.quietHoursEnabled item.isChecked = configGlobal.sync.quietHoursEnabled
util.refresh() util.refresh()
}) }).show()
} }
).also { ).also {
it.subTextChecked = getQuietHours() it.subTextChecked = getQuietHours()

View File

@ -5,9 +5,9 @@
package pl.szczodrzynski.edziennik.ui.settings.cards package pl.szczodrzynski.edziennik.ui.settings.cards
import com.danielstone.materialaboutlibrary.model.MaterialAboutCard import com.danielstone.materialaboutlibrary.model.MaterialAboutCard
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial
import pl.szczodrzynski.edziennik.R import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.ui.base.dialog.SimpleDialog
import pl.szczodrzynski.edziennik.ui.dialogs.settings.AppLanguageDialog import pl.szczodrzynski.edziennik.ui.dialogs.settings.AppLanguageDialog
import pl.szczodrzynski.edziennik.ui.dialogs.settings.MiniMenuConfigDialog import pl.szczodrzynski.edziennik.ui.dialogs.settings.MiniMenuConfigDialog
import pl.szczodrzynski.edziennik.ui.dialogs.settings.ThemeChooserDialog import pl.szczodrzynski.edziennik.ui.dialogs.settings.ThemeChooserDialog
@ -92,14 +92,12 @@ class SettingsThemeCard(util: SettingsUtil) : SettingsCard(util) {
setHeaderBackground() setHeaderBackground()
return@createActionItem return@createActionItem
} }
MaterialAlertDialogBuilder(activity) SimpleDialog<Int>(activity) {
.setItems( itemsRes(
arrayOf( R.string.settings_theme_drawer_header_dialog_set to 0,
activity.getString(R.string.settings_theme_drawer_header_dialog_set), R.string.settings_theme_drawer_header_dialog_restore to 1,
activity.getString(R.string.settings_theme_drawer_header_dialog_restore) ) {
) when (it) {
) { _, which ->
when (which) {
0 -> setHeaderBackground() 0 -> setHeaderBackground()
1 -> { 1 -> {
app.config.ui.headerBackground = null app.config.ui.headerBackground = null
@ -108,8 +106,8 @@ class SettingsThemeCard(util: SettingsUtil) : SettingsCard(util) {
} }
} }
} }
.setNegativeButton(R.string.cancel, null) negative(R.string.cancel)
.show() }.show()
}, },
util.createActionItem( util.createActionItem(
@ -121,14 +119,12 @@ class SettingsThemeCard(util: SettingsUtil) : SettingsCard(util) {
setAppBackground() setAppBackground()
return@createActionItem return@createActionItem
} }
MaterialAlertDialogBuilder(activity) SimpleDialog<Int>(activity) {
.setItems( itemsRes(
arrayOf( R.string.settings_theme_app_background_dialog_set to 0,
activity.getString(R.string.settings_theme_app_background_dialog_set), R.string.settings_theme_app_background_dialog_restore to 1,
activity.getString(R.string.settings_theme_app_background_dialog_restore) ) {
) when (it) {
) { _, which ->
when (which) {
0 -> setAppBackground() 0 -> setAppBackground()
1 -> { 1 -> {
app.config.ui.appBackground = null app.config.ui.appBackground = null
@ -136,8 +132,8 @@ class SettingsThemeCard(util: SettingsUtil) : SettingsCard(util) {
} }
} }
} }
.setNegativeButton(R.string.cancel, null) negative(R.string.cancel)
.show() }.show()
}, },
util.createPropertyItem( util.createPropertyItem(

View File

@ -1,10 +1,8 @@
package pl.szczodrzynski.edziennik.ui.settings.contributors package pl.szczodrzynski.edziennik.ui.settings.contributors
import android.os.Bundle import android.os.Bundle
import android.os.Process
import androidx.core.view.isInvisible import androidx.core.view.isInvisible
import androidx.core.view.isVisible import androidx.core.view.isVisible
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import pl.szczodrzynski.edziennik.App import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.MainActivity import pl.szczodrzynski.edziennik.MainActivity
import pl.szczodrzynski.edziennik.R import pl.szczodrzynski.edziennik.R
@ -14,8 +12,9 @@ import pl.szczodrzynski.edziennik.databinding.ContributorsFragmentBinding
import pl.szczodrzynski.edziennik.ext.Bundle import pl.szczodrzynski.edziennik.ext.Bundle
import pl.szczodrzynski.edziennik.ext.onClick import pl.szczodrzynski.edziennik.ext.onClick
import pl.szczodrzynski.edziennik.ext.onLongClick import pl.szczodrzynski.edziennik.ext.onLongClick
import pl.szczodrzynski.edziennik.ui.base.dialog.SimpleDialog
import pl.szczodrzynski.edziennik.ui.base.fragment.PagerFragment import pl.szczodrzynski.edziennik.ui.base.fragment.PagerFragment
import kotlin.system.exitProcess import pl.szczodrzynski.edziennik.ui.dialogs.RestartDialog
class ContributorsFragment : PagerFragment<ContributorsFragmentBinding, MainActivity>( class ContributorsFragment : PagerFragment<ContributorsFragmentBinding, MainActivity>(
inflater = ContributorsFragmentBinding::inflate, inflater = ContributorsFragmentBinding::inflate,
@ -77,28 +76,19 @@ class ContributorsFragment : PagerFragment<ContributorsFragmentBinding, MainActi
} }
b.glove.onClick { b.glove.onClick {
MaterialAlertDialogBuilder(activity) SimpleDialog<Unit>(activity) {
.setTitle(R.string.are_you_sure) title(R.string.are_you_sure)
.setMessage(R.string.dev_mode_enable_warning) message(R.string.dev_mode_enable_warning)
.setPositiveButton(R.string.yes) { _, _ -> positive(R.string.yes) {
app.config.devMode = true app.config.devMode = true
App.devMode = true App.devMode = true
MaterialAlertDialogBuilder(activity) RestartDialog(activity).show()
.setTitle("Restart")
.setMessage("Wymagany restart aplikacji")
.setPositiveButton(R.string.ok) { _, _ ->
Process.killProcess(Process.myPid())
Runtime.getRuntime().exit(0)
exitProcess(0)
}
.setCancelable(false)
.show()
} }
.setNegativeButton(R.string.no) { _, _ -> negative(R.string.no) {
app.config.devMode = false app.config.devMode = false
App.devMode = false App.devMode = false
} }
.show() }.show()
} }
contributors = contributors ?: SzkolnyApi(app).runCatching(activity.errorSnackbar) { contributors = contributors ?: SzkolnyApi(app).runCatching(activity.errorSnackbar) {

View File

@ -29,13 +29,8 @@ import pl.szczodrzynski.edziennik.ui.base.dialog.ViewDialog
class TemplateDialog( class TemplateDialog(
activity: AppCompatActivity, activity: AppCompatActivity,
private val onActionPerformed: (() -> Unit)? = null, private val onActionPerformed: (() -> Unit)? = null,
onShowListener: ((tag: String) -> Unit)? = null, ) : BindingDialog<DialogTemplateBinding>(activity) {
onDismissListener: ((tag: String) -> Unit)? = null,
) : BindingDialog<DialogTemplateBinding>(activity, onShowListener, onDismissListener) {
override val TAG = "TemplateDialog"
override fun getTitle(): CharSequence = "Template"
override fun getTitleRes() = R.string.menu_template override fun getTitleRes() = R.string.menu_template
override fun inflate(layoutInflater: LayoutInflater) = override fun inflate(layoutInflater: LayoutInflater) =
DialogTemplateBinding.inflate(layoutInflater) DialogTemplateBinding.inflate(layoutInflater)
@ -62,8 +57,6 @@ class TemplateDialog(
// to convert a map of StringIDs to CharSequences // to convert a map of StringIDs to CharSequences
// .mapKeys { (resId, _) -> activity.getString(resId) } // .mapKeys { (resId, _) -> activity.getString(resId) }
override suspend fun onShow() = Unit
// local variables go here // local variables go here
// onPositiveClick // onPositiveClick

View File

@ -7,50 +7,62 @@ package pl.szczodrzynski.edziennik.ui.timetable
import android.content.ContentResolver import android.content.ContentResolver
import android.content.ContentValues import android.content.ContentValues
import android.content.Intent import android.content.Intent
import android.graphics.* import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.DashPathEffect
import android.graphics.Paint
import android.graphics.Rect
import android.graphics.Typeface
import android.os.Build import android.os.Build
import android.os.Environment import android.os.Environment
import android.provider.MediaStore import android.provider.MediaStore
import android.util.Log import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.View.MeasureSpec import android.view.View.MeasureSpec
import android.widget.LinearLayout import android.widget.LinearLayout
import android.widget.TextView import android.widget.TextView
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.cardview.widget.CardView import androidx.cardview.widget.CardView
import com.google.android.material.datepicker.MaterialDatePicker import com.google.android.material.datepicker.MaterialDatePicker
import com.google.android.material.dialog.MaterialAlertDialogBuilder import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.* import kotlinx.coroutines.launch
import org.greenrobot.eventbus.EventBus import kotlinx.coroutines.withContext
import org.greenrobot.eventbus.Subscribe import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode import org.greenrobot.eventbus.ThreadMode
import pl.szczodrzynski.edziennik.* import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.data.api.edziennik.EdziennikTask import pl.szczodrzynski.edziennik.data.api.edziennik.EdziennikTask
import pl.szczodrzynski.edziennik.data.api.events.ApiTaskAllFinishedEvent import pl.szczodrzynski.edziennik.data.api.events.ApiTaskAllFinishedEvent
import pl.szczodrzynski.edziennik.data.api.events.ApiTaskErrorEvent import pl.szczodrzynski.edziennik.data.api.events.ApiTaskErrorEvent
import pl.szczodrzynski.edziennik.data.api.events.ApiTaskFinishedEvent import pl.szczodrzynski.edziennik.data.api.events.ApiTaskFinishedEvent
import pl.szczodrzynski.edziennik.data.db.entity.Lesson import pl.szczodrzynski.edziennik.data.db.entity.Lesson
import pl.szczodrzynski.edziennik.data.enums.FeatureType
import pl.szczodrzynski.edziennik.data.db.full.LessonFull import pl.szczodrzynski.edziennik.data.db.full.LessonFull
import pl.szczodrzynski.edziennik.data.enums.FeatureType
import pl.szczodrzynski.edziennik.databinding.DialogGenerateBlockTimetableBinding import pl.szczodrzynski.edziennik.databinding.DialogGenerateBlockTimetableBinding
import pl.szczodrzynski.edziennik.ext.* import pl.szczodrzynski.edziennik.ext.JsonObject
import pl.szczodrzynski.edziennik.ext.asStrikethroughSpannable
import pl.szczodrzynski.edziennik.ext.dp
import pl.szczodrzynski.edziennik.ext.getSchoolYearConstrains
import pl.szczodrzynski.edziennik.ext.setText
import pl.szczodrzynski.edziennik.ui.base.dialog.BaseDialog
import pl.szczodrzynski.edziennik.ui.base.dialog.BindingDialog
import pl.szczodrzynski.edziennik.ui.base.dialog.SimpleDialog
import pl.szczodrzynski.edziennik.utils.models.Date import pl.szczodrzynski.edziennik.utils.models.Date
import pl.szczodrzynski.edziennik.utils.models.Time import pl.szczodrzynski.edziennik.utils.models.Time
import pl.szczodrzynski.edziennik.utils.models.Week import pl.szczodrzynski.edziennik.utils.models.Week
import timber.log.Timber import timber.log.Timber
import java.io.File import java.io.File
import kotlin.coroutines.CoroutineContext import kotlin.collections.component1
import kotlin.collections.component2
import kotlin.collections.set
import kotlin.math.roundToInt import kotlin.math.roundToInt
class GenerateBlockTimetableDialog( class GenerateBlockTimetableDialog(
val activity: AppCompatActivity, activity: AppCompatActivity,
val onShowListener: ((tag: String) -> Unit)? = null, ) : BindingDialog<DialogGenerateBlockTimetableBinding>(activity) {
val onDismissListener: ((tag: String) -> Unit)? = null
) : CoroutineScope {
companion object { companion object {
const val TAG = "GenerateBlockTimetableDialog" private const val TAG = "GenerateBlockTimetableDialog"
private const val WIDTH_CONSTANT = 70 private const val WIDTH_CONSTANT = 70
private const val WIDTH_WEEKDAY = 285 private const val WIDTH_WEEKDAY = 285
private const val WIDTH_SPACING = 15 private const val WIDTH_SPACING = 15
@ -59,64 +71,45 @@ class GenerateBlockTimetableDialog(
private const val HEIGHT_FOOTER = 40 private const val HEIGHT_FOOTER = 40
} }
override fun getTitleRes() = R.string.timetable_generate_range
override fun inflate(layoutInflater: LayoutInflater) =
DialogGenerateBlockTimetableBinding.inflate(layoutInflater)
override fun getPositiveButtonText() = R.string.save
override fun getNegativeButtonText() = R.string.cancel
private val heightProfileName by lazy { if (showProfileName) 100 else 0 } private val heightProfileName by lazy { if (showProfileName) 100 else 0 }
private val app by lazy { activity.application as App }
private val job: Job = Job()
override val coroutineContext: CoroutineContext
get() = job + Dispatchers.Main
private lateinit var dialog: AlertDialog
private lateinit var b: DialogGenerateBlockTimetableBinding
private var showProfileName: Boolean = false private var showProfileName: Boolean = false
private var showTeachersNames: Boolean = true private var showTeachersNames: Boolean = true
private var noColors: Boolean = false private var noColors: Boolean = false
private var enqueuedWeekDialog: AlertDialog? = null private var enqueuedWeekDialog: BaseDialog<*>? = null
private var enqueuedWeekStart = Date.getToday() private var enqueuedWeekStart = Date.getToday()
private var enqueuedWeekEnd = Date.getToday() private var enqueuedWeekEnd = Date.getToday()
init { run { private val weekCurrentStart = Week.getWeekStart()
if (activity.isFinishing) private val weekCurrentEnd = Week.getWeekEnd()
return@run private val weekNextStart = weekCurrentEnd.clone().stepForward(0, 0, 1)
onShowListener?.invoke(TAG) private val weekNextEnd = weekNextStart.clone().stepForward(0, 0, 6)
EventBus.getDefault().register(this)
val weekCurrentStart = Week.getWeekStart()
val weekCurrentEnd = Week.getWeekEnd()
val weekNextStart = weekCurrentEnd.clone().stepForward(0, 0, 1)
val weekNextEnd = weekNextStart.clone().stepForward(0, 0, 6)
b = DialogGenerateBlockTimetableBinding.inflate(activity.layoutInflater)
override suspend fun onShow() {
b.withChangesCurrentWeekRadio.setText(R.string.timetable_generate_current_week_format, weekCurrentStart.formattedStringShort, weekCurrentEnd.formattedStringShort) b.withChangesCurrentWeekRadio.setText(R.string.timetable_generate_current_week_format, weekCurrentStart.formattedStringShort, weekCurrentEnd.formattedStringShort)
b.withChangesNextWeekRadio.setText(R.string.timetable_generate_next_week_format, weekNextStart.formattedStringShort, weekCurrentEnd.formattedStringShort) b.withChangesNextWeekRadio.setText(R.string.timetable_generate_next_week_format, weekNextStart.formattedStringShort, weekCurrentEnd.formattedStringShort)
b.showProfileNameCheckbox.setOnCheckedChangeListener { _, isChecked -> showProfileName = isChecked } b.showProfileNameCheckbox.setOnCheckedChangeListener { _, isChecked -> showProfileName = isChecked }
b.showTeachersNamesCheckbox.setOnCheckedChangeListener { _, isChecked -> showTeachersNames = isChecked } b.showTeachersNamesCheckbox.setOnCheckedChangeListener { _, isChecked -> showTeachersNames = isChecked }
b.noColorsCheckbox.setOnCheckedChangeListener { _, isChecked -> noColors = isChecked } b.noColorsCheckbox.setOnCheckedChangeListener { _, isChecked -> noColors = isChecked }
}
dialog = MaterialAlertDialogBuilder(activity) override suspend fun onPositiveClick(): Boolean {
.setTitle(R.string.timetable_generate_range) when (b.weekSelectionRadioGroup.checkedRadioButtonId) {
.setView(b.root) R.id.withChangesCurrentWeekRadio -> generateBlockTimetable(weekCurrentStart, weekCurrentEnd)
.setNeutralButton(R.string.cancel) { dialog, _ -> dialog.dismiss() } R.id.withChangesNextWeekRadio -> generateBlockTimetable(weekNextStart, weekNextEnd)
.setPositiveButton(R.string.save, null) R.id.forSelectedWeekRadio -> selectDate()
.setOnDismissListener {
onDismissListener?.invoke(TAG)
EventBus.getDefault().unregister(this@GenerateBlockTimetableDialog)
}
.show()
dialog.getButton(AlertDialog.BUTTON_POSITIVE)?.onClick {
when (b.weekSelectionRadioGroup.checkedRadioButtonId) {
R.id.withChangesCurrentWeekRadio -> generateBlockTimetable(weekCurrentStart, weekCurrentEnd)
R.id.withChangesNextWeekRadio -> generateBlockTimetable(weekNextStart, weekNextEnd)
R.id.forSelectedWeekRadio -> selectDate()
}
} }
}} return NO_DISMISS
}
private fun selectDate() { private fun selectDate() {
MaterialDatePicker.Builder.datePicker() MaterialDatePicker.Builder.datePicker()
@ -146,7 +139,7 @@ class GenerateBlockTimetableDialog(
@Subscribe(threadMode = ThreadMode.MAIN) @Subscribe(threadMode = ThreadMode.MAIN)
fun onApiTaskErrorEvent(event: ApiTaskErrorEvent) { fun onApiTaskErrorEvent(event: ApiTaskErrorEvent) {
dialog.dismiss() dismiss()
enqueuedWeekDialog?.dismiss() enqueuedWeekDialog?.dismiss()
} }
@ -191,11 +184,11 @@ class GenerateBlockTimetableDialog(
if (enqueuedWeekDialog != null) { if (enqueuedWeekDialog != null) {
return@launch return@launch
} }
enqueuedWeekDialog = MaterialAlertDialogBuilder(activity) enqueuedWeekDialog = SimpleDialog<Unit>(activity) {
.setTitle(R.string.please_wait) title(R.string.please_wait)
.setMessage(R.string.timetable_syncing_text) message(R.string.timetable_syncing_text)
.setCancelable(false) cancelable(false)
.show() }.show()
enqueuedWeekStart = weekStart enqueuedWeekStart = weekStart
enqueuedWeekEnd = weekEnd enqueuedWeekEnd = weekEnd
@ -210,10 +203,11 @@ class GenerateBlockTimetableDialog(
return@launch return@launch
} }
val progressDialog = MaterialAlertDialogBuilder(activity) val progressDialog = SimpleDialog<Unit>(activity) {
.setTitle(R.string.timetable_generate_progress_title) title(R.string.timetable_generate_progress_title)
.setMessage(R.string.timetable_generate_progress_text) message(R.string.timetable_generate_progress_text)
.show() cancelable(false)
}.show()
if (minTime == null) { if (minTime == null) {
progressDialog.dismiss() progressDialog.dismiss()
@ -221,8 +215,6 @@ class GenerateBlockTimetableDialog(
return@launch return@launch
} }
dialog.dismiss()
val uri = withContext(Dispatchers.Default) { val uri = withContext(Dispatchers.Default) {
val diff = Time.diff(maxTime, minTime) val diff = Time.diff(maxTime, minTime)
@ -402,26 +394,28 @@ class GenerateBlockTimetableDialog(
} }
progressDialog.dismiss() progressDialog.dismiss()
MaterialAlertDialogBuilder(activity) SimpleDialog<Unit>(activity) {
.setTitle(R.string.timetable_generate_success_title) title(R.string.timetable_generate_success_title)
.setMessage(R.string.timetable_generate_success_text) message(R.string.timetable_generate_success_text)
.setPositiveButton(R.string.share) { dialog, _ -> positive(R.string.share) {
dialog.dismiss() val intent = Intent(Intent.ACTION_SEND)
intent.setDataAndType(null, "image/*")
val intent = Intent(Intent.ACTION_SEND) intent.putExtra(Intent.EXTRA_STREAM, uri)
intent.setDataAndType(null, "image/*") activity.startActivity(
intent.putExtra(Intent.EXTRA_STREAM, uri) Intent.createChooser(
activity.startActivity(Intent.createChooser(intent, activity.getString(R.string.share_intent))) intent,
} activity.getString(R.string.share_intent)
.setNegativeButton(R.string.open) { dialog, _ -> )
dialog.dismiss() )
}
val intent = Intent(Intent.ACTION_VIEW) negative(R.string.open) {
intent.setDataAndType(uri, "image/*") val intent = Intent(Intent.ACTION_VIEW)
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) intent.setDataAndType(uri, "image/*")
activity.startActivity(intent) intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
} activity.startActivity(intent)
.setNeutralButton(R.string.do_nothing) { dialog, _ -> dialog.dismiss() } }
.show() neutral(R.string.do_nothing)
}.showModal()
dismiss()
}} }}
} }

View File

@ -36,11 +36,7 @@ class LessonDetailsDialog(
private val lesson: LessonFull, private val lesson: LessonFull,
private val attendance: AttendanceFull? = null, private val attendance: AttendanceFull? = null,
private val showNotes: Boolean = true, private val showNotes: Boolean = true,
onShowListener: ((tag: String) -> Unit)? = null, ) : BindingDialog<DialogLessonDetailsBinding>(activity) {
onDismissListener: ((tag: String) -> Unit)? = null,
) : BindingDialog<DialogLessonDetailsBinding>(activity, onShowListener, onDismissListener) {
override val TAG = "LessonDetailsDialog"
override fun getTitleRes(): Int? = null override fun getTitleRes(): Int? = null
override fun inflate(layoutInflater: LayoutInflater) = override fun inflate(layoutInflater: LayoutInflater) =
@ -60,8 +56,6 @@ class LessonDetailsDialog(
activity, activity,
lesson.profileId, lesson.profileId,
defaultLesson = lesson, defaultLesson = lesson,
onShowListener = onShowListener,
onDismissListener = onDismissListener
).show() ).show()
return NO_DISMISS return NO_DISMISS
} }
@ -114,7 +108,7 @@ class LessonDetailsDialog(
} }
} }
b.shiftedGoTo.setOnClickListener { b.shiftedGoTo.setOnClickListener {
dialog.dismiss() dismiss()
val dateStr = otherLessonDate?.stringY_m_d ?: return@setOnClickListener val dateStr = otherLessonDate?.stringY_m_d ?: return@setOnClickListener
val intent = Intent(TimetableFragment.ACTION_SCROLL_TO_DATE).apply { val intent = Intent(TimetableFragment.ACTION_SCROLL_TO_DATE).apply {
putExtra("timetableDate", dateStr) putExtra("timetableDate", dateStr)
@ -168,8 +162,6 @@ class LessonDetailsDialog(
AttendanceDetailsDialog( AttendanceDetailsDialog(
activity = activity, activity = activity,
attendance = attendance, attendance = attendance,
onShowListener = onShowListener,
onDismissListener = onDismissListener,
).show() ).show()
} }
} }
@ -186,8 +178,6 @@ class LessonDetailsDialog(
EventDetailsDialog( EventDetailsDialog(
activity, activity,
it, it,
onShowListener = onShowListener,
onDismissListener = onDismissListener
).show() ).show()
}, },
onEventEditClick = { onEventEditClick = {
@ -195,8 +185,6 @@ class LessonDetailsDialog(
activity, activity,
it.profileId, it.profileId,
editingEvent = it, editingEvent = it,
onShowListener = onShowListener,
onDismissListener = onDismissListener
).show() ).show()
} }
) )
@ -236,12 +224,12 @@ class LessonDetailsDialog(
BetterLink.attach( BetterLink.attach(
b.teacherNameView, b.teacherNameView,
teachers = mapOf(lesson.displayTeacherId!! to name), teachers = mapOf(lesson.displayTeacherId!! to name),
onActionSelected = dialog::dismiss onActionSelected = ::dismiss
) )
BetterLink.attach( BetterLink.attach(
b.oldTeacherNameView, b.oldTeacherNameView,
teachers = mapOf(lesson.displayTeacherId!! to name), teachers = mapOf(lesson.displayTeacherId!! to name),
onActionSelected = dialog::dismiss onActionSelected = ::dismiss
) )
} }
@ -250,8 +238,6 @@ class LessonDetailsDialog(
b.notesButton.setupNotesButton( b.notesButton.setupNotesButton(
activity = activity, activity = activity,
owner = lesson, owner = lesson,
onShowListener = onShowListener,
onDismissListener = onDismissListener,
) )
b.legend.isVisible = showNotes b.legend.isVisible = showNotes
if (showNotes) if (showNotes)

View File

@ -109,7 +109,7 @@ class TimetableFragment : PagerFragment<FragmentTimetableV2Binding, MainActivity
.withIcon(CommunityMaterial.Icon.cmd_cog_outline) .withIcon(CommunityMaterial.Icon.cmd_cog_outline)
.withOnClickListener { .withOnClickListener {
activity.bottomSheet.close() activity.bottomSheet.close()
TimetableConfigDialog(activity, false, null, null).show() TimetableConfigDialog(activity, false).show()
} }
) )

View File

@ -9,40 +9,37 @@ import android.content.Intent.FLAG_ACTIVITY_REORDER_TO_FRONT
import android.graphics.drawable.ColorDrawable import android.graphics.drawable.ColorDrawable
import android.os.Bundle import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import kotlinx.coroutines.* import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import pl.szczodrzynski.edziennik.App import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.MainActivity import pl.szczodrzynski.edziennik.MainActivity
import pl.szczodrzynski.edziennik.ext.Intent
import pl.szczodrzynski.edziennik.data.enums.NavTarget import pl.szczodrzynski.edziennik.data.enums.NavTarget
import pl.szczodrzynski.edziennik.ext.Intent
import pl.szczodrzynski.edziennik.ext.app import pl.szczodrzynski.edziennik.ext.app
import pl.szczodrzynski.edziennik.ui.timetable.LessonDetailsDialog import pl.szczodrzynski.edziennik.ui.timetable.LessonDetailsDialog
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
class LessonDialogActivity : AppCompatActivity(), CoroutineScope { class LessonDialogActivity : AppCompatActivity(), CoroutineScope {
companion object {
private const val TAG = "LessonDialogActivity"
}
private lateinit var job: Job private val job = Job()
override val coroutineContext: CoroutineContext override val coroutineContext: CoroutineContext
get() = job + Dispatchers.Main get() = job + Dispatchers.Main
private val shownDialogs = hashSetOf<String>()
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
window.setBackgroundDrawable(ColorDrawable(0)) window.setBackgroundDrawable(ColorDrawable(0))
job = Job()
app.uiManager.applyTheme(this, noDisplay = true) app.uiManager.applyTheme(this, noDisplay = true)
val app = application as App val app = application as App
launch { launch {
val deferred = async(Dispatchers.Default) { val lesson = withContext(Dispatchers.IO) {
val extras = intent?.extras val extras = intent?.extras
val profileId = extras?.getInt("profileId") ?: return@async null val profileId = extras?.getInt("profileId") ?: return@withContext null
if (extras.getBoolean("separatorItem", false)) { if (extras.getBoolean("separatorItem", false)) {
val i = Intent( val i = Intent(
@ -53,28 +50,16 @@ class LessonDialogActivity : AppCompatActivity(), CoroutineScope {
).addFlags(FLAG_ACTIVITY_REORDER_TO_FRONT or FLAG_ACTIVITY_NEW_TASK) ).addFlags(FLAG_ACTIVITY_REORDER_TO_FRONT or FLAG_ACTIVITY_NEW_TASK)
app.startActivity(i) app.startActivity(i)
finish() finish()
return@async null return@withContext null
} }
val lessonId = extras.getLong("lessonId") val lessonId = extras.getLong("lessonId")
app.db.timetableDao().getByIdNow(profileId, lessonId) app.db.timetableDao().getByIdNow(profileId, lessonId)
} } ?: return@launch
val lesson = deferred.await()
lesson?.let { LessonDetailsDialog(this@LessonDialogActivity, lesson).showModal()
LessonDetailsDialog( finish()
this@LessonDialogActivity,
lesson,
onShowListener = { tag ->
shownDialogs.add(tag)
},
onDismissListener = { tag ->
shownDialogs.remove(tag)
if (shownDialogs.isEmpty())
finish()
}
).show()
}
} }
} }
} }

View File

@ -4,21 +4,12 @@
<LinearLayout <LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" android:orientation="vertical"
android:paddingStart="?attr/dialogPreferredPadding" android:paddingStart="?attr/dialogPreferredPadding"
android:paddingTop="8dp"
android:paddingEnd="?attr/dialogPreferredPadding"> android:paddingEnd="?attr/dialogPreferredPadding">
<TextView
android:id="@android:id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="4dp"
tools:text="This is a custom message of the dialog." />
<com.google.android.material.textfield.TextInputLayout <com.google.android.material.textfield.TextInputLayout
android:id="@+id/text_input_layout" android:id="@+id/text_input_layout"
style="?textInputOutlinedStyle" style="?textInputOutlinedStyle"