diff --git a/app/build.gradle b/app/build.gradle index 6a14957..e82a167 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -67,7 +67,8 @@ android { } dependencies { - implementation 'com.github.SimpleMobileTools:Simple-Commons:554dda71a4' +// implementation 'com.github.SimpleMobileTools:Simple-Commons:554dda71a4' + implementation project(":commons") implementation 'com.facebook.stetho:stetho:1.5.0' implementation 'androidx.constraintlayout:constraintlayout:2.0.4' implementation 'com.shawnlin:number-picker:2.4.6' diff --git a/app/src/main/kotlin/com/simplemobiletools/clock/App.kt b/app/src/main/kotlin/com/simplemobiletools/clock/App.kt index 7bc445f..308a3c1 100644 --- a/app/src/main/kotlin/com/simplemobiletools/clock/App.kt +++ b/app/src/main/kotlin/com/simplemobiletools/clock/App.kt @@ -26,7 +26,7 @@ import org.greenrobot.eventbus.ThreadMode class App : Application(), LifecycleObserver { - private var countDownTimers = mutableMapOf() + private var countDownTimers = mutableMapOf() override fun onCreate() { super.onCreate() @@ -108,7 +108,7 @@ class App : Application(), LifecycleObserver { } } - private fun updateTimerState(timerId: Long, state: TimerState) { + private fun updateTimerState(timerId: Int, state: TimerState) { timerHelper.getTimer(timerId) { timer -> val newTimer = timer.copy(state = state) timerHelper.insertOrUpdateTimer(newTimer) { diff --git a/app/src/main/kotlin/com/simplemobiletools/clock/activities/MainActivity.kt b/app/src/main/kotlin/com/simplemobiletools/clock/activities/MainActivity.kt index 015e49a..1d80297 100644 --- a/app/src/main/kotlin/com/simplemobiletools/clock/activities/MainActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/clock/activities/MainActivity.kt @@ -104,7 +104,7 @@ class MainActivity : SimpleActivity() { val tabToOpen = intent.getIntExtra(OPEN_TAB, TAB_CLOCK) view_pager.setCurrentItem(tabToOpen, false) if (tabToOpen == TAB_TIMER) { - val timerId = intent.getLongExtra(TIMER_ID, INVALID_TIMER_ID) + val timerId = intent.getIntExtra(TIMER_ID, INVALID_TIMER_ID) (view_pager.adapter as ViewPagerAdapter).updateTimerPosition(timerId) } } @@ -152,7 +152,7 @@ class MainActivity : SimpleActivity() { val tabToOpen = intent.getIntExtra(OPEN_TAB, config.lastUsedViewPagerPage) intent.removeExtra(OPEN_TAB) if (tabToOpen == TAB_TIMER) { - val timerId = intent.getLongExtra(TIMER_ID, INVALID_TIMER_ID) + val timerId = intent.getIntExtra(TIMER_ID, INVALID_TIMER_ID) viewPagerAdapter.updateTimerPosition(timerId) } view_pager.currentItem = tabToOpen diff --git a/app/src/main/kotlin/com/simplemobiletools/clock/activities/SplashActivity.kt b/app/src/main/kotlin/com/simplemobiletools/clock/activities/SplashActivity.kt index 164ace1..d2d8c73 100644 --- a/app/src/main/kotlin/com/simplemobiletools/clock/activities/SplashActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/clock/activities/SplashActivity.kt @@ -16,7 +16,7 @@ class SplashActivity : BaseSplashActivity() { intent.extras?.containsKey(OPEN_TAB) == true -> { Intent(this, MainActivity::class.java).apply { putExtra(OPEN_TAB, intent.getIntExtra(OPEN_TAB, TAB_CLOCK)) - putExtra(TIMER_ID, intent.getLongExtra(TIMER_ID, INVALID_TIMER_ID)) + putExtra(TIMER_ID, intent.getIntExtra(TIMER_ID, INVALID_TIMER_ID)) startActivity(this) } } diff --git a/app/src/main/kotlin/com/simplemobiletools/clock/adapters/TimerAdapter.kt b/app/src/main/kotlin/com/simplemobiletools/clock/adapters/TimerAdapter.kt index e5f864d..208be25 100644 --- a/app/src/main/kotlin/com/simplemobiletools/clock/adapters/TimerAdapter.kt +++ b/app/src/main/kotlin/com/simplemobiletools/clock/adapters/TimerAdapter.kt @@ -1,28 +1,32 @@ package com.simplemobiletools.clock.adapters import android.graphics.Color -import android.view.LayoutInflater +import android.view.Menu import android.view.View import android.view.ViewGroup import androidx.recyclerview.widget.DiffUtil -import androidx.recyclerview.widget.ListAdapter -import androidx.recyclerview.widget.RecyclerView import com.simplemobiletools.clock.R import com.simplemobiletools.clock.activities.SimpleActivity import com.simplemobiletools.clock.dialogs.MyTimePickerDialogDialog -import com.simplemobiletools.clock.extensions.* +import com.simplemobiletools.clock.extensions.getFormattedDuration +import com.simplemobiletools.clock.extensions.hideTimerNotification +import com.simplemobiletools.clock.extensions.secondsToMillis +import com.simplemobiletools.clock.extensions.timerHelper import com.simplemobiletools.clock.models.Timer import com.simplemobiletools.clock.models.TimerEvent import com.simplemobiletools.clock.models.TimerState +import com.simplemobiletools.commons.adapters.MyRecyclerViewListAdapter import com.simplemobiletools.commons.extensions.* +import com.simplemobiletools.commons.views.MyRecyclerView import kotlinx.android.synthetic.main.item_timer.view.* import org.greenrobot.eventbus.EventBus class TimerAdapter( - private val activity: SimpleActivity, - private val onRefresh: () -> Unit, - private val onClick: (Timer) -> Unit, -) : ListAdapter(diffUtil) { + private val simpleActivity: SimpleActivity, + recyclerView: MyRecyclerView, + onRefresh: () -> Unit, + private val onItemClick: (Timer) -> Unit, +) : MyRecyclerViewListAdapter(simpleActivity, recyclerView, diffUtil, null, onItemClick, onRefresh) { companion object { private val diffUtil = object : DiffUtil.ItemCallback() { @@ -36,101 +40,130 @@ class TimerAdapter( } } - private val config = activity.config - private var textColor = config.textColor - private var adjustedPrimaryColor = activity.getAdjustedPrimaryColor() - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TimerViewHolder { - return TimerViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.item_timer, parent, false)) + init { + setupDragListener(true) } - override fun onBindViewHolder(holder: TimerViewHolder, position: Int) { - holder.bind(getItem(position)) - } + override fun getActionMenuId() = R.menu.cab_alarms - fun updateTextColor(textColor: Int) { - this.textColor = textColor - onRefresh.invoke() - } + override fun prepareActionMode(menu: Menu) {} - inner class TimerViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { - - fun bind(timer: Timer) { - itemView.apply { - post { - timer_play_pause.background = activity.resources.getColoredDrawableWithColor(R.drawable.circle_background_filled, adjustedPrimaryColor) - timer_play_pause.applyColorFilter(if (adjustedPrimaryColor == Color.WHITE) Color.BLACK else Color.WHITE) - timer_reset.applyColorFilter(textColor) - timer_delete.applyColorFilter(textColor) - } - timer_label.setTextColor(textColor) - timer_label.setHintTextColor(textColor.adjustAlpha(0.7f)) - //only update when different to prevent flickering and unnecessary updates - if (timer_label.text.toString() != timer.label) { - timer_label.setText(timer.label) - } - - - timer_time.setTextColor(textColor) - timer_time.text = when (timer.state) { - is TimerState.Finished -> 0.getFormattedDuration() - is TimerState.Idle -> timer.seconds.getFormattedDuration() - is TimerState.Paused -> timer.state.tick.getFormattedDuration() - is TimerState.Running -> timer.state.tick.getFormattedDuration() - } - timer_time.setOnClickListener { - changeDuration(timer) - } - - timer_delete.applyColorFilter(textColor) - timer_delete.setOnClickListener { - activity.timerHelper.deleteTimer(timer.id!!) { - onRefresh.invoke() - } - } - - timer_reset.applyColorFilter(textColor) - timer_reset.setOnClickListener { - stopTimer(timer) - } - - - timer_play_pause.setOnClickListener { - when (val state = timer.state) { - is TimerState.Idle -> EventBus.getDefault().post(TimerEvent.Start(timer.id!!, timer.seconds.secondsToMillis)) - is TimerState.Paused -> EventBus.getDefault().post(TimerEvent.Start(timer.id!!, state.tick)) - is TimerState.Running -> EventBus.getDefault().post(TimerEvent.Pause(timer.id!!, state.tick)) - is TimerState.Finished -> EventBus.getDefault().post(TimerEvent.Start(timer.id!!, timer.seconds.secondsToMillis)) - } - } - - updateViewStates(timer.state) - - setOnClickListener { - onClick.invoke(timer) - } - } + override fun actionItemPressed(id: Int) { + if (selectedKeys.isEmpty()) { + return } - private fun updateViewStates(state: TimerState) { + when (id) { + R.id.cab_delete -> deleteItems() + } + } + + override fun getSelectableItemCount() = itemCount + + override fun getIsItemSelectable(position: Int) = true + + override fun getItemSelectionKey(position: Int) = getItem(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 onActionModeCreated() {} + + override fun onActionModeDestroyed() {} + + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = createViewHolder(R.layout.item_timer, parent) + + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + holder.bindView(getItem(position), true, true) { itemView, _ -> + setupView(itemView, getItem(position)) + } + bindViewHolder(holder) + } + + private fun deleteItems() { + val positions = getSelectedItemPositions() + val timersToRemove = positions.map { position -> + getItem(position) + } + removeSelectedItems(positions) + activity.timerHelper.deleteTimers(timersToRemove) { + onRefresh.invoke() + } + } + + + private fun setupView(view: View, timer: Timer) { + view.apply { + val isSelected = selectedKeys.contains(timer.id) + timer_frame.isSelected = isSelected + + timer_label.setTextColor(textColor) + timer_label.setHintTextColor(textColor.adjustAlpha(0.7f)) + timer_label.text = timer.label + + timer_time.setTextColor(textColor) + timer_time.text = when (timer.state) { + is TimerState.Finished -> 0.getFormattedDuration() + is TimerState.Idle -> timer.seconds.getFormattedDuration() + is TimerState.Paused -> timer.state.tick.getFormattedDuration() + is TimerState.Running -> timer.state.tick.getFormattedDuration() + } + timer_time.setOnClickListener { + changeDuration(timer) + } + + timer_delete.applyColorFilter(textColor) + timer_delete.setOnClickListener { + simpleActivity.timerHelper.deleteTimer(timer.id!!) { + onRefresh.invoke() + } + } + + timer_reset.applyColorFilter(textColor) + timer_reset.setOnClickListener { + stopTimer(timer) + } + + timer_play_pause.background = simpleActivity.resources.getColoredDrawableWithColor(R.drawable.circle_background_filled, adjustedPrimaryColor) + timer_play_pause.applyColorFilter(if (adjustedPrimaryColor == Color.WHITE) Color.BLACK else Color.WHITE) + timer_play_pause.setOnClickListener { + when (val state = timer.state) { + is TimerState.Idle -> EventBus.getDefault().post(TimerEvent.Start(timer.id!!, timer.seconds.secondsToMillis)) + is TimerState.Paused -> EventBus.getDefault().post(TimerEvent.Start(timer.id!!, state.tick)) + is TimerState.Running -> EventBus.getDefault().post(TimerEvent.Pause(timer.id!!, state.tick)) + is TimerState.Finished -> EventBus.getDefault().post(TimerEvent.Start(timer.id!!, timer.seconds.secondsToMillis)) + } + } + + val state = timer.state val resetPossible = state is TimerState.Running || state is TimerState.Paused || state is TimerState.Finished - itemView.timer_reset.beInvisibleIf(!resetPossible) - itemView.timer_delete.beInvisibleIf(!(!resetPossible && itemCount > 1)) + timer_reset.beInvisibleIf(!resetPossible) + timer_delete.beInvisibleIf(!(!resetPossible && itemCount > 1)) val drawableId = if (state is TimerState.Running) R.drawable.ic_pause_vector else R.drawable.ic_play_vector val iconColor = if (adjustedPrimaryColor == Color.WHITE) Color.BLACK else Color.WHITE - itemView.timer_play_pause.setImageDrawable(activity.resources.getColoredDrawableWithColor(drawableId, iconColor)) + timer_play_pause.setImageDrawable(simpleActivity.resources.getColoredDrawableWithColor(drawableId, iconColor)) } } private fun changeDuration(timer: Timer) { - MyTimePickerDialogDialog(activity, timer.seconds) { seconds -> + MyTimePickerDialogDialog(simpleActivity, timer.seconds) { seconds -> val timerSeconds = if (seconds <= 0) 10 else seconds updateTimer(timer.copy(seconds = timerSeconds)) } } private fun updateTimer(timer: Timer, refresh: Boolean = true) { - activity.timerHelper.insertOrUpdateTimer(timer) { + simpleActivity.timerHelper.insertOrUpdateTimer(timer) { if (refresh) { onRefresh.invoke() } @@ -139,7 +172,7 @@ class TimerAdapter( private fun stopTimer(timer: Timer) { EventBus.getDefault().post(TimerEvent.Reset(timer.id!!, timer.seconds.secondsToMillis)) - activity.hideTimerNotification() + simpleActivity.hideTimerNotification() } } diff --git a/app/src/main/kotlin/com/simplemobiletools/clock/adapters/ViewPagerAdapter.kt b/app/src/main/kotlin/com/simplemobiletools/clock/adapters/ViewPagerAdapter.kt index bc2d9a9..6f795b9 100644 --- a/app/src/main/kotlin/com/simplemobiletools/clock/adapters/ViewPagerAdapter.kt +++ b/app/src/main/kotlin/com/simplemobiletools/clock/adapters/ViewPagerAdapter.kt @@ -54,7 +54,7 @@ class ViewPagerAdapter(fm: FragmentManager) : FragmentStatePagerAdapter(fm) { (fragments[TAB_TIMER] as? TimerFragment)?.updateAlarmSound(alarmSound) } - fun updateTimerPosition(timerId: Long) { + fun updateTimerPosition(timerId: Int) { (fragments[TAB_TIMER] as? TimerFragment)?.updatePosition(timerId) } } diff --git a/app/src/main/kotlin/com/simplemobiletools/clock/extensions/Context.kt b/app/src/main/kotlin/com/simplemobiletools/clock/extensions/Context.kt index cfe71ee..6bf1062 100644 --- a/app/src/main/kotlin/com/simplemobiletools/clock/extensions/Context.kt +++ b/app/src/main/kotlin/com/simplemobiletools/clock/extensions/Context.kt @@ -144,7 +144,7 @@ fun Context.getOpenAlarmTabIntent(): PendingIntent { return PendingIntent.getActivity(this, OPEN_ALARMS_TAB_INTENT_ID, intent, PendingIntent.FLAG_UPDATE_CURRENT) } -fun Context.getOpenTimerTabIntent(timerId: Long): PendingIntent { +fun Context.getOpenTimerTabIntent(timerId: Int): PendingIntent { val intent = getLaunchIntent() ?: Intent(this, SplashActivity::class.java) intent.putExtra(OPEN_TAB, TAB_TIMER) intent.putExtra(TIMER_ID, timerId) diff --git a/app/src/main/kotlin/com/simplemobiletools/clock/fragments/TimerFragment.kt b/app/src/main/kotlin/com/simplemobiletools/clock/fragments/TimerFragment.kt index 72c1aea..d524928 100644 --- a/app/src/main/kotlin/com/simplemobiletools/clock/fragments/TimerFragment.kt +++ b/app/src/main/kotlin/com/simplemobiletools/clock/fragments/TimerFragment.kt @@ -44,7 +44,7 @@ class TimerFragment : Fragment() { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { view = (inflater.inflate(R.layout.fragment_timer, container, false) as ViewGroup).apply { - timerAdapter = TimerAdapter(requireActivity() as SimpleActivity, ::refreshTimers, ::openEditTimer) + timerAdapter = TimerAdapter(requireActivity() as SimpleActivity, timers_list, ::refreshTimers, ::openEditTimer) storeStateVariables() @@ -105,7 +105,7 @@ class TimerFragment : Fragment() { currentEditAlarmDialog?.updateAlarmSound(alarmSound) } - fun updatePosition(timerId: Long) { + fun updatePosition(timerId: Int) { activity?.timerHelper?.getTimers { timers -> val position = timers.indexOfFirst { it.id == timerId } if (position != INVALID_POSITION) { diff --git a/app/src/main/kotlin/com/simplemobiletools/clock/helpers/Constants.kt b/app/src/main/kotlin/com/simplemobiletools/clock/helpers/Constants.kt index c99fe5a..5e304fe 100644 --- a/app/src/main/kotlin/com/simplemobiletools/clock/helpers/Constants.kt +++ b/app/src/main/kotlin/com/simplemobiletools/clock/helpers/Constants.kt @@ -47,7 +47,7 @@ const val TAB_ALARM = 1 const val TAB_STOPWATCH = 2 const val TAB_TIMER = 3 const val TIMER_ID = "timer_id" -const val INVALID_TIMER_ID = -1L +const val INVALID_TIMER_ID = -1 // stopwatch sorting const val SORT_BY_LAP = 1 diff --git a/app/src/main/kotlin/com/simplemobiletools/clock/helpers/TimerHelper.kt b/app/src/main/kotlin/com/simplemobiletools/clock/helpers/TimerHelper.kt index ba25598..e51bede 100644 --- a/app/src/main/kotlin/com/simplemobiletools/clock/helpers/TimerHelper.kt +++ b/app/src/main/kotlin/com/simplemobiletools/clock/helpers/TimerHelper.kt @@ -14,7 +14,7 @@ class TimerHelper(val context: Context) { } } - fun getTimer(timerId: Long, callback: (timer: Timer) -> Unit) { + fun getTimer(timerId: Int, callback: (timer: Timer) -> Unit) { ensureBackgroundThread { callback.invoke(timerDao.getTimer(timerId)) } @@ -27,10 +27,17 @@ class TimerHelper(val context: Context) { } } - fun deleteTimer(id: Long, callback: () -> Unit = {}) { + fun deleteTimer(id: Int, callback: () -> Unit = {}) { ensureBackgroundThread { timerDao.deleteTimer(id) callback.invoke() } } + + fun deleteTimers(timers: List, callback: () -> Unit = {}) { + ensureBackgroundThread { + timerDao.deleteTimers(timers) + callback.invoke() + } + } } diff --git a/app/src/main/kotlin/com/simplemobiletools/clock/interfaces/TimerDao.kt b/app/src/main/kotlin/com/simplemobiletools/clock/interfaces/TimerDao.kt index fd64f8d..834a641 100644 --- a/app/src/main/kotlin/com/simplemobiletools/clock/interfaces/TimerDao.kt +++ b/app/src/main/kotlin/com/simplemobiletools/clock/interfaces/TimerDao.kt @@ -1,9 +1,6 @@ package com.simplemobiletools.clock.interfaces -import androidx.room.Dao -import androidx.room.Insert -import androidx.room.OnConflictStrategy -import androidx.room.Query +import androidx.room.* import com.simplemobiletools.clock.models.Timer @Dao @@ -13,11 +10,14 @@ interface TimerDao { fun getTimers(): List @Query("SELECT * FROM timers WHERE id=:id") - fun getTimer(id: Long): Timer + fun getTimer(id: Int): Timer @Insert(onConflict = OnConflictStrategy.REPLACE) fun insertOrUpdateTimer(timer: Timer): Long @Query("DELETE FROM timers WHERE id=:id") - fun deleteTimer(id: Long) + fun deleteTimer(id: Int) + + @Delete + fun deleteTimers(list: List) } diff --git a/app/src/main/kotlin/com/simplemobiletools/clock/models/Timer.kt b/app/src/main/kotlin/com/simplemobiletools/clock/models/Timer.kt index 1706264..db66392 100644 --- a/app/src/main/kotlin/com/simplemobiletools/clock/models/Timer.kt +++ b/app/src/main/kotlin/com/simplemobiletools/clock/models/Timer.kt @@ -5,7 +5,7 @@ import androidx.room.PrimaryKey @Entity(tableName = "timers") data class Timer( - @PrimaryKey(autoGenerate = true) var id: Long?, + @PrimaryKey(autoGenerate = true) var id: Int?, var seconds: Int, val state: TimerState, var vibrate: Boolean, diff --git a/app/src/main/kotlin/com/simplemobiletools/clock/models/TimerEvent.kt b/app/src/main/kotlin/com/simplemobiletools/clock/models/TimerEvent.kt index c5ae5ec..938e3cd 100644 --- a/app/src/main/kotlin/com/simplemobiletools/clock/models/TimerEvent.kt +++ b/app/src/main/kotlin/com/simplemobiletools/clock/models/TimerEvent.kt @@ -1,9 +1,9 @@ package com.simplemobiletools.clock.models -sealed class TimerEvent(open val timerId: Long) { - data class Reset(override val timerId: Long, val duration: Long) : TimerEvent(timerId) - data class Start(override val timerId: Long, val duration: Long) : TimerEvent(timerId) - data class Pause(override val timerId: Long, val duration: Long) : TimerEvent(timerId) - data class Finish(override val timerId: Long, val duration: Long) : TimerEvent(timerId) - data class Refresh(override val timerId: Long) : TimerEvent(timerId) +sealed class TimerEvent(open val timerId: Int) { + data class Reset(override val timerId: Int, val duration: Long) : TimerEvent(timerId) + data class Start(override val timerId: Int, val duration: Long) : TimerEvent(timerId) + data class Pause(override val timerId: Int, val duration: Long) : TimerEvent(timerId) + data class Finish(override val timerId: Int, val duration: Long) : TimerEvent(timerId) + data class Refresh(override val timerId: Int) : TimerEvent(timerId) } diff --git a/app/src/main/kotlin/com/simplemobiletools/clock/services/TimerService.kt b/app/src/main/kotlin/com/simplemobiletools/clock/services/TimerService.kt index 4099600..858d06f 100644 --- a/app/src/main/kotlin/com/simplemobiletools/clock/services/TimerService.kt +++ b/app/src/main/kotlin/com/simplemobiletools/clock/services/TimerService.kt @@ -82,7 +82,7 @@ class TimerService : Service() { } @TargetApi(Build.VERSION_CODES.O) - private fun notification(title: String, contentText: String, firstRunningTimerId: Long): Notification { + private fun notification(title: String, contentText: String, firstRunningTimerId: Int): Notification { val channelId = "simple_alarm_timer" val label = getString(R.string.timer) val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager diff --git a/app/src/main/res/layout/item_timer.xml b/app/src/main/res/layout/item_timer.xml index 96ea9bd..f8e80a1 100644 --- a/app/src/main/res/layout/item_timer.xml +++ b/app/src/main/res/layout/item_timer.xml @@ -2,6 +2,7 @@