diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt b/app/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt index affb686f..37deec60 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt @@ -420,7 +420,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope { App.db.profileDao().getByIdNow(profile.identifier.toInt()) } ?: return@launch drawer.close() - ProfileConfigDialog(this@MainActivity, appProfile) + ProfileConfigDialog(this@MainActivity, appProfile).show() } true } else { @@ -529,7 +529,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope { if (app.config.appVersion < BuildConfig.VERSION_CODE) { // force an AppSync after update app.config.sync.lastAppSync = 0L - ChangelogDialog(this) + ChangelogDialog(this).show() if (app.config.appVersion < 170) { //Intent intent = new Intent(this, ChangelogIntroActivity.class); //startActivity(intent); @@ -587,7 +587,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope { .withIcon(CommunityMaterial.Icon.cmd_download_outline) .withOnClickListener { bottomSheet.close() - SyncViewListDialog(this, navTargetId) + SyncViewListDialog(this, navTargetId).show() }, BottomSheetSeparatorItem(false), BottomSheetPrimaryItem(false) @@ -690,7 +690,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope { Type.NOT_AVAILABLE -> { swipeRefreshLayout.isRefreshing = false loadTarget(DRAWER_ITEM_HOME) - RegisterUnavailableDialog(this, error.status!!) + RegisterUnavailableDialog(this, error.status!!).show() return } Type.API_ERROR -> { @@ -722,7 +722,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope { @Subscribe(threadMode = ThreadMode.MAIN, sticky = true) fun onUpdateEvent(event: Update) { EventBus.getDefault().removeStickyEvent(event) - UpdateAvailableDialog(this, event) + UpdateAvailableDialog(this, event).show() } @Subscribe(threadMode = ThreadMode.MAIN, sticky = true) @@ -730,7 +730,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope { EventBus.getDefault().removeStickyEvent(event) val error = app.availabilityManager.check(app.profile, cacheOnly = true) if (error != null) { - RegisterUnavailableDialog(this, error.status!!) + RegisterUnavailableDialog(this, error.status!!).show() } } @@ -797,7 +797,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope { if (event.error.errorCode == ERROR_VULCAN_API_DEPRECATED) { if (event.error.profileId != App.profileId) return - ErrorDetailsDialog(this, listOf(event.error)) + ErrorDetailsDialog(this, listOf(event.error)).show() } navView.toolbar.apply { subtitleFormat = R.string.toolbar_subtitle @@ -894,7 +894,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope { this, extras.getString("serverMessageTitle") ?: getString(R.string.app_name), extras.getString("serverMessageText") ?: "" - ) + ).show() true } "feedbackMessage" -> { @@ -917,7 +917,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope { this, App.profileId, defaultDate = date - ) + ).show() true } else -> false diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/SzkolnyApi.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/SzkolnyApi.kt index 1996b1a3..39449c42 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/SzkolnyApi.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/SzkolnyApi.kt @@ -103,7 +103,7 @@ class SzkolnyApi(val app: App) : CoroutineScope { activity, listOf(apiError), R.string.error_occured - ) + ).show() null } null diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/agenda/AgendaFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/agenda/AgendaFragment.kt index a13b9b02..83d89e67 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/agenda/AgendaFragment.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/agenda/AgendaFragment.kt @@ -77,14 +77,14 @@ class AgendaFragment : Fragment(), CoroutineScope { activity, app.profileId, defaultDate = AgendaFragmentDefault.selectedDate - ) + ).show() }, BottomSheetPrimaryItem(true) .withTitle(R.string.menu_agenda_config) .withIcon(CommunityMaterial.Icon.cmd_cog_outline) .withOnClickListener { activity.bottomSheet.close() - AgendaConfigDialog(activity, true, null, null) + AgendaConfigDialog(activity, true, null, null).show() }, BottomSheetPrimaryItem(true) .withTitle(R.string.menu_agenda_change_view) @@ -124,7 +124,7 @@ class AgendaFragment : Fragment(), CoroutineScope { activity, app.profileId, defaultDate = AgendaFragmentDefault.selectedDate - ) + ).show() } activity.gainAttention() @@ -188,7 +188,7 @@ class AgendaFragment : Fragment(), CoroutineScope { unreadEventDates.remove(date.value) } - DayDialog(activity, app.profileId, date) + DayDialog(activity, app.profileId, date).show() }} b.progressBar.visibility = View.GONE diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/agenda/AgendaFragmentDefault.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/agenda/AgendaFragmentDefault.kt index be01c222..d51e2e70 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/agenda/AgendaFragmentDefault.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/agenda/AgendaFragmentDefault.kt @@ -139,7 +139,7 @@ class AgendaFragmentDefault( val c = Calendar.getInstance() c.time = dayItem.date if (c.timeInMillis == selectedDate.inMillis) { - DayDialog(activity, app.profileId, selectedDate) + DayDialog(activity, app.profileId, selectedDate).show() } } @@ -147,16 +147,25 @@ class AgendaFragmentDefault( val date = Date.fromCalendar(event.instanceDay) when (event) { - is AgendaEvent -> EventDetailsDialog(activity, event.event) - is LessonChangesEvent -> LessonChangesDialog(activity, app.profileId, date) + is AgendaEvent -> EventDetailsDialog(activity, event.event).show() + is LessonChangesEvent -> LessonChangesDialog( + activity = activity, + profileId = app.profileId, + defaultDate = date + ).show() is TeacherAbsenceEvent -> TeacherAbsenceDialog( - activity, - app.profileId, - date - ) - is AgendaEventGroup -> DayDialog(activity, app.profileId, date, eventTypeId = event.typeId) + activity = activity, + profileId = app.profileId, + date = date + ).show() + is AgendaEventGroup -> DayDialog( + activity = activity, + profileId = app.profileId, + date = date, + eventTypeId = event.typeId, + ).show() is BaseCalendarEvent -> if (event.isPlaceHolder) - DayDialog(activity, app.profileId, date) + DayDialog(activity, app.profileId, date).show() } if (event is BaseEvent && event.showItemBadge) { diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/agenda/DayDialog.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/agenda/DayDialog.kt index af5a4c04..e888c82e 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/agenda/DayDialog.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/agenda/DayDialog.kt @@ -4,12 +4,11 @@ package pl.szczodrzynski.edziennik.ui.agenda +import android.view.LayoutInflater import android.view.View -import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AppCompatActivity import androidx.core.view.isVisible import androidx.recyclerview.widget.LinearLayoutManager -import com.google.android.material.dialog.MaterialAlertDialogBuilder import kotlinx.coroutines.* import pl.szczodrzynski.edziennik.* import pl.szczodrzynski.edziennik.data.db.entity.Lesson @@ -23,6 +22,7 @@ import pl.szczodrzynski.edziennik.ui.agenda.lessonchanges.LessonChangesEventRend import pl.szczodrzynski.edziennik.ui.agenda.teacherabsence.TeacherAbsenceDialog import pl.szczodrzynski.edziennik.ui.agenda.teacherabsence.TeacherAbsenceEvent import pl.szczodrzynski.edziennik.ui.agenda.teacherabsence.TeacherAbsenceEventRenderer +import pl.szczodrzynski.edziennik.ui.dialogs.base.BindingDialog import pl.szczodrzynski.edziennik.ui.event.EventDetailsDialog import pl.szczodrzynski.edziennik.ui.event.EventListAdapter import pl.szczodrzynski.edziennik.ui.event.EventManualDialog @@ -30,87 +30,67 @@ import pl.szczodrzynski.edziennik.utils.SimpleDividerItemDecoration import pl.szczodrzynski.edziennik.utils.models.Date import pl.szczodrzynski.edziennik.utils.models.Time import pl.szczodrzynski.edziennik.utils.models.Week -import kotlin.coroutines.CoroutineContext class DayDialog( - val activity: AppCompatActivity, - val profileId: Int, - val date: Date, - val eventTypeId: Long? = null, - val onShowListener: ((tag: String) -> Unit)? = null, - val onDismissListener: ((tag: String) -> Unit)? = null -) : CoroutineScope { - companion object { - private const val TAG = "DayDialog" - } + activity: AppCompatActivity, + private val profileId: Int, + private val date: Date, + private val eventTypeId: Long? = null, + onShowListener: ((tag: String) -> Unit)? = null, + onDismissListener: ((tag: String) -> Unit)? = null, +) : BindingDialog(activity, onShowListener, onDismissListener) { - private lateinit var app: App - private lateinit var b: DialogDayBinding - private lateinit var dialog: AlertDialog + override val TAG = "DayDialog" - private val job = Job() - override val coroutineContext: CoroutineContext - get() = job + Dispatchers.Main + override fun getTitleRes(): Int? = null + override fun inflate(layoutInflater: LayoutInflater) = + DialogDayBinding.inflate(layoutInflater) + + override fun getPositiveButtonText() = R.string.close + override fun getNeutralButtonText() = R.string.add private lateinit var adapter: EventListAdapter - init { run { - if (activity.isFinishing) - return@run - onShowListener?.invoke(TAG) - app = activity.applicationContext as App - b = DialogDayBinding.inflate(activity.layoutInflater) - dialog = MaterialAlertDialogBuilder(activity) - .setView(b.root) - .setPositiveButton(R.string.close) { dialog, _ -> - dialog.dismiss() - } - .setNeutralButton(R.string.add, null) - .setOnDismissListener { - onDismissListener?.invoke(TAG) - } - .show() + override suspend fun onNeutralClick(): Boolean { + EventManualDialog( + activity, + profileId, + defaultDate = date, + onShowListener = onShowListener, + onDismissListener = onDismissListener + ).show() + return NO_DISMISS + } - dialog.getButton(AlertDialog.BUTTON_NEUTRAL)?.onClick { - EventManualDialog( - activity, - profileId, - defaultDate = date, - onShowListener = onShowListener, - onDismissListener = onDismissListener - ) - } - - update() - }} - - private fun update() { launch { + override suspend fun onShow() { b.dayDate.setText( - R.string.dialog_day_date_format, - Week.getFullDayName(date.weekDay), - date.formattedString + R.string.dialog_day_date_format, + Week.getFullDayName(date.weekDay), + date.formattedString ) val lessons = withContext(Dispatchers.Default) { app.db.timetableDao().getAllForDateNow(profileId, date) }.filter { it.type != Lesson.TYPE_NO_LESSONS } - if (lessons.isNotEmpty()) { run { - val startTime = lessons.first().startTime ?: return@run - val endTime = lessons.last().endTime ?: return@run - val diff = Time.diff(startTime, endTime) + if (lessons.isNotEmpty()) { + run { + val startTime = lessons.first().startTime ?: return@run + val endTime = lessons.last().endTime ?: return@run + val diff = Time.diff(startTime, endTime) - b.lessonsInfo.setText( + b.lessonsInfo.setText( R.string.dialog_day_lessons_info, startTime.stringHM, endTime.stringHM, lessons.size.toString(), diff.hour.toString(), diff.minute.toString() - ) + ) - b.lessonsInfo.visibility = View.VISIBLE - }} + b.lessonsInfo.visibility = View.VISIBLE + } + } val lessonChanges = withContext(Dispatchers.Default) { app.db.timetableDao().getChangesForDateNow(profileId, date) @@ -133,7 +113,7 @@ class DayDialog( date, onShowListener = onShowListener, onDismissListener = onDismissListener - ) + ).show() } } b.lessonChangesFrame.isVisible = lessonChanges.isNotEmpty() @@ -158,36 +138,36 @@ class DayDialog( date, onShowListener = onShowListener, onDismissListener = onDismissListener - ) + ).show() } } b.teacherAbsenceFrame.isVisible = teacherAbsences.isNotEmpty() adapter = EventListAdapter( - activity = activity, - showWeekDay = false, - showDate = false, - showType = true, - showTime = true, - showSubject = true, - markAsSeen = true, - onItemClick = { - EventDetailsDialog( - activity, - it, - onShowListener = onShowListener, - onDismissListener = onDismissListener - ) - }, - onEventEditClick = { - EventManualDialog( - activity, - it.profileId, - editingEvent = it, - onShowListener = onShowListener, - onDismissListener = onDismissListener - ) - } + activity = activity, + showWeekDay = false, + showDate = false, + showType = true, + showTime = true, + showSubject = true, + markAsSeen = true, + onItemClick = { + EventDetailsDialog( + activity, + it, + onShowListener = onShowListener, + onDismissListener = onDismissListener + ).show() + }, + onEventEditClick = { + EventManualDialog( + activity, + it.profileId, + editingEvent = it, + onShowListener = onShowListener, + onDismissListener = onDismissListener + ).show() + } ) app.db.eventDao().getAllByDate(profileId, date).observe(activity) { events -> @@ -217,5 +197,5 @@ class DayDialog( b.eventsNoData.visibility = View.VISIBLE } } - }} + } } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/agenda/lessonchanges/LessonChangesDialog.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/agenda/lessonchanges/LessonChangesDialog.kt index 8fd2b454..9e755046 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/agenda/lessonchanges/LessonChangesDialog.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/agenda/lessonchanges/LessonChangesDialog.kt @@ -1,76 +1,53 @@ package pl.szczodrzynski.edziennik.ui.agenda.lessonchanges -import androidx.appcompat.app.AlertDialog +import android.view.LayoutInflater import androidx.appcompat.app.AppCompatActivity import androidx.recyclerview.widget.LinearLayoutManager -import com.google.android.material.dialog.MaterialAlertDialogBuilder -import kotlinx.coroutines.* -import pl.szczodrzynski.edziennik.App +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext import pl.szczodrzynski.edziennik.R import pl.szczodrzynski.edziennik.databinding.DialogLessonChangeListBinding +import pl.szczodrzynski.edziennik.ui.dialogs.base.BindingDialog import pl.szczodrzynski.edziennik.ui.timetable.LessonDetailsDialog import pl.szczodrzynski.edziennik.utils.models.Date -import kotlin.coroutines.CoroutineContext class LessonChangesDialog( - val activity: AppCompatActivity, - val profileId: Int, - private val defaultDate: Date, - val onShowListener: ((tag: String) -> Unit)? = null, - val onDismissListener: ((tag: String) -> Unit)? = null -) : CoroutineScope { - companion object { - const val TAG = "LessonChangeDialog" - } + activity: AppCompatActivity, + private val profileId: Int, + private val defaultDate: Date, + onShowListener: ((tag: String) -> Unit)? = null, + onDismissListener: ((tag: String) -> Unit)? = null, +) : BindingDialog(activity, onShowListener, onDismissListener) { - private val app by lazy { activity.application as App } + override val TAG = "LessonChangesDialog" - private lateinit var job: Job - override val coroutineContext: CoroutineContext - get() = job + Dispatchers.Main + override fun getTitle(): String = defaultDate.formattedString + override fun getTitleRes(): Int? = null + override fun inflate(layoutInflater: LayoutInflater) = + DialogLessonChangeListBinding.inflate(layoutInflater) - private lateinit var b: DialogLessonChangeListBinding - private lateinit var dialog: AlertDialog + override fun getPositiveButtonText() = R.string.close - init { run { - if (activity.isFinishing) - return@run - job = Job() - onShowListener?.invoke(TAG) - b = DialogLessonChangeListBinding.inflate(activity.layoutInflater) - dialog = MaterialAlertDialogBuilder(activity) - .setTitle(defaultDate.formattedString) - .setView(b.root) - .setPositiveButton(R.string.close) { dialog, _ -> dialog.dismiss() } - .setOnDismissListener { - onDismissListener?.invoke(TAG) - } - .create() - loadLessonChanges() - }} - - private fun loadLessonChanges() { launch { + override suspend fun onShow() { val lessonChanges = withContext(Dispatchers.Default) { app.db.timetableDao().getChangesForDateNow(profileId, defaultDate) } val adapter = LessonChangesAdapter( - activity, - onItemClick = { - LessonDetailsDialog( - activity, - it, - onShowListener = onShowListener, - onDismissListener = onDismissListener - ) - } + activity, + onItemClick = { + LessonDetailsDialog( + activity, + it, + onShowListener = onShowListener, + onDismissListener = onDismissListener + ).show() + } ).apply { items = lessonChanges } b.lessonChangeView.adapter = adapter b.lessonChangeView.layoutManager = LinearLayoutManager(activity) - - dialog.show() - }} + } } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/agenda/teacherabsence/TeacherAbsenceDialog.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/agenda/teacherabsence/TeacherAbsenceDialog.kt index a4f527ff..7a1071de 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/agenda/teacherabsence/TeacherAbsenceDialog.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/agenda/teacherabsence/TeacherAbsenceDialog.kt @@ -1,57 +1,42 @@ package pl.szczodrzynski.edziennik.ui.agenda.teacherabsence +import android.view.LayoutInflater import android.view.View -import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.LifecycleOwner -import androidx.lifecycle.Observer import androidx.recyclerview.widget.LinearLayoutManager -import com.google.android.material.dialog.MaterialAlertDialogBuilder -import pl.szczodrzynski.edziennik.App import pl.szczodrzynski.edziennik.R import pl.szczodrzynski.edziennik.databinding.DialogTeacherAbsenceListBinding +import pl.szczodrzynski.edziennik.ui.dialogs.base.BindingDialog import pl.szczodrzynski.edziennik.utils.models.Date class TeacherAbsenceDialog( - val activity: AppCompatActivity, - val profileId: Int, - val date: Date, - val onShowListener: ((tag: String) -> Unit)? = null, - val onDismissListener: ((tag: String) -> Unit)? = null -) { - companion object { - private const val TAG = "TeacherAbsenceDialog" - } + activity: AppCompatActivity, + private val profileId: Int, + private val date: Date, + onShowListener: ((tag: String) -> Unit)? = null, + onDismissListener: ((tag: String) -> Unit)? = null, +) : BindingDialog(activity, onShowListener, onDismissListener) { - private val app by lazy { activity.application as App } + override val TAG = "TeacherAbsenceDialog" - private lateinit var b: DialogTeacherAbsenceListBinding - private lateinit var dialog: AlertDialog + override fun getTitle(): String = date.formattedString + override fun getTitleRes(): Int? = null + override fun inflate(layoutInflater: LayoutInflater) = + DialogTeacherAbsenceListBinding.inflate(layoutInflater) - init { run { - if (activity.isFinishing) - return@run - - b = DialogTeacherAbsenceListBinding.inflate(activity.layoutInflater) - - dialog = MaterialAlertDialogBuilder(activity) - .setTitle(date.formattedString) - .setView(b.root) - .setPositiveButton(R.string.close) { dialog, _ -> dialog.dismiss() } - .setOnDismissListener { - onDismissListener?.invoke(TAG) - } - .create() + override fun getPositiveButtonText() = R.string.close + override suspend fun onShow() { b.teacherAbsenceView.setHasFixedSize(true) b.teacherAbsenceView.layoutManager = LinearLayoutManager(activity) - app.db.teacherAbsenceDao().getAllByDate(profileId, date).observe(activity as LifecycleOwner, Observer { absenceList -> + app.db.teacherAbsenceDao().getAllByDate(profileId, date).observe( + activity as LifecycleOwner + ) { absenceList -> val adapter = TeacherAbsenceAdapter(activity, date, absenceList) b.teacherAbsenceView.adapter = adapter b.teacherAbsenceView.visibility = View.VISIBLE - }) - - dialog.show() - }} + } + } } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/attendance/AttendanceDetailsDialog.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/attendance/AttendanceDetailsDialog.kt index 257360ec..4d33687d 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/attendance/AttendanceDetailsDialog.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/attendance/AttendanceDetailsDialog.kt @@ -4,54 +4,33 @@ package pl.szczodrzynski.edziennik.ui.attendance -import androidx.appcompat.app.AlertDialog +import android.view.LayoutInflater import androidx.appcompat.app.AppCompatActivity import androidx.core.graphics.ColorUtils -import com.google.android.material.dialog.MaterialAlertDialogBuilder -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job import pl.szczodrzynski.edziennik.App import pl.szczodrzynski.edziennik.R import pl.szczodrzynski.edziennik.data.db.full.AttendanceFull import pl.szczodrzynski.edziennik.databinding.AttendanceDetailsDialogBinding import pl.szczodrzynski.edziennik.ext.setTintColor +import pl.szczodrzynski.edziennik.ui.dialogs.base.BindingDialog import pl.szczodrzynski.edziennik.utils.BetterLink -import kotlin.coroutines.CoroutineContext class AttendanceDetailsDialog( - val activity: AppCompatActivity, - val attendance: AttendanceFull, - val onShowListener: ((tag: String) -> Unit)? = null, - val onDismissListener: ((tag: String) -> Unit)? = null -) : CoroutineScope { - companion object { - private const val TAG = "AttendanceDetailsDialog" - } + activity: AppCompatActivity, + private val attendance: AttendanceFull, + onShowListener: ((tag: String) -> Unit)? = null, + onDismissListener: ((tag: String) -> Unit)? = null, +) : BindingDialog(activity, onShowListener, onDismissListener) { - private lateinit var app: App - private lateinit var b: AttendanceDetailsDialogBinding - private lateinit var dialog: AlertDialog + override val TAG = "AttendanceDetailsDialog" - private val job = Job() - override val coroutineContext: CoroutineContext - get() = job + Dispatchers.Main + override fun getTitleRes(): Int? = null + override fun inflate(layoutInflater: LayoutInflater) = + AttendanceDetailsDialogBinding.inflate(layoutInflater) - // local variables go here + override fun getPositiveButtonText() = R.string.close - init { run { - if (activity.isFinishing) - return@run - onShowListener?.invoke(TAG) - app = activity.applicationContext as App - b = AttendanceDetailsDialogBinding.inflate(activity.layoutInflater) - dialog = MaterialAlertDialogBuilder(activity) - .setView(b.root) - .setPositiveButton(R.string.close, null) - .setOnDismissListener { - onDismissListener?.invoke(TAG) - } - .show() + override suspend fun onShow() { val manager = app.attendanceManager val attendanceColor = manager.getAttendanceColor(attendance) @@ -69,5 +48,5 @@ class AttendanceDetailsDialog( onActionSelected = dialog::dismiss ) } - }} + } } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/attendance/AttendanceFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/attendance/AttendanceFragment.kt index ac07d944..e5687a3c 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/attendance/AttendanceFragment.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/attendance/AttendanceFragment.kt @@ -67,7 +67,7 @@ class AttendanceFragment : Fragment(), CoroutineScope { .withIcon(CommunityMaterial.Icon.cmd_cog_outline) .withOnClickListener(View.OnClickListener { activity.bottomSheet.close() - AttendanceConfigDialog(activity, true, null, null) + AttendanceConfigDialog(activity, true, null, null).show() }), BottomSheetSeparatorItem(true), BottomSheetPrimaryItem(true) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/attendance/AttendanceListFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/attendance/AttendanceListFragment.kt index faec3261..6b056103 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/attendance/AttendanceListFragment.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/attendance/AttendanceListFragment.kt @@ -96,7 +96,7 @@ class AttendanceListFragment : LazyFragment(), CoroutineScope { }}) adapter.onAttendanceClick = { - AttendanceDetailsDialog(activity, it) + AttendanceDetailsDialog(activity, it).show() } }; return true} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/attendance/AttendanceSummaryFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/attendance/AttendanceSummaryFragment.kt index 91a4bfda..c8f0c226 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/attendance/AttendanceSummaryFragment.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/attendance/AttendanceSummaryFragment.kt @@ -108,7 +108,7 @@ class AttendanceSummaryFragment : LazyFragment(), CoroutineScope { }}) adapter.onAttendanceClick = { - AttendanceDetailsDialog(activity, it) + AttendanceDetailsDialog(activity, it).show() } b.toggleGroup.check(when (periodSelection) { diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/captcha/LibrusCaptchaDialog.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/captcha/LibrusCaptchaDialog.kt index be53e004..12ad0e37 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/captcha/LibrusCaptchaDialog.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/captcha/LibrusCaptchaDialog.kt @@ -5,58 +5,34 @@ package pl.szczodrzynski.edziennik.ui.captcha import android.graphics.drawable.Drawable +import android.view.LayoutInflater import android.view.View -import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AppCompatActivity -import com.google.android.material.dialog.MaterialAlertDialogBuilder -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job -import pl.szczodrzynski.edziennik.App import pl.szczodrzynski.edziennik.R import pl.szczodrzynski.edziennik.databinding.RecaptchaViewBinding import pl.szczodrzynski.edziennik.ext.onClick -import kotlin.coroutines.CoroutineContext +import pl.szczodrzynski.edziennik.ui.dialogs.base.BindingDialog class LibrusCaptchaDialog( - val activity: AppCompatActivity, - val onSuccess: (recaptchaCode: String) -> Unit, - val onFailure: (() -> Unit)?, - val onShowListener: ((tag: String) -> Unit)? = null, - val onDismissListener: ((tag: String) -> Unit)? = null -) : CoroutineScope { - companion object { - private const val TAG = "LibrusCaptchaDialog" - } + activity: AppCompatActivity, + private val onSuccess: (recaptchaCode: String) -> Unit, + private val onFailure: (() -> Unit)?, + onShowListener: ((tag: String) -> Unit)? = null, + onDismissListener: ((tag: String) -> Unit)? = null, +) : BindingDialog(activity, onShowListener, onDismissListener) { + override val TAG = "LibrusCaptchaDialog" - private lateinit var app: App - private lateinit var b: RecaptchaViewBinding - private lateinit var dialog: AlertDialog + override fun getTitleRes(): Int? = null + override fun inflate(layoutInflater: LayoutInflater) = + RecaptchaViewBinding.inflate(layoutInflater) - private val job = Job() - override val coroutineContext: CoroutineContext - get() = job + Dispatchers.Main + override fun getNegativeButtonText() = R.string.cancel private lateinit var checkboxBackground: Drawable private lateinit var checkboxForeground: Drawable private var success = false - init { run { - if (activity.isFinishing) - return@run - onShowListener?.invoke(TAG) - app = activity.applicationContext as App - b = RecaptchaViewBinding.inflate(activity.layoutInflater) - dialog = MaterialAlertDialogBuilder(activity) - .setView(b.root) - .setNegativeButton(R.string.cancel, null) - .setOnDismissListener { - if (!success) - onFailure?.invoke() - onDismissListener?.invoke(TAG) - } - .show() - + override suspend fun onShow() { checkboxBackground = b.checkbox.background checkboxForeground = b.checkbox.foreground success = false @@ -69,23 +45,28 @@ class LibrusCaptchaDialog( b.checkbox.foreground = null b.progress.visibility = View.VISIBLE RecaptchaDialog( - activity, - siteKey = "6Lf48moUAAAAAB9ClhdvHr46gRWR-CN31CXQPG2U", - referer = "https://portal.librus.pl/rodzina/login", - onSuccess = { recaptchaCode -> - b.checkbox.background = checkboxBackground - b.checkbox.foreground = checkboxForeground - b.progress.visibility = View.GONE - success = true - onSuccess(recaptchaCode) - dialog.dismiss() - }, - onFailure = { - b.checkbox.background = checkboxBackground - b.checkbox.foreground = checkboxForeground - b.progress.visibility = View.GONE - } - ) + activity, + siteKey = "6Lf48moUAAAAAB9ClhdvHr46gRWR-CN31CXQPG2U", + referer = "https://portal.librus.pl/rodzina/login", + onSuccess = { recaptchaCode -> + b.checkbox.background = checkboxBackground + b.checkbox.foreground = checkboxForeground + b.progress.visibility = View.GONE + success = true + onSuccess(recaptchaCode) + dialog.dismiss() + }, + onFailure = { + b.checkbox.background = checkboxBackground + b.checkbox.foreground = checkboxForeground + b.progress.visibility = View.GONE + } + ).show() } - }} + } + + override fun onDismiss() { + if (!success) + onFailure?.invoke() + } } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/captcha/RecaptchaDialog.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/captcha/RecaptchaDialog.kt index 81fd82af..cfecde91 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/captcha/RecaptchaDialog.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/captcha/RecaptchaDialog.kt @@ -6,129 +6,56 @@ package pl.szczodrzynski.edziennik.ui.captcha import android.graphics.Bitmap import android.graphics.BitmapFactory -import android.os.Handler -import android.util.Log import android.view.LayoutInflater import android.widget.Toast -import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AppCompatActivity -import com.google.android.material.dialog.MaterialAlertDialogBuilder import kotlinx.coroutines.* import okhttp3.* -import pl.szczodrzynski.edziennik.App +import pl.szczodrzynski.edziennik.R import pl.szczodrzynski.edziennik.databinding.RecaptchaDialogBinding +import pl.szczodrzynski.edziennik.ui.dialogs.base.BindingDialog import java.io.IOException -import kotlin.coroutines.CoroutineContext +import kotlin.coroutines.resume +import kotlin.coroutines.suspendCoroutine class RecaptchaDialog( - val activity: AppCompatActivity, - val siteKey: String, - val referer: String, - val autoRetry: Boolean = true, - val onSuccess: (recaptchaCode: String) -> Unit, - val onFailure: (() -> Unit)? = null, - val onShowListener: ((tag: String) -> Unit)? = null, - val onDismissListener: ((tag: String) -> Unit)? = null -) : CoroutineScope { - companion object { - private const val TAG = "RecaptchaDialog" - } + activity: AppCompatActivity, + private val siteKey: String, + private val referer: String, + private val autoRetry: Boolean = true, + private val onSuccess: (recaptchaCode: String) -> Unit, + private val onFailure: (() -> Unit)? = null, + onShowListener: ((tag: String) -> Unit)? = null, + onDismissListener: ((tag: String) -> Unit)? = null, +) : BindingDialog(activity, onShowListener, onDismissListener) { - private lateinit var app: App - private val b by lazy { RecaptchaDialogBinding.inflate(LayoutInflater.from(activity)) } - private var dialog: AlertDialog? = null + override val TAG = "RecaptchaDialog" + + override fun getTitleRes(): Int? = null + override fun inflate(layoutInflater: LayoutInflater) = + RecaptchaDialogBinding.inflate(layoutInflater) + + override fun getPositiveButtonText() = R.string.ok private val captchaUrl = "https://www.google.com/recaptcha/api/fallback?k=$siteKey" private var success = false - - private val job = Job() - override val coroutineContext: CoroutineContext - get() = job + Dispatchers.Main - private var code = "" private var payload = "" - init { run { - if (activity.isFinishing) - return@run - app = activity.applicationContext as App - onShowListener?.invoke(TAG) - success = false - - launch { initCaptcha() } - }} - - private suspend fun initCaptcha() { - withContext(Dispatchers.Default) { - val request = Request.Builder() - .url(captchaUrl) - .addHeader("Referer", referer) - .addHeader("Accept-Language", "pl") - .build() - app.http.newCall(request).enqueue(object : Callback { - override fun onResponse(call: Call, response: Response) { - val html = response.body()?.string() ?: return - Log.d(TAG, html) - parseHtml(html) - } - - override fun onFailure(call: Call, e: IOException) { - - } - }) + override suspend fun onBeforeShow(): Boolean { + val (title, text, bitmap) = withContext(Dispatchers.Default) { + val html = loadCaptchaHtml() ?: return@withContext null + return@withContext loadCaptchaData(html) + } ?: run { + onFailure?.invoke() + return false } + + initViews(title, text, bitmap) + return true } - private fun parseHtml(html: String) { - launch { - "class=\"rc-imageselect-desc(?:-no-canonical)?\">(.+?) (.+?)".toRegex().find(html)?.let { - b.descTitle.text = it.groupValues[1] - b.descText.text = it.groupValues[2] - } - code = "name=\"c\" value=\"([A-z0-9-_]+)\"".toRegex().find(html)?.let { it.groupValues[1] } ?: return@launch - payload = "https://www.google.com/recaptcha/api2/payload?c=$code&k=$siteKey" - withContext(Dispatchers.Default) { - val request = Request.Builder() - .url(payload) - .addHeader("Referer", captchaUrl) - .addHeader("Accept-Language", "pl") - .build() - app.http.newCall(request).enqueue(object : Callback { - override fun onResponse(call: Call, response: Response) { - val bitmap: Bitmap? = BitmapFactory.decodeStream(response.body()?.byteStream()) - Handler(activity.mainLooper).post { - if (bitmap == null) { - onFailure?.invoke() - Toast.makeText(activity, "Nie udało się załadować reCAPTCHA.", Toast.LENGTH_SHORT).show() - return@post - } - b.payload.setImageBitmap(bitmap) - showDialog() - } - } - - override fun onFailure(call: Call, e: IOException) { - onFailure?.invoke() - } - }) - } - } - } - - private fun showDialog() { - if (dialog == null) { - dialog = MaterialAlertDialogBuilder(activity) - .setView(b.root) - .setPositiveButton("OK") { _, _ -> - validateAnswer() - } - .setOnDismissListener { - if (!success) - onFailure?.invoke() - onDismissListener?.invoke(TAG) - } - .create() - } + override suspend fun onShow() { b.image0.isChecked = false b.image1.isChecked = false b.image2.isChecked = false @@ -138,51 +65,156 @@ class RecaptchaDialog( b.image6.isChecked = false b.image7.isChecked = false b.image8.isChecked = false - dialog!!.show() } - private fun validateAnswer() { - launch { - val list = mutableListOf( - "c=$code" - ) - if (b.image0.isChecked) list += "response=0" - if (b.image1.isChecked) list += "response=1" - if (b.image2.isChecked) list += "response=2" - if (b.image3.isChecked) list += "response=3" - if (b.image4.isChecked) list += "response=4" - if (b.image5.isChecked) list += "response=5" - if (b.image6.isChecked) list += "response=6" - if (b.image7.isChecked) list += "response=7" - if (b.image8.isChecked) list += "response=8" - val request = Request.Builder() - .url(captchaUrl) - .addHeader("Referer", captchaUrl) - .addHeader("Accept-Language", "pl") - .addHeader("Origin", "https://www.google.com") - .addHeader("Content-Type", "application/x-www-form-urlencoded") - .post(RequestBody.create(MediaType.parse("application/x-www-form-urlencoded"), list.joinToString("&"))) - .build() - withContext(Dispatchers.Default) { + override fun onDismiss() { + if (!success) + onFailure?.invoke() + } + + private fun initViews(title: String, text: String, bitmap: Bitmap) { + b.descTitle.text = title + b.descText.text = text + b.payload.setImageBitmap(bitmap) + } + + private suspend fun loadCaptchaHtml(): String? { + val request = Request.Builder() + .url(captchaUrl) + .addHeader("Referer", referer) + .addHeader("Accept-Language", "pl") + .build() + + return suspendCoroutine { cont -> + app.http.newCall(request).enqueue(object : Callback { + override fun onResponse(call: Call, response: Response) { + val html = response.body()?.string() + cont.resume(html) + } + + override fun onFailure(call: Call, e: IOException) { + cont.resume(null) + } + }) + } + } + + private suspend fun loadCaptchaData(html: String): Triple? { + var title = "" + var text = "" + "class=\"rc-imageselect-desc(?:-no-canonical)?\">(.+?) (.+?)" + .toRegex() + .find(html) + ?.let { + title = it.groupValues[1] + text = it.groupValues[2] + } + + code = "name=\"c\" value=\"([A-z0-9-_]+)\"" + .toRegex() + .find(html) + ?.let { it.groupValues[1] } + ?: return null + + payload = "https://www.google.com/recaptcha/api2/payload?c=$code&k=$siteKey" + val request = Request.Builder() + .url(payload) + .addHeader("Referer", captchaUrl) + .addHeader("Accept-Language", "pl") + .build() + + val bitmap = suspendCoroutine { cont -> + app.http.newCall(request).enqueue(object : Callback { + override fun onResponse(call: Call, response: Response) { + val bitmap: Bitmap? = BitmapFactory.decodeStream(response.body()?.byteStream()) + if (bitmap == null) { + Toast.makeText( + activity, + "Nie udało się załadować reCAPTCHA.", + Toast.LENGTH_SHORT + ).show() + } + cont.resume(bitmap) + } + + override fun onFailure(call: Call, e: IOException) { + cont.resume(null) + } + }) + } ?: return null + + return Triple(title, text, bitmap) + } + + override suspend fun onPositiveClick(): Boolean { + val list = mutableListOf( + "c=$code" + ) + if (b.image0.isChecked) list += "response=0" + if (b.image1.isChecked) list += "response=1" + if (b.image2.isChecked) list += "response=2" + if (b.image3.isChecked) list += "response=3" + if (b.image4.isChecked) list += "response=4" + if (b.image5.isChecked) list += "response=5" + if (b.image6.isChecked) list += "response=6" + if (b.image7.isChecked) list += "response=7" + if (b.image8.isChecked) list += "response=8" + + val request = Request.Builder() + .url(captchaUrl) + .addHeader("Referer", captchaUrl) + .addHeader("Accept-Language", "pl") + .addHeader("Origin", "https://www.google.com") + .addHeader("Content-Type", "application/x-www-form-urlencoded") + .post(RequestBody.create( + MediaType.parse("application/x-www-form-urlencoded"), + list.joinToString("&"), + )) + .build() + + val (code, html) = withContext(Dispatchers.Default) { + return@withContext suspendCoroutine> { cont -> app.http.newCall(request).enqueue(object : Callback { override fun onResponse(call: Call, response: Response) { - val html = response.body()?.string() ?: return - val match = "([A-z0-9-_]+)".toRegex().find(html) - if (match == null) { - parseHtml(html) + val html = response.body()?.string() ?: run { + cont.resume(null to null) return } - Handler(activity.mainLooper).post { - success = true - onSuccess(match.groupValues[1]) + val match = "([A-z0-9-_]+)".toRegex().find(html) + if (match == null) { + cont.resume(null to html) + } else { + cont.resume(match.groupValues[1] to null) } } override fun onFailure(call: Call, e: IOException) { - + cont.resume(null to null) } }) } } + + when { + code != null -> { + success = true + onSuccess(code) + return DISMISS + } + html != null -> { + val (title, text, bitmap) = withContext(Dispatchers.Default) { + return@withContext loadCaptchaData(html) + } ?: run { + onFailure?.invoke() + return DISMISS + } + initViews(title, text, bitmap) + return NO_DISMISS + } + else -> { + onFailure?.invoke() + return DISMISS + } + } } } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/debug/LabPageFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/debug/LabPageFragment.kt index 9dddfd00..9535579c 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/debug/LabPageFragment.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/debug/LabPageFragment.kt @@ -72,7 +72,7 @@ class LabPageFragment : LazyFragment(), CoroutineScope { } b.clearProfile.onClick { - ProfileRemoveDialog(activity, App.profileId, "FAKE", noProfileRemoval = true) + ProfileRemoveDialog(activity, App.profileId, "FAKE", noProfileRemoval = true).show() } b.removeHomework.onClick { diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/BellSyncDialog.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/BellSyncDialog.kt index eb3b85cb..abf48b45 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/BellSyncDialog.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/BellSyncDialog.kt @@ -4,41 +4,32 @@ package pl.szczodrzynski.edziennik.ui.dialogs -import androidx.appcompat.app.AlertDialog +import android.view.LayoutInflater import androidx.appcompat.app.AppCompatActivity import com.google.android.material.dialog.MaterialAlertDialogBuilder -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job -import kotlinx.coroutines.launch -import pl.szczodrzynski.edziennik.App import pl.szczodrzynski.edziennik.MainActivity import pl.szczodrzynski.edziennik.R import pl.szczodrzynski.edziennik.databinding.DialogBellSyncBinding import pl.szczodrzynski.edziennik.ext.resolveDrawable import pl.szczodrzynski.edziennik.ext.startCoroutineTimer +import pl.szczodrzynski.edziennik.ui.dialogs.base.BindingDialog import pl.szczodrzynski.edziennik.utils.models.Time -import kotlin.coroutines.CoroutineContext class BellSyncDialog( - val activity: AppCompatActivity, - private val bellTime: Time, - val onShowListener: ((tag: String) -> Unit)? = null, - val onDismissListener: ((tag: String) -> Unit)? = null -) : CoroutineScope { + activity: AppCompatActivity, + private val bellTime: Time, + onShowListener: ((tag: String) -> Unit)? = null, + onDismissListener: ((tag: String) -> Unit)? = null, +) : BindingDialog(activity, onShowListener, onDismissListener) { - companion object { - const val TAG = "BellSyncDialog" - } + override val TAG = "BellSyncDialog" - private lateinit var job: Job - override val coroutineContext: CoroutineContext - get() = job + Dispatchers.Main + override fun getTitleRes() = R.string.bell_sync_title + override fun inflate(layoutInflater: LayoutInflater) = + DialogBellSyncBinding.inflate(layoutInflater) - private lateinit var dialog: AlertDialog - private lateinit var b: DialogBellSyncBinding - - private val app by lazy { activity.application as App } + override fun getNeutralButtonText() = R.string.cancel private var counterJob: Job? = null @@ -50,25 +41,7 @@ class BellSyncDialog( return Pair(bellDiff, multiplier) } - init { apply { - if (activity.isFinishing) - return@apply - job = Job() - b = DialogBellSyncBinding.inflate(activity.layoutInflater) - onShowListener?.invoke(TAG) - dialog = MaterialAlertDialogBuilder(activity) - .setTitle(R.string.bell_sync_title) - .setView(b.root) - .setNeutralButton(R.string.cancel) { dialog, _ -> dialog.dismiss() } - .setOnDismissListener { - counterJob?.cancel() - onDismissListener?.invoke(TAG) - } - .show() - initView() - }} - - private fun initView() { + override suspend fun onShow() { b.bellSyncButton.setOnClickListener { val (bellDiff, multiplier) = actualBellDiff val bellDiffText = (if (multiplier == -1) '-' else '+') + bellDiff.stringHMS @@ -76,26 +49,29 @@ class BellSyncDialog( app.config.timetable.bellSyncMultiplier = multiplier MaterialAlertDialogBuilder(activity) - .setTitle(R.string.bell_sync_title) - .setMessage(app.getString(R.string.bell_sync_results, bellDiffText)) - .setPositiveButton(R.string.ok) { resultsDialog, _ -> - resultsDialog.dismiss() - dialog.dismiss() - if (activity is MainActivity) activity.reloadTarget() - } - .show() + .setTitle(R.string.bell_sync_title) + .setMessage(app.getString(R.string.bell_sync_results, bellDiffText)) + .setPositiveButton(R.string.ok) { resultsDialog, _ -> + resultsDialog.dismiss() + dialog.dismiss() + if (activity is MainActivity) activity.reloadTarget() + } + .show() } if (Time.diff(Time.getNow(), bellTime) > Time(2, 0, 0)) { // Easter egg ^^ b.bellSyncButton.setImageDrawable(R.drawable.ic_bell_wtf.resolveDrawable(app)) // wtf } - launch { - counterJob = startCoroutineTimer(repeatMillis = 500) { - val (bellDiff, multiplier) = actualBellDiff - val bellDiffText = (if (multiplier == -1) '-' else '+') + bellDiff.stringHMS - b.bellSyncHowto.text = app.getString(R.string.bell_sync_howto, bellTime.stringHM, bellDiffText) - } + counterJob = startCoroutineTimer(repeatMillis = 500) { + val (bellDiff, multiplier) = actualBellDiff + val bellDiffText = (if (multiplier == -1) '-' else '+') + bellDiff.stringHMS + b.bellSyncHowto.text = + app.getString(R.string.bell_sync_howto, bellTime.stringHM, bellDiffText) } } + + override fun onDismiss() { + counterJob?.cancel() + } } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/BellSyncTimeChooseDialog.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/BellSyncTimeChooseDialog.kt index e43100a8..6e11a50d 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/BellSyncTimeChooseDialog.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/BellSyncTimeChooseDialog.kt @@ -4,7 +4,7 @@ package pl.szczodrzynski.edziennik.ui.dialogs -import androidx.appcompat.app.AlertDialog +import android.view.LayoutInflater import androidx.appcompat.app.AppCompatActivity import com.google.android.material.dialog.MaterialAlertDialogBuilder import kotlinx.coroutines.* @@ -13,78 +13,74 @@ import pl.szczodrzynski.edziennik.MainActivity import pl.szczodrzynski.edziennik.R import pl.szczodrzynski.edziennik.data.db.entity.Lesson import pl.szczodrzynski.edziennik.databinding.DialogBellSyncTimeChooseBinding +import pl.szczodrzynski.edziennik.ui.dialogs.base.BindingDialog import pl.szczodrzynski.edziennik.utils.TextInputDropDown import pl.szczodrzynski.edziennik.utils.models.Date import pl.szczodrzynski.edziennik.utils.models.Time -import kotlin.coroutines.CoroutineContext class BellSyncTimeChooseDialog( - val activity: AppCompatActivity, - val onShowListener: ((tag: String) -> Unit)? = null, - val onDismissListener: ((tag: String) -> Unit)? = null -) : CoroutineScope { - + activity: AppCompatActivity, + onShowListener: ((tag: String) -> Unit)? = null, + onDismissListener: ((tag: String) -> Unit)? = null, +) : BindingDialog(activity, onShowListener, onDismissListener) { companion object { - const val TAG = "BellSyncTimeChooseDialog" - private const val MAX_DIFF_MINUTES = 10 } - private lateinit var job: Job - override val coroutineContext: CoroutineContext - get() = job + Dispatchers.Main + override val TAG = "BellSyncTimeChooseDialog" - private lateinit var dialog: AlertDialog - private lateinit var b: DialogBellSyncTimeChooseBinding + override fun getTitleRes() = R.string.bell_sync_title + override fun inflate(layoutInflater: LayoutInflater) = + DialogBellSyncTimeChooseBinding.inflate(layoutInflater) - private val app by lazy { activity.application as App } + override fun getPositiveButtonText() = R.string.ok + override fun getNeutralButtonText() = R.string.reset + override fun getNegativeButtonText() = R.string.cancel + + override suspend fun onShow() = Unit private val today = Date.getToday() private val selectedTime: Time? get() = b.timeDropdown.selected?.tag as Time? - init { apply { - if (activity.isFinishing) - return@apply - job = Job() - b = DialogBellSyncTimeChooseBinding.inflate(activity.layoutInflater) - onShowListener?.invoke(TAG) - dialog = MaterialAlertDialogBuilder(activity) - .setTitle(R.string.bell_sync_title) - .setView(b.root) - .setPositiveButton(R.string.ok) { dialog, _ -> - dialog.dismiss() - selectedTime?.let { - BellSyncDialog(activity, it) - } - } - .setNegativeButton(R.string.cancel) { dialog, _ -> dialog.dismiss() } - .setOnDismissListener { - onDismissListener?.invoke(TAG) - } - .create() - .apply { - setButton(AlertDialog.BUTTON_NEUTRAL, app.getString(R.string.reset)) { _, _ -> - showResetDialog() - } - } + override suspend fun onPositiveClick(): Boolean { + selectedTime?.let { + BellSyncDialog(activity, it).show() + } + return DISMISS + } - initView() - }} + override suspend fun onNeutralClick(): Boolean { + MaterialAlertDialogBuilder(activity) + .setTitle(R.string.bell_sync_title) + .setMessage(R.string.bell_sync_reset_confirm) + .setPositiveButton(R.string.yes) { dialog, _ -> + app.config.timetable.bellSyncDiff = null + app.config.timetable.bellSyncMultiplier = 0 - private fun initView() { + dialog.dismiss() + reload() + if (activity is MainActivity) + activity.reloadTarget() + } + .setNegativeButton(R.string.no, null) + .show() + return NO_DISMISS + } + + override suspend fun onBeforeShow(): Boolean { b.bellSyncHowto.text = app.getString(R.string.bell_sync_choose_howto) app.config.timetable.bellSyncDiff?.let { bellDiff -> val multiplier = app.config.timetable.bellSyncMultiplier val bellDiffText = (if (multiplier == -1) '-' else '+') + bellDiff.stringHMS b.bellSyncHowto.text = app.getString(R.string.concat_2_strings, - app.getString(R.string.bell_sync_choose_howto), - app.getString(R.string.bell_sync_current_dialog, bellDiffText) + app.getString(R.string.bell_sync_choose_howto), + app.getString(R.string.bell_sync_current_dialog, bellDiffText) ) } - loadTimeList() + return loadTimeList() } private fun checkForLessons(timeList: List