Skip to content
13 changes: 10 additions & 3 deletions app/src/main/kotlin/org/fossify/clock/activities/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ import org.fossify.clock.BuildConfig
import org.fossify.clock.R
import org.fossify.clock.adapters.ViewPagerAdapter
import org.fossify.clock.databinding.ActivityMainBinding
import org.fossify.clock.extensions.*
import org.fossify.clock.extensions.config
import org.fossify.clock.extensions.getEnabledAlarms
import org.fossify.clock.extensions.rescheduleEnabledAlarms
import org.fossify.clock.extensions.updateWidgets
import org.fossify.clock.helpers.*
import org.fossify.commons.databinding.BottomTablayoutItemBinding
import org.fossify.commons.extensions.*
Expand Down Expand Up @@ -127,7 +130,11 @@ class MainActivity : SimpleActivity() {
private fun setupOptionsMenu() {
binding.mainToolbar.setOnMenuItemClickListener { menuItem ->
when (menuItem.itemId) {
R.id.sort -> getViewPagerAdapter()?.showAlarmSortDialog()
R.id.sort -> when (binding.viewPager.currentItem) {
TAB_ALARM_INDEX -> getViewPagerAdapter()?.showAlarmSortDialog()
TAB_TIMER_INDEX -> getViewPagerAdapter()?.showTimerSortDialog()
}

R.id.more_apps_from_us -> launchMoreAppsFromUsIntent()
R.id.settings -> launchSettings()
R.id.about -> launchAbout()
Expand All @@ -139,7 +146,7 @@ class MainActivity : SimpleActivity() {

private fun refreshMenuItems() {
binding.mainToolbar.menu.apply {
findItem(R.id.sort).isVisible = binding.viewPager.currentItem == getTabIndex(TAB_ALARM)
findItem(R.id.sort).isVisible = binding.viewPager.currentItem == getTabIndex(TAB_ALARM) || binding.viewPager.currentItem == getTabIndex(TAB_TIMER)
findItem(R.id.more_apps_from_us).isVisible = !resources.getBoolean(org.fossify.commons.R.bool.hide_google_relations)
}
}
Expand Down
25 changes: 24 additions & 1 deletion app/src/main/kotlin/org/fossify/clock/adapters/TimerAdapter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,12 @@ import org.fossify.clock.models.TimerEvent
import org.fossify.clock.models.TimerState
import org.fossify.commons.adapters.MyRecyclerViewListAdapter
import org.fossify.commons.dialogs.PermissionRequiredDialog
import org.fossify.commons.extensions.*
import org.fossify.commons.extensions.adjustAlpha
import org.fossify.commons.extensions.applyColorFilter
import org.fossify.commons.extensions.beInvisibleIf
import org.fossify.commons.extensions.getColoredDrawableWithColor
import org.fossify.commons.extensions.getFormattedDuration
import org.fossify.commons.extensions.openNotificationSettings
import org.fossify.commons.views.MyRecyclerView
import org.greenrobot.eventbus.EventBus

Expand All @@ -41,6 +46,24 @@ class TimerAdapter(

init {
setupDragListener(true)
setHasStableIds(true)
}

override fun getItemId(position: Int): Long {
return getItem(position).id!!.toLong()
}

override fun submitList(list: MutableList<Timer>?, commitCallback: Runnable?) {
val layoutManager = recyclerView.layoutManager!!
val recyclerViewState = layoutManager.onSaveInstanceState()
super.submitList(list) {
layoutManager.onRestoreInstanceState(recyclerViewState)
commitCallback?.run()
}
}

override fun submitList(list: MutableList<Timer>?) {
submitList(list, null)
}

override fun getActionMenuId() = R.menu.cab_alarms
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ class ViewPagerAdapter(fm: FragmentManager) : FragmentStatePagerAdapter(fm) {
(fragments[TAB_ALARM_INDEX] as? AlarmFragment)?.showSortingDialog()
}

fun showTimerSortDialog() {
(fragments[TAB_TIMER_INDEX] as? TimerFragment)?.showSortingDialog()
}

fun updateClockTabAlarm() {
(fragments[TAB_CLOCK_INDEX] as? ClockFragment)?.updateAlarm()
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package org.fossify.clock.dialogs

import org.fossify.clock.R
import org.fossify.clock.databinding.DialogChangeTimerSortBinding
import org.fossify.clock.extensions.config
import org.fossify.clock.helpers.SORT_BY_CREATION_ORDER
import org.fossify.clock.helpers.SORT_BY_TIMER_DURATION
import org.fossify.commons.activities.BaseSimpleActivity
import org.fossify.commons.extensions.getAlertDialogBuilder
import org.fossify.commons.extensions.setupDialogStuff

class ChangeTimerSortDialog(val activity: BaseSimpleActivity, val callback: () -> Unit) {
private val binding = DialogChangeTimerSortBinding.inflate(activity.layoutInflater).apply {
val activeRadioButton = when (activity.config.timerSort) {
SORT_BY_TIMER_DURATION -> sortingDialogRadioTimerDuration
else -> sortingDialogRadioCreationOrder
}
activeRadioButton.isChecked = true
}

init {
activity.getAlertDialogBuilder()
.setPositiveButton(org.fossify.commons.R.string.ok) { _, _ -> dialogConfirmed() }
.setNegativeButton(org.fossify.commons.R.string.cancel, null)
.apply {
activity.setupDialogStuff(binding.root, this, org.fossify.commons.R.string.sort_by)
}
}

private fun dialogConfirmed() {
val sort = when (binding.sortingDialogRadioSorting.checkedRadioButtonId) {
R.id.sorting_dialog_radio_timer_duration -> SORT_BY_TIMER_DURATION
else -> SORT_BY_CREATION_ORDER
}

activity.config.timerSort = sort
callback()
}
}
74 changes: 58 additions & 16 deletions app/src/main/kotlin/org/fossify/clock/fragments/TimerFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,26 @@ import androidx.fragment.app.Fragment
import org.fossify.clock.activities.SimpleActivity
import org.fossify.clock.adapters.TimerAdapter
import org.fossify.clock.databinding.FragmentTimerBinding
import org.fossify.clock.dialogs.ChangeTimerSortDialog
import org.fossify.clock.dialogs.EditTimerDialog
import org.fossify.clock.extensions.config
import org.fossify.clock.extensions.createNewTimer
import org.fossify.clock.extensions.timerHelper
import org.fossify.clock.helpers.DisabledItemChangeAnimator
import org.fossify.clock.helpers.SORT_BY_TIMER_DURATION
import org.fossify.clock.models.Timer
import org.fossify.clock.models.TimerEvent
import org.fossify.commons.extensions.getProperBackgroundColor
import org.fossify.commons.extensions.getProperTextColor
import org.fossify.commons.extensions.hideKeyboard
import org.fossify.commons.extensions.updateTextColors
import org.fossify.commons.helpers.SORT_BY_DATE_CREATED
import org.fossify.commons.models.AlarmSound
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode

class TimerFragment : Fragment() {
private val INVALID_POSITION = -1
private lateinit var binding: FragmentTimerBinding
private lateinit var timerAdapter: TimerAdapter
private var timerPositionToScrollTo = INVALID_POSITION
Expand All @@ -43,7 +45,11 @@ class TimerFragment : Fragment() {
super.onDestroy()
}

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?,
): View {
binding = FragmentTimerBinding.inflate(inflater, container, false).apply {
timersList.itemAnimator = DisabledItemChangeAnimator()
timerAdd.setOnClickListener {
Expand Down Expand Up @@ -73,7 +79,12 @@ class TimerFragment : Fragment() {
timerAdapter.updateBackgroundColor(requireContext().getProperBackgroundColor())
timerAdapter.updateTextColor(requireContext().getProperTextColor())
} else {
timerAdapter = TimerAdapter(requireActivity() as SimpleActivity, binding.timersList, ::refreshTimers, ::openEditTimer)
timerAdapter = TimerAdapter(
simpleActivity = requireActivity() as SimpleActivity,
recyclerView = binding.timersList,
onRefresh = ::refreshTimers,
onItemClick = ::openEditTimer
)
binding.timersList.adapter = timerAdapter
}
}
Expand All @@ -85,16 +96,47 @@ class TimerFragment : Fragment() {
refreshTimers()
}

private fun refreshTimers(scrollToLatest: Boolean = false) {
fun showSortingDialog() {
ChangeTimerSortDialog(activity as SimpleActivity) {
refreshTimers(
animate = false // disable sorting animations for now.
)
}
}

private fun getSortedTimers(callback: (List<Timer>) -> Unit) {
activity?.timerHelper?.getTimers { timers ->
val sortedTimers = when (requireContext().config.timerSort) {
SORT_BY_TIMER_DURATION -> timers.sortedBy { it.seconds }
SORT_BY_DATE_CREATED -> timers.sortedBy { it.id }
else -> timers
}

activity?.runOnUiThread {
timerAdapter.submitList(timers) {
callback(sortedTimers)
}
}
}

private fun refreshTimers(animate: Boolean = true) {
getSortedTimers { timers ->
with(binding.timersList) {
val originalAnimator = itemAnimator
if (!animate) {
itemAnimator = null
}

timerAdapter.submitList(timers.toMutableList()) {
view?.post {
if (timerPositionToScrollTo != INVALID_POSITION && timerAdapter.itemCount > timerPositionToScrollTo) {
binding.timersList.scrollToPosition(timerPositionToScrollTo)
if (timerPositionToScrollTo != INVALID_POSITION &&
timerAdapter.itemCount > timerPositionToScrollTo
) {
smoothScrollToPosition(timerPositionToScrollTo)
timerPositionToScrollTo = INVALID_POSITION
} else if (scrollToLatest) {
binding.timersList.scrollToPosition(timers.lastIndex)
}

if (!animate) {
itemAnimator = originalAnimator
}
}
}
Expand All @@ -112,15 +154,13 @@ class TimerFragment : Fragment() {
}

fun updatePosition(timerId: Int) {
activity?.timerHelper?.getTimers { timers ->
getSortedTimers { timers ->
val position = timers.indexOfFirst { it.id == timerId }
if (position != INVALID_POSITION) {
activity?.runOnUiThread {
if (timerAdapter.itemCount > position) {
binding.timersList.scrollToPosition(position)
} else {
timerPositionToScrollTo = position
}
if (timerAdapter.itemCount > position) {
binding.timersList.smoothScrollToPosition(position)
} else {
timerPositionToScrollTo = position
}
}
}
Expand All @@ -133,3 +173,5 @@ class TimerFragment : Fragment() {
}
}
}

private const val INVALID_POSITION = -1
4 changes: 4 additions & 0 deletions app/src/main/kotlin/org/fossify/clock/helpers/Config.kt
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ class Config(context: Context) : BaseConfig(context) {
get() = prefs.getInt(ALARMS_SORT_BY, SORT_BY_CREATION_ORDER)
set(alarmSort) = prefs.edit().putInt(ALARMS_SORT_BY, alarmSort).apply()

var timerSort: Int
get() = prefs.getInt(TIMERS_SORT_BY, SORT_BY_CREATION_ORDER)
set(timerSort) = prefs.edit().putInt(TIMERS_SORT_BY, timerSort).apply()

var alarmMaxReminderSecs: Int
get() = prefs.getInt(ALARM_MAX_REMINDER_SECS, DEFAULT_MAX_ALARM_REMINDER_SECS)
set(alarmMaxReminderSecs) = prefs.edit().putInt(ALARM_MAX_REMINDER_SECS, alarmMaxReminderSecs).apply()
Expand Down
4 changes: 3 additions & 1 deletion app/src/main/kotlin/org/fossify/clock/helpers/Constants.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ const val ALARM_LAST_CONFIG = "alarm_last_config"
const val TIMER_LAST_CONFIG = "timer_last_config"
const val INCREASE_VOLUME_GRADUALLY = "increase_volume_gradually"
const val ALARMS_SORT_BY = "alarms_sort_by"
const val TIMERS_SORT_BY = "timers_sort_by"
const val STOPWATCH_LAPS_SORT_BY = "stopwatch_laps_sort_by"
const val WAS_INITIAL_WIDGET_SET_UP = "was_initial_widget_set_up"
const val DATA_EXPORT_EXTENSION = ".json"
Expand Down Expand Up @@ -70,10 +71,11 @@ const val SORT_BY_LAP = 1
const val SORT_BY_LAP_TIME = 2
const val SORT_BY_TOTAL_TIME = 4

// alarm sorting
// alarm and timer sorting
const val SORT_BY_CREATION_ORDER = 0
const val SORT_BY_ALARM_TIME = 1
const val SORT_BY_DATE_AND_TIME = 2
const val SORT_BY_TIMER_DURATION = 3

const val TODAY_BIT = -1
const val TOMORROW_BIT = -2
Expand Down
33 changes: 33 additions & 0 deletions app/src/main/res/layout/dialog_change_timer_sort.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/sorting_dialog_scrollview"
android:layout_width="match_parent"
android:layout_height="match_parent">

<RadioGroup
android:id="@+id/sorting_dialog_radio_sorting"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/medium_margin"
android:paddingStart="@dimen/activity_margin"
android:paddingTop="@dimen/activity_margin"
android:paddingEnd="@dimen/activity_margin">

<org.fossify.commons.views.MyCompatRadioButton
android:id="@+id/sorting_dialog_radio_creation_order"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="@dimen/medium_margin"
android:paddingBottom="@dimen/medium_margin"
android:text="@string/sort_by_creation_order" />

<org.fossify.commons.views.MyCompatRadioButton
android:id="@+id/sorting_dialog_radio_timer_duration"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="@dimen/medium_margin"
android:paddingBottom="@dimen/medium_margin"
android:text="@string/sort_by_timer_duration" />

</RadioGroup>
</ScrollView>
1 change: 1 addition & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
<string name="swipe_right_to_dismiss">Swipe right to Dismiss, or left to Snooze.</string>
<string name="sort_by_creation_order">Creation order</string>
<string name="sort_by_alarm_time">Alarm time</string>
<string name="sort_by_timer_duration">Timer duration</string>
<string name="sort_by_day_and_alarm_time">Day and Alarm time</string>
<string name="analogue_clock">Analogue clock</string>
<string name="digital_clock">Digital clock</string>
Expand Down
Loading