Merge branch 'timers_sort' into manual_sort

This commit is contained in:
ronniedroid
2024-04-28 11:42:07 +03:00
7 changed files with 128 additions and 183 deletions

View File

@@ -154,10 +154,6 @@ class MainActivity : SimpleActivity() {
if (intent.extras?.containsKey(OPEN_TAB) == true) {
val tabToOpen = intent.getIntExtra(OPEN_TAB, TAB_CLOCK)
binding.viewPager.setCurrentItem(tabToOpen, false)
if (tabToOpen == TAB_TIMER) {
val timerId = intent.getIntExtra(TIMER_ID, INVALID_TIMER_ID)
(binding.viewPager.adapter as ViewPagerAdapter).updateTimerPosition(timerId)
}
if (tabToOpen == TAB_STOPWATCH) {
if (intent.getBooleanExtra(TOGGLE_STOPWATCH, false)) {
(binding.viewPager.adapter as ViewPagerAdapter).startStopWatch()
@@ -205,10 +201,6 @@ class MainActivity : SimpleActivity() {
val tabToOpen = intent.getIntExtra(OPEN_TAB, config.lastUsedViewPagerPage)
intent.removeExtra(OPEN_TAB)
if (tabToOpen == TAB_TIMER) {
val timerId = intent.getIntExtra(TIMER_ID, INVALID_TIMER_ID)
viewPagerAdapter.updateTimerPosition(timerId)
}
if (tabToOpen == TAB_STOPWATCH) {
config.toggleStopwatch = intent.getBooleanExtra(TOGGLE_STOPWATCH, false)

View File

@@ -3,7 +3,6 @@ package org.fossify.clock.adapters
import android.view.Menu
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.DiffUtil
import me.grantland.widget.AutofitHelper
import org.fossify.clock.R
import org.fossify.clock.activities.SimpleActivity
@@ -14,30 +13,18 @@ import org.fossify.clock.extensions.secondsToMillis
import org.fossify.clock.models.Timer
import org.fossify.clock.models.TimerEvent
import org.fossify.clock.models.TimerState
import org.fossify.commons.adapters.MyRecyclerViewListAdapter
import org.fossify.commons.adapters.MyRecyclerViewAdapter
import org.fossify.commons.dialogs.PermissionRequiredDialog
import org.fossify.commons.extensions.*
import org.fossify.commons.views.MyRecyclerView
import org.greenrobot.eventbus.EventBus
class TimerAdapter(
private val simpleActivity: SimpleActivity,
activity: SimpleActivity,
var timers: ArrayList<Timer>,
recyclerView: MyRecyclerView,
onRefresh: () -> Unit,
onItemClick: (Timer) -> Unit,
) : MyRecyclerViewListAdapter<Timer>(simpleActivity, recyclerView, diffUtil, onItemClick, onRefresh) {
companion object {
private val diffUtil = object : DiffUtil.ItemCallback<Timer>() {
override fun areItemsTheSame(oldItem: Timer, newItem: Timer): Boolean {
return oldItem.id == newItem.id
}
override fun areContentsTheSame(oldItem: Timer, newItem: Timer): Boolean {
return oldItem == newItem
}
}
}
itemClick: (Any) -> Unit,
) : MyRecyclerViewAdapter(activity, recyclerView, itemClick) {
init {
setupDragListener(true)
@@ -57,22 +44,13 @@ class TimerAdapter(
}
}
override fun getSelectableItemCount() = itemCount
override fun getSelectableItemCount() = timers.size
override fun getIsItemSelectable(position: Int) = true
override fun getItemSelectionKey(position: Int) = getItem(position).id
override fun getItemSelectionKey(position: Int) = timers.getOrNull(position)?.id
override fun getItemKeyPosition(key: Int): Int {
var position = -1
for (i in 0 until itemCount) {
if (key == getItem(i).id) {
position = i
break
}
}
return position
}
override fun getItemKeyPosition(key: Int) = timers.indexOfFirst { it.id == key }
override fun onActionModeCreated() {}
@@ -83,25 +61,38 @@ class TimerAdapter(
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bindView(getItem(position), true, true) { itemView, _ ->
setupView(itemView, getItem(position))
val timer = timers[position]
holder.bindView(timer, true, true) { itemView, _ ->
setupView(itemView, timer)
}
bindViewHolder(holder)
}
override fun getItemCount() = timers.size
fun updateItems(newItems: ArrayList<Timer>) {
timers = newItems
notifyDataSetChanged()
finishActMode()
}
private fun deleteItems() {
val timersToRemove = ArrayList<Timer>()
val positions = getSelectedItemPositions()
val timersToRemove = positions.map { position ->
getItem(position)
getSelectedItems().forEach {
timersToRemove.add(it)
}
timers.removeAll(timersToRemove)
removeSelectedItems(positions)
timersToRemove.forEach(::deleteTimer)
}
private fun getSelectedItems() = timers.filter { selectedKeys.contains(it.id) } as ArrayList<Timer>
private fun setupView(view: View, timer: Timer) {
ItemTimerBinding.bind(view).apply {
val isSelected = selectedKeys.contains(timer.id)
timerFrame.isSelected = isSelected
timerHolder.isSelected = isSelected
timerLabel.setTextColor(textColor)
timerLabel.setHintTextColor(textColor.adjustAlpha(0.7f))
@@ -148,17 +139,17 @@ class TimerAdapter(
} else {
org.fossify.commons.R.drawable.ic_play_vector
}
timerPlayPause.setImageDrawable(simpleActivity.resources.getColoredDrawableWithColor(drawableId, textColor))
timerPlayPause.setImageDrawable(activity.resources.getColoredDrawableWithColor(drawableId, textColor))
}
}
private fun resetTimer(timer: Timer) {
EventBus.getDefault().post(TimerEvent.Reset(timer.id!!))
simpleActivity.hideTimerNotification(timer.id!!)
activity.hideTimerNotification(timer.id!!)
}
private fun deleteTimer(timer: Timer) {
EventBus.getDefault().post(TimerEvent.Delete(timer.id!!))
simpleActivity.hideTimerNotification(timer.id!!)
activity.hideTimerNotification(timer.id!!)
}
}

View File

@@ -61,10 +61,6 @@ class ViewPagerAdapter(fm: FragmentManager) : FragmentStatePagerAdapter(fm) {
(fragments[TAB_TIMER] as? TimerFragment)?.updateAlarmSound(alarmSound)
}
fun updateTimerPosition(timerId: Int) {
(fragments[TAB_TIMER] as? TimerFragment)?.updatePosition(timerId)
}
fun startStopWatch() {
(fragments[TAB_STOPWATCH] as? StopwatchFragment)?.startStopWatch()
}

View File

@@ -15,7 +15,6 @@ 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
@@ -30,10 +29,8 @@ import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
class TimerFragment : Fragment() {
private val INVALID_POSITION = -1
private var timers = ArrayList<Timer>()
private lateinit var binding: FragmentTimerBinding
private lateinit var timerAdapter: TimerAdapter
private var timerPositionToScrollTo = INVALID_POSITION
private var currentEditAlarmDialog: EditTimerDialog? = null
override fun onCreate(savedInstanceState: Bundle?) {
@@ -48,7 +45,7 @@ class TimerFragment : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
binding = FragmentTimerBinding.inflate(inflater, container, false).apply {
timersList.itemAnimator = DisabledItemChangeAnimator()
requireContext().updateTextColors(timerFragment)
timerAdd.setOnClickListener {
activity?.run {
hideKeyboard()
@@ -57,7 +54,6 @@ class TimerFragment : Fragment() {
}
}
initOrUpdateAdapter()
refreshTimers()
// the initial timer is created asynchronously at first launch, make sure we show it once created
@@ -70,21 +66,8 @@ class TimerFragment : Fragment() {
return binding.root
}
private fun initOrUpdateAdapter() {
if (this::timerAdapter.isInitialized) {
timerAdapter.updatePrimaryColor()
timerAdapter.updateBackgroundColor(requireContext().getProperBackgroundColor())
timerAdapter.updateTextColor(requireContext().getProperTextColor())
} else {
timerAdapter = TimerAdapter(requireActivity() as SimpleActivity, binding.timersList, ::refreshTimers, ::openEditTimer)
binding.timersList.adapter = timerAdapter
}
}
override fun onResume() {
super.onResume()
requireContext().updateTextColors(binding.root)
initOrUpdateAdapter()
refreshTimers()
}
@@ -94,22 +77,27 @@ class TimerFragment : Fragment() {
}
}
private fun refreshTimers(scrollToLatest: Boolean = false) {
activity?.timerHelper?.getTimers { timers ->
var sortedTimers: List<Timer> = timers
private fun refreshTimers() {
activity?.timerHelper?.getTimers { timersFromDB ->
timers = timersFromDB
when (requireContext().config.timerSort) {
SORT_BY_TIMER_DURATION -> sortedTimers = timers.sortedBy { it.seconds }
SORT_BY_DATE_CREATED -> sortedTimers = timers.sortedBy { it.id }
SORT_BY_TIMER_DURATION -> timers.sortBy { it.seconds }
SORT_BY_DATE_CREATED -> timers.sortBy { it.id }
}
activity?.runOnUiThread {
timerAdapter.submitList(sortedTimers) {
view?.post {
if (timerPositionToScrollTo != INVALID_POSITION && timerAdapter.itemCount > timerPositionToScrollTo) {
binding.timersList.scrollToPosition(timerPositionToScrollTo)
timerPositionToScrollTo = INVALID_POSITION
} else if (scrollToLatest) {
binding.timersList.scrollToPosition(sortedTimers.lastIndex)
}
val currAdapter = binding.timersList.adapter
if (currAdapter == null) {
TimerAdapter(activity as SimpleActivity, timers, binding.timersList) {
openEditTimer(it as Timer)
}.apply {
binding.timersList.adapter = this
}
} else {
(currAdapter as TimerAdapter).apply {
updatePrimaryColor()
updateBackgroundColor(requireContext().getProperBackgroundColor())
updateTextColor(requireContext().getProperTextColor())
updateItems(this@TimerFragment.timers)
}
}
}
@@ -125,21 +113,6 @@ class TimerFragment : Fragment() {
currentEditAlarmDialog?.updateAlarmSound(alarmSound)
}
fun updatePosition(timerId: Int) {
activity?.timerHelper?.getTimers { 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
}
}
}
}
}
private fun openEditTimer(timer: Timer) {
currentEditAlarmDialog = EditTimerDialog(activity as SimpleActivity, timer) {
currentEditAlarmDialog = null

View File

@@ -8,9 +8,9 @@ import org.fossify.commons.helpers.ensureBackgroundThread
class TimerHelper(val context: Context) {
private val timerDao = context.timerDb
fun getTimers(callback: (timers: List<Timer>) -> Unit) {
fun getTimers(callback: (timers: ArrayList<Timer>) -> Unit) {
ensureBackgroundThread {
callback.invoke(timerDao.getTimers())
callback.invoke(timerDao.getTimers() as ArrayList<Timer>)
}
}

View File

@@ -1,24 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/timer_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent">
<org.fossify.commons.views.MyRecyclerView
android:id="@+id/timers_list"
<RelativeLayout
android:id="@+id/timer_holder"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:paddingBottom="@dimen/fab_list_bottom_padding"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:itemCount="3"
tools:listitem="@layout/item_timer" />
android:layout_height="match_parent">
<org.fossify.commons.views.MyRecyclerView
android:id="@+id/timers_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:overScrollMode="ifContentScrolls"
android:paddingBottom="@dimen/fab_list_bottom_padding"
android:scrollbars="none"
app:layoutManager="org.fossify.commons.views.MyLinearLayoutManager"
tools:listitem="@layout/item_timer" />
</RelativeLayout>
<org.fossify.commons.views.MyFloatingActionButton
android:id="@+id/timer_add"
@@ -26,13 +30,8 @@
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/activity_margin"
android:contentDescription="@string/new_timer"
android:src="@drawable/ic_plus_vector"
app:backgroundTint="@color/color_primary"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:rippleColor="@color/pressed_item_foreground" />
android:src="@drawable/ic_plus_vector" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@@ -1,77 +1,71 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/timer_frame"
android:id="@+id/timer_holder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?selectableItemBackground"
android:background="?attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:foreground="@drawable/selector">
android:foreground="@drawable/selector"
android:paddingHorizontal="@dimen/activity_margin"
android:paddingVertical="@dimen/medium_margin">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
<org.fossify.commons.views.MyTextView
android:id="@+id/timer_time"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:paddingStart="@dimen/activity_margin"
android:paddingTop="@dimen/medium_margin"
android:paddingBottom="@dimen/activity_margin">
android:includeFontPadding="false"
android:maxLines="1"
android:textSize="@dimen/alarm_text_size"
app:layout_constraintEnd_toStartOf="@id/timer_reset"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="00:00" />
<TextView
android:id="@+id/timer_time"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:includeFontPadding="false"
android:maxLines="1"
android:textSize="@dimen/alarm_text_size"
app:layout_constraintEnd_toStartOf="@id/timer_reset"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="00:00" />
<org.fossify.commons.views.MyTextView
android:id="@+id/timer_label"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:ellipsize="end"
android:includeFontPadding="false"
android:maxLines="1"
android:textSize="@dimen/bigger_text_size"
app:layout_constraintEnd_toEndOf="@id/timer_time"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/timer_time"
tools:text="Cook rice" />
<org.fossify.commons.views.MyTextView
android:id="@+id/timer_label"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:ellipsize="end"
android:includeFontPadding="false"
android:maxLines="1"
android:textSize="@dimen/bigger_text_size"
app:layout_constraintEnd_toEndOf="@id/timer_time"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/timer_time"
tools:text="Cook rice" />
<ImageView
android:id="@+id/timer_reset"
android:layout_width="@dimen/timer_button_small_size"
android:layout_height="@dimen/timer_button_small_size"
android:layout_marginStart="@dimen/medium_margin"
android:layout_marginEnd="@dimen/medium_margin"
android:background="?attr/selectableItemBackgroundBorderless"
android:padding="@dimen/normal_margin"
android:src="@drawable/ic_reset_vector"
android:visibility="visible"
app:layout_constraintBottom_toBottomOf="@+id/timer_play_pause"
app:layout_constraintEnd_toStartOf="@+id/timer_play_pause"
app:layout_constraintStart_toEndOf="@id/timer_time"
app:layout_constraintTop_toTopOf="@id/timer_play_pause" />
<ImageView
android:id="@+id/timer_reset"
android:layout_width="@dimen/timer_button_small_size"
android:layout_height="@dimen/timer_button_small_size"
android:layout_marginStart="@dimen/medium_margin"
android:layout_marginEnd="@dimen/medium_margin"
android:background="?attr/selectableItemBackgroundBorderless"
android:padding="@dimen/normal_margin"
android:src="@drawable/ic_reset_vector"
android:visibility="visible"
app:layout_constraintBottom_toBottomOf="@+id/timer_play_pause"
app:layout_constraintEnd_toStartOf="@+id/timer_play_pause"
app:layout_constraintStart_toEndOf="@id/timer_time"
app:layout_constraintTop_toTopOf="@id/timer_play_pause" />
<ImageView
android:id="@+id/timer_play_pause"
android:layout_width="@dimen/timer_button_size"
android:layout_height="@dimen/timer_button_size"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginStart="@dimen/medium_margin"
android:layout_marginEnd="@dimen/small_margin"
android:background="?attr/selectableItemBackgroundBorderless"
android:padding="@dimen/activity_margin"
android:src="@drawable/ic_play_vector"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/timer_reset"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/timer_play_pause"
android:layout_width="@dimen/timer_button_size"
android:layout_height="@dimen/timer_button_size"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginStart="@dimen/medium_margin"
android:layout_marginEnd="@dimen/small_margin"
android:background="?attr/selectableItemBackgroundBorderless"
android:padding="@dimen/activity_margin"
android:src="@drawable/ic_play_vector"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/timer_reset"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>