forked from github/wulkanowy-mirror
Add DatePicker to Timetable and Attendance modules. (#522)
This commit is contained in:
parent
38370d647d
commit
b7206ed714
@ -176,6 +176,7 @@ dependencies {
|
||||
implementation "at.favre.lib:slf4j-timber:1.0.1"
|
||||
implementation "com.squareup.okhttp3:logging-interceptor:3.12.6"
|
||||
implementation "com.mikepenz:aboutlibraries:7.0.4"
|
||||
implementation 'com.wdullaer:materialdatetimepicker:4.2.3'
|
||||
|
||||
playImplementation "com.google.firebase:firebase-core:17.2.1"
|
||||
playImplementation "com.crashlytics.sdk.android:crashlytics:2.10.1"
|
||||
|
@ -7,6 +7,7 @@ import android.view.MenuInflater
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.wdullaer.materialdatetimepicker.date.DatePickerDialog
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||
import eu.davidea.flexibleadapter.common.FlexibleItemDecoration
|
||||
import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager
|
||||
@ -17,9 +18,11 @@ import io.github.wulkanowy.ui.base.BaseFragment
|
||||
import io.github.wulkanowy.ui.modules.attendance.summary.AttendanceSummaryFragment
|
||||
import io.github.wulkanowy.ui.modules.main.MainActivity
|
||||
import io.github.wulkanowy.ui.modules.main.MainView
|
||||
import io.github.wulkanowy.utils.SchooldaysRangeLimiter
|
||||
import io.github.wulkanowy.utils.dpToPx
|
||||
import io.github.wulkanowy.utils.setOnItemClickListener
|
||||
import kotlinx.android.synthetic.main.fragment_attendance.*
|
||||
import org.threeten.bp.LocalDate
|
||||
import javax.inject.Inject
|
||||
|
||||
class AttendanceFragment : BaseFragment(), AttendanceView, MainView.MainChildView,
|
||||
@ -71,6 +74,7 @@ class AttendanceFragment : BaseFragment(), AttendanceView, MainView.MainChildVie
|
||||
|
||||
attendanceSwipe.setOnRefreshListener(presenter::onSwipeRefresh)
|
||||
attendancePreviousButton.setOnClickListener { presenter.onPreviousDay() }
|
||||
attendanceNavDate.setOnClickListener { presenter.onPickDate() }
|
||||
attendanceNextButton.setOnClickListener { presenter.onNextDay() }
|
||||
|
||||
attendanceNavContainer.setElevationCompat(requireContext().dpToPx(8f))
|
||||
@ -141,6 +145,21 @@ class AttendanceFragment : BaseFragment(), AttendanceView, MainView.MainChildVie
|
||||
(activity as? MainActivity)?.showDialogFragment(AttendanceDialog.newInstance(lesson))
|
||||
}
|
||||
|
||||
override fun showDatePickerDialog(currentDate: LocalDate) {
|
||||
val dateSetListener = DatePickerDialog.OnDateSetListener { _, year, month, dayOfMonth ->
|
||||
presenter.onDateSet(year, month + 1, dayOfMonth)
|
||||
}
|
||||
val datePickerDialog = DatePickerDialog.newInstance(dateSetListener,
|
||||
currentDate.year, currentDate.monthValue - 1, currentDate.dayOfMonth)
|
||||
|
||||
with(datePickerDialog) {
|
||||
setDateRangeLimiter(SchooldaysRangeLimiter())
|
||||
version = DatePickerDialog.Version.VERSION_2
|
||||
scrollOrientation = DatePickerDialog.ScrollOrientation.VERTICAL
|
||||
show(this@AttendanceFragment.parentFragmentManager, null)
|
||||
}
|
||||
}
|
||||
|
||||
override fun openSummaryView() {
|
||||
(activity as? MainActivity)?.pushView(AttendanceSummaryFragment.newInstance())
|
||||
}
|
||||
|
@ -56,6 +56,15 @@ class AttendancePresenter @Inject constructor(
|
||||
reloadView()
|
||||
}
|
||||
|
||||
fun onPickDate() {
|
||||
view?.showDatePickerDialog(currentDate)
|
||||
}
|
||||
|
||||
fun onDateSet(year: Int, month: Int, day: Int) {
|
||||
loadData(LocalDate.of(year, month, day))
|
||||
reloadView()
|
||||
}
|
||||
|
||||
fun onSwipeRefresh() {
|
||||
Timber.i("Force refreshing the attendance")
|
||||
loadData(currentDate, true)
|
||||
|
@ -2,6 +2,7 @@ package io.github.wulkanowy.ui.modules.attendance
|
||||
|
||||
import io.github.wulkanowy.data.db.entities.Attendance
|
||||
import io.github.wulkanowy.ui.base.BaseView
|
||||
import org.threeten.bp.LocalDate
|
||||
|
||||
interface AttendanceView : BaseView {
|
||||
|
||||
@ -35,6 +36,8 @@ interface AttendanceView : BaseView {
|
||||
|
||||
fun showAttendanceDialog(lesson: Attendance)
|
||||
|
||||
fun showDatePickerDialog(currentDate: LocalDate)
|
||||
|
||||
fun openSummaryView()
|
||||
|
||||
fun popView()
|
||||
|
@ -7,6 +7,7 @@ import android.view.MenuInflater
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.wdullaer.materialdatetimepicker.date.DatePickerDialog
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||
import eu.davidea.flexibleadapter.common.FlexibleItemDecoration
|
||||
import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager
|
||||
@ -17,9 +18,11 @@ import io.github.wulkanowy.ui.base.BaseFragment
|
||||
import io.github.wulkanowy.ui.modules.main.MainActivity
|
||||
import io.github.wulkanowy.ui.modules.main.MainView
|
||||
import io.github.wulkanowy.ui.modules.timetable.completed.CompletedLessonsFragment
|
||||
import io.github.wulkanowy.utils.SchooldaysRangeLimiter
|
||||
import io.github.wulkanowy.utils.dpToPx
|
||||
import io.github.wulkanowy.utils.setOnItemClickListener
|
||||
import kotlinx.android.synthetic.main.fragment_timetable.*
|
||||
import org.threeten.bp.LocalDate
|
||||
import javax.inject.Inject
|
||||
|
||||
class TimetableFragment : BaseFragment(), TimetableView, MainView.MainChildView,
|
||||
@ -72,6 +75,7 @@ class TimetableFragment : BaseFragment(), TimetableView, MainView.MainChildView,
|
||||
|
||||
timetableSwipe.setOnRefreshListener(presenter::onSwipeRefresh)
|
||||
timetablePreviousButton.setOnClickListener { presenter.onPreviousDay() }
|
||||
timetableNavDate.setOnClickListener {presenter.onPickDate() }
|
||||
timetableNextButton.setOnClickListener { presenter.onNextDay() }
|
||||
|
||||
timetableNavContainer.setElevationCompat(requireContext().dpToPx(8f))
|
||||
@ -142,6 +146,21 @@ class TimetableFragment : BaseFragment(), TimetableView, MainView.MainChildView,
|
||||
(activity as? MainActivity)?.showDialogFragment(TimetableDialog.newInstance(lesson))
|
||||
}
|
||||
|
||||
override fun showDatePickerDialog(currentDate: LocalDate) {
|
||||
val dateSetListener = DatePickerDialog.OnDateSetListener { _, year, month, dayOfMonth ->
|
||||
presenter.onDateSet(year, month + 1, dayOfMonth)
|
||||
}
|
||||
val datePickerDialog = DatePickerDialog.newInstance(dateSetListener,
|
||||
currentDate.year, currentDate.monthValue - 1, currentDate.dayOfMonth)
|
||||
|
||||
with(datePickerDialog) {
|
||||
setDateRangeLimiter(SchooldaysRangeLimiter())
|
||||
version = DatePickerDialog.Version.VERSION_2
|
||||
scrollOrientation = DatePickerDialog.ScrollOrientation.VERTICAL
|
||||
show(this@TimetableFragment.parentFragmentManager, null)
|
||||
}
|
||||
}
|
||||
|
||||
override fun openCompletedLessonsView() {
|
||||
(activity as? MainActivity)?.pushView(CompletedLessonsFragment.newInstance())
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ import io.github.wulkanowy.utils.previousSchoolDay
|
||||
import io.github.wulkanowy.utils.toFormattedString
|
||||
import org.threeten.bp.LocalDate
|
||||
import org.threeten.bp.LocalDate.now
|
||||
import org.threeten.bp.LocalDate.of
|
||||
import org.threeten.bp.LocalDate.ofEpochDay
|
||||
import timber.log.Timber
|
||||
import java.util.concurrent.TimeUnit.MILLISECONDS
|
||||
@ -55,6 +56,15 @@ class TimetablePresenter @Inject constructor(
|
||||
reloadView()
|
||||
}
|
||||
|
||||
fun onPickDate() {
|
||||
view?.showDatePickerDialog(currentDate)
|
||||
}
|
||||
|
||||
fun onDateSet(year: Int, month: Int, day: Int) {
|
||||
loadData(of(year, month, day))
|
||||
reloadView()
|
||||
}
|
||||
|
||||
fun onSwipeRefresh() {
|
||||
Timber.i("Force refreshing the timetable")
|
||||
loadData(currentDate, true)
|
||||
|
@ -2,6 +2,7 @@ package io.github.wulkanowy.ui.modules.timetable
|
||||
|
||||
import io.github.wulkanowy.data.db.entities.Timetable
|
||||
import io.github.wulkanowy.ui.base.BaseView
|
||||
import org.threeten.bp.LocalDate
|
||||
|
||||
interface TimetableView : BaseView {
|
||||
|
||||
@ -35,6 +36,8 @@ interface TimetableView : BaseView {
|
||||
|
||||
fun showTimetableDialog(lesson: Timetable)
|
||||
|
||||
fun showDatePickerDialog(currentDate: LocalDate)
|
||||
|
||||
fun popView()
|
||||
|
||||
fun openCompletedLessonsView()
|
||||
|
@ -4,6 +4,7 @@ import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.wdullaer.materialdatetimepicker.date.DatePickerDialog
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||
import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager
|
||||
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
||||
@ -12,10 +13,12 @@ import io.github.wulkanowy.data.db.entities.CompletedLesson
|
||||
import io.github.wulkanowy.ui.base.BaseFragment
|
||||
import io.github.wulkanowy.ui.modules.main.MainActivity
|
||||
import io.github.wulkanowy.ui.modules.main.MainView
|
||||
import io.github.wulkanowy.utils.SchooldaysRangeLimiter
|
||||
import io.github.wulkanowy.utils.dpToPx
|
||||
import io.github.wulkanowy.utils.getCompatDrawable
|
||||
import io.github.wulkanowy.utils.setOnItemClickListener
|
||||
import kotlinx.android.synthetic.main.fragment_timetable_completed.*
|
||||
import org.threeten.bp.LocalDate
|
||||
import javax.inject.Inject
|
||||
|
||||
class CompletedLessonsFragment : BaseFragment(), CompletedLessonsView, MainView.TitledView {
|
||||
@ -56,6 +59,7 @@ class CompletedLessonsFragment : BaseFragment(), CompletedLessonsView, MainView.
|
||||
|
||||
completedLessonsSwipe.setOnRefreshListener(presenter::onSwipeRefresh)
|
||||
completedLessonsPreviousButton.setOnClickListener { presenter.onPreviousDay() }
|
||||
completedLessonsNavDate.setOnClickListener { presenter.onPickDate() }
|
||||
completedLessonsNextButton.setOnClickListener { presenter.onNextDay() }
|
||||
|
||||
completedLessonsNavContainer.setElevationCompat(requireContext().dpToPx(8f))
|
||||
@ -110,6 +114,21 @@ class CompletedLessonsFragment : BaseFragment(), CompletedLessonsView, MainView.
|
||||
(activity as? MainActivity)?.showDialogFragment(CompletedLessonDialog.newInstance(completedLesson))
|
||||
}
|
||||
|
||||
override fun showDatePickerDialog(currentDate: LocalDate) {
|
||||
val dateSetListener = DatePickerDialog.OnDateSetListener { _, year, month, dayOfMonth ->
|
||||
presenter.onDateSet(year, month + 1, dayOfMonth)
|
||||
}
|
||||
val datePickerDialog = DatePickerDialog.newInstance(dateSetListener,
|
||||
currentDate.year, currentDate.monthValue - 1, currentDate.dayOfMonth)
|
||||
|
||||
with(datePickerDialog) {
|
||||
setDateRangeLimiter(SchooldaysRangeLimiter())
|
||||
version = DatePickerDialog.Version.VERSION_2
|
||||
scrollOrientation = DatePickerDialog.ScrollOrientation.VERTICAL
|
||||
show(this@CompletedLessonsFragment.parentFragmentManager, null)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
super.onSaveInstanceState(outState)
|
||||
outState.putLong(SAVED_DATE_KEY, presenter.currentDate.toEpochDay())
|
||||
|
@ -57,6 +57,15 @@ class CompletedLessonsPresenter @Inject constructor(
|
||||
reloadView()
|
||||
}
|
||||
|
||||
fun onPickDate() {
|
||||
view?.showDatePickerDialog(currentDate)
|
||||
}
|
||||
|
||||
fun onDateSet(year: Int, month: Int, day: Int) {
|
||||
loadData(LocalDate.of(year, month, day))
|
||||
reloadView()
|
||||
}
|
||||
|
||||
fun onSwipeRefresh() {
|
||||
Timber.i("Force refreshing the completed lessons")
|
||||
loadData(currentDate, true)
|
||||
|
@ -2,6 +2,7 @@ package io.github.wulkanowy.ui.modules.timetable.completed
|
||||
|
||||
import io.github.wulkanowy.data.db.entities.CompletedLesson
|
||||
import io.github.wulkanowy.ui.base.BaseView
|
||||
import org.threeten.bp.LocalDate
|
||||
|
||||
interface CompletedLessonsView : BaseView {
|
||||
|
||||
@ -32,4 +33,6 @@ interface CompletedLessonsView : BaseView {
|
||||
fun showNextButton(show: Boolean)
|
||||
|
||||
fun showCompletedLessonDialog(completedLesson: CompletedLesson)
|
||||
|
||||
fun showDatePickerDialog(currentDate: LocalDate)
|
||||
}
|
||||
|
@ -0,0 +1,51 @@
|
||||
package io.github.wulkanowy.utils
|
||||
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
import com.wdullaer.materialdatetimepicker.date.DateRangeLimiter
|
||||
import org.threeten.bp.DayOfWeek
|
||||
import org.threeten.bp.LocalDate
|
||||
import java.util.Calendar
|
||||
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
class SchooldaysRangeLimiter : DateRangeLimiter {
|
||||
|
||||
private val now = LocalDate.now()
|
||||
|
||||
override fun setToNearestDate(day: Calendar): Calendar = day
|
||||
|
||||
override fun isOutOfRange(year: Int, month: Int, day: Int): Boolean {
|
||||
val date = LocalDate.of(year, month + 1, day)
|
||||
val dayOfWeek = date.dayOfWeek
|
||||
return dayOfWeek == DayOfWeek.SUNDAY || dayOfWeek == DayOfWeek.SATURDAY || date.isHolidays
|
||||
}
|
||||
|
||||
override fun getStartDate(): Calendar {
|
||||
val startYear = if (now.monthValue <= 6) now.year - 1 else now.year
|
||||
val startOfSchoolYear = now.withYear(startYear).firstSchoolDay
|
||||
|
||||
val calendar = Calendar.getInstance()
|
||||
calendar.set(startOfSchoolYear.year, startOfSchoolYear.monthValue - 1, startOfSchoolYear.dayOfMonth)
|
||||
return calendar
|
||||
}
|
||||
|
||||
override fun getEndDate(): Calendar {
|
||||
val endYear = if (now.monthValue > 6) now.year + 1 else now.year
|
||||
val endOfSchoolYear = now.withYear(endYear).lastSchoolDay
|
||||
|
||||
val calendar = Calendar.getInstance()
|
||||
calendar.set(endOfSchoolYear.year, endOfSchoolYear.monthValue - 1, endOfSchoolYear.dayOfMonth)
|
||||
return calendar
|
||||
}
|
||||
|
||||
override fun writeToParcel(parcel: Parcel, flags: Int) {}
|
||||
|
||||
override fun describeContents() = 0
|
||||
|
||||
companion object CREATOR : Parcelable.Creator<SchooldaysRangeLimiter> {
|
||||
|
||||
override fun createFromParcel(parcel: Parcel): SchooldaysRangeLimiter = SchooldaysRangeLimiter()
|
||||
|
||||
override fun newArray(size: Int): Array<SchooldaysRangeLimiter?> = arrayOfNulls(size)
|
||||
}
|
||||
}
|
@ -60,8 +60,8 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:layout_gravity="bottom"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal"
|
||||
tools:ignore="UnusedAttribute">
|
||||
|
||||
<ImageButton
|
||||
@ -70,19 +70,20 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:contentDescription="@string/all_prev"
|
||||
android:paddingLeft="12dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingRight="12dp"
|
||||
android:paddingBottom="8dp"
|
||||
android:scaleType="fitStart"
|
||||
android:tint="?colorPrimary"
|
||||
app:srcCompat="@drawable/ic_chevron_left"
|
||||
android:contentDescription="@string/all_prev"/>
|
||||
app:srcCompat="@drawable/ic_chevron_left" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/attendanceNavDate"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:fontFamily="sans-serif"
|
||||
android:gravity="center"
|
||||
android:text="@string/app_name"
|
||||
@ -94,13 +95,13 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:contentDescription="@string/all_next"
|
||||
android:paddingLeft="12dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingRight="12dp"
|
||||
android:paddingBottom="8dp"
|
||||
android:scaleType="fitEnd"
|
||||
android:tint="?colorPrimary"
|
||||
app:srcCompat="@drawable/ic_chevron_right"
|
||||
android:contentDescription="@string/all_next" />
|
||||
app:srcCompat="@drawable/ic_chevron_right" />
|
||||
</io.github.wulkanowy.ui.widgets.MaterialLinearLayout>
|
||||
</FrameLayout>
|
||||
|
@ -60,28 +60,30 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:layout_gravity="bottom"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal"
|
||||
tools:ignore="UnusedAttribute">
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/timetablePreviousButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:contentDescription="@string/all_prev"
|
||||
android:paddingLeft="12dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingRight="12dp"
|
||||
android:paddingBottom="8dp"
|
||||
android:scaleType="fitStart"
|
||||
android:tint="?colorPrimary"
|
||||
app:srcCompat="@drawable/ic_chevron_left"
|
||||
android:contentDescription="@string/all_prev"/>
|
||||
app:srcCompat="@drawable/ic_chevron_left" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/timetableNavDate"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:fontFamily="sans-serif"
|
||||
android:gravity="center"
|
||||
android:text="@string/app_name"
|
||||
@ -93,13 +95,13 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:contentDescription="@string/all_next"
|
||||
android:paddingLeft="12dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingRight="12dp"
|
||||
android:paddingBottom="8dp"
|
||||
android:scaleType="fitEnd"
|
||||
android:tint="?colorPrimary"
|
||||
app:srcCompat="@drawable/ic_chevron_right"
|
||||
android:contentDescription="@string/all_next" />
|
||||
app:srcCompat="@drawable/ic_chevron_right" />
|
||||
</io.github.wulkanowy.ui.widgets.MaterialLinearLayout>
|
||||
</FrameLayout>
|
||||
|
@ -88,6 +88,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:fontFamily="sans-serif"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:gravity="center"
|
||||
android:text="@string/app_name"
|
||||
android:textSize="16sp" />
|
||||
|
@ -10,6 +10,7 @@
|
||||
<item name="android:textColor">?android:textColorPrimary</item>
|
||||
<item name="android:statusBarColor" tools:targetApi="lollipop">@android:color/black</item>
|
||||
<item name="android:windowLightNavigationBar" tools:targetApi="o_mr1">false</item>
|
||||
<item name="mdtp_theme_dark">true</item>
|
||||
</style>
|
||||
|
||||
<style name="WulkanowyTheme.Black" parent="WulkanowyTheme.NoActionBar">
|
||||
|
@ -29,4 +29,6 @@
|
||||
<item name="windowNoTitle">true</item>
|
||||
<item name="android:textColor">?android:textColorPrimary</item>
|
||||
</style>
|
||||
|
||||
<style name="mdtp_ActionButton.Text" parent="Widget.MaterialComponents.Button.TextButton.Dialog"/>
|
||||
</resources>
|
||||
|
Loading…
x
Reference in New Issue
Block a user