From 174896d87b0b4b31e476ab5bbbbe05b89b839459 Mon Sep 17 00:00:00 2001 From: razeeman Date: Sat, 28 Oct 2023 14:31:36 +0300 Subject: [PATCH] add goal check on widget --- .../GetCurrentRecordsDurationInteractor.kt | 12 +++++++- .../core/mapper/RecordTypeViewDataMapper.kt | 12 ++++++-- .../feature_views/RecordTypeView.kt | 5 ++++ .../feature_views/extension/ViewExtensions.kt | 6 ++++ .../res/layout/record_type_view_layout.xml | 10 +++++-- .../single/WidgetSingleProvider.kt | 30 +++++++++++++++++++ 6 files changed, 69 insertions(+), 6 deletions(-) diff --git a/core/src/main/java/com/example/util/simpletimetracker/core/interactor/GetCurrentRecordsDurationInteractor.kt b/core/src/main/java/com/example/util/simpletimetracker/core/interactor/GetCurrentRecordsDurationInteractor.kt index 000dee992..dee469bf8 100644 --- a/core/src/main/java/com/example/util/simpletimetracker/core/interactor/GetCurrentRecordsDurationInteractor.kt +++ b/core/src/main/java/com/example/util/simpletimetracker/core/interactor/GetCurrentRecordsDurationInteractor.kt @@ -19,6 +19,13 @@ class GetCurrentRecordsDurationInteractor @Inject constructor( private val timeMapper: TimeMapper, ) { + suspend fun getDailyCurrent( + typeId: Long, + runningRecord: RunningRecord?, + ): Result { + return getRangeCurrent(typeId, runningRecord, getRange(RangeLength.Day)) + } + suspend fun getDailyCurrent(runningRecord: RunningRecord): Result { return getRangeCurrent(runningRecord.id, runningRecord, getRange(RangeLength.Day)) } @@ -57,7 +64,10 @@ class GetCurrentRecordsDurationInteractor @Inject constructor( typeId = typeId, runningRecord = runningRecord, range = range, - rangeRecords = recordInteractor.getFromRange(range), + rangeRecords = recordInteractor.getFromRangeByType( + typeIds = listOf(typeId), + range = range, + ), ) } diff --git a/core/src/main/java/com/example/util/simpletimetracker/core/mapper/RecordTypeViewDataMapper.kt b/core/src/main/java/com/example/util/simpletimetracker/core/mapper/RecordTypeViewDataMapper.kt index bd46472a1..0938fa7f2 100644 --- a/core/src/main/java/com/example/util/simpletimetracker/core/mapper/RecordTypeViewDataMapper.kt +++ b/core/src/main/java/com/example/util/simpletimetracker/core/mapper/RecordTypeViewDataMapper.kt @@ -132,13 +132,21 @@ class RecordTypeViewDataMapper @Inject constructor( goals: Map>, allDailyCurrents: Map, ): Boolean? { - val goal = goals[type.id].orEmpty().getDaily() + return mapGoalCheckmark( + goal = goals[type.id].orEmpty().getDaily(), + dailyCurrent = allDailyCurrents[type.id], + ) + } + + fun mapGoalCheckmark( + goal: RecordTypeGoal?, + dailyCurrent: GetCurrentRecordsDurationInteractor.Result?, + ): Boolean? { val goalValue = when (goal?.type) { is RecordTypeGoal.Type.Duration -> goal.value * 1000 is RecordTypeGoal.Type.Count -> goal.value else -> 0 } - val dailyCurrent = allDailyCurrents[type.id] val current = when (goal?.type) { is RecordTypeGoal.Type.Duration -> dailyCurrent?.duration.orZero() is RecordTypeGoal.Type.Count -> dailyCurrent?.count.orZero() diff --git a/features/feature_views/src/main/java/com/example/util/simpletimetracker/feature_views/RecordTypeView.kt b/features/feature_views/src/main/java/com/example/util/simpletimetracker/feature_views/RecordTypeView.kt index e00899458..15dad6e21 100644 --- a/features/feature_views/src/main/java/com/example/util/simpletimetracker/feature_views/RecordTypeView.kt +++ b/features/feature_views/src/main/java/com/example/util/simpletimetracker/feature_views/RecordTypeView.kt @@ -6,6 +6,7 @@ import android.util.AttributeSet import android.view.Gravity import android.view.LayoutInflater import android.widget.RelativeLayout +import androidx.appcompat.widget.AppCompatImageView import androidx.cardview.widget.CardView import androidx.constraintlayout.widget.ConstraintSet import androidx.core.view.isVisible @@ -125,6 +126,10 @@ class RecordTypeView @JvmOverloads constructor( return binding.containerRecordTypeItem } + fun getCheckmarkOutline(): AppCompatImageView { + return binding.ivRecordTypeItemCheckOutline + } + private fun changeConstraints(isRow: Boolean) = with(binding.container) { if (isRow) { val setRow = ConstraintSet() diff --git a/features/feature_views/src/main/java/com/example/util/simpletimetracker/feature_views/extension/ViewExtensions.kt b/features/feature_views/src/main/java/com/example/util/simpletimetracker/feature_views/extension/ViewExtensions.kt index 58a8ade4b..4a75f79de 100644 --- a/features/feature_views/src/main/java/com/example/util/simpletimetracker/feature_views/extension/ViewExtensions.kt +++ b/features/feature_views/src/main/java/com/example/util/simpletimetracker/feature_views/extension/ViewExtensions.kt @@ -107,6 +107,12 @@ fun SeekBar.onProgressChanged(func: (Int) -> Unit) { }) } +fun View.setAllMargins( + all: Int? +) { + setMargins(all, all, all, all) +} + fun View.setMargins( top: Int? = null, bottom: Int? = null, diff --git a/features/feature_views/src/main/res/layout/record_type_view_layout.xml b/features/feature_views/src/main/res/layout/record_type_view_layout.xml index 6198ed697..981666b0e 100644 --- a/features/feature_views/src/main/res/layout/record_type_view_layout.xml +++ b/features/feature_views/src/main/res/layout/record_type_view_layout.xml @@ -23,9 +23,10 @@ android:id="@+id/ivRecordTypeItemCheckOutline" android:layout_width="20dp" android:layout_height="20dp" + android:layout_alignParentTop="true" android:layout_alignParentEnd="true" - android:tint="?colorSecondary" android:elevation="@dimen/record_type_card_elevation" + android:tint="?colorSecondary" android:visibility="gone" app:srcCompat="@drawable/record_type_check_unmarked" tools:visibility="visible" /> @@ -34,9 +35,12 @@ android:id="@+id/ivRecordTypeItemCheck" android:layout_width="20dp" android:layout_height="20dp" - android:layout_alignParentEnd="true" - android:tint="@color/white" + android:layout_alignStart="@id/ivRecordTypeItemCheckOutline" + android:layout_alignTop="@id/ivRecordTypeItemCheckOutline" + android:layout_alignEnd="@id/ivRecordTypeItemCheckOutline" + android:layout_alignBottom="@id/ivRecordTypeItemCheckOutline" android:elevation="@dimen/record_type_card_elevation" + android:tint="@color/white" android:visibility="gone" app:srcCompat="@drawable/record_type_check_mark" tools:visibility="visible" /> diff --git a/features/feature_widget/src/main/java/com/example/util/simpletimetracker/feature_widget/single/WidgetSingleProvider.kt b/features/feature_widget/src/main/java/com/example/util/simpletimetracker/feature_widget/single/WidgetSingleProvider.kt index b35c68bc3..0350b355d 100644 --- a/features/feature_widget/src/main/java/com/example/util/simpletimetracker/feature_widget/single/WidgetSingleProvider.kt +++ b/features/feature_widget/src/main/java/com/example/util/simpletimetracker/feature_widget/single/WidgetSingleProvider.kt @@ -12,6 +12,7 @@ import android.view.LayoutInflater import android.view.View import android.widget.FrameLayout import android.widget.RemoteViews +import com.example.util.simpletimetracker.core.interactor.GetCurrentRecordsDurationInteractor import com.example.util.simpletimetracker.core.interactor.RecordRepeatInteractor import com.example.util.simpletimetracker.core.mapper.ColorMapper import com.example.util.simpletimetracker.core.mapper.IconMapper @@ -19,11 +20,14 @@ import com.example.util.simpletimetracker.core.mapper.RecordTypeViewDataMapper import com.example.util.simpletimetracker.core.repo.ResourceRepo import com.example.util.simpletimetracker.core.utils.PendingIntents import com.example.util.simpletimetracker.domain.REPEAT_BUTTON_ITEM_ID +import com.example.util.simpletimetracker.domain.extension.getDaily +import com.example.util.simpletimetracker.domain.extension.orFalse import com.example.util.simpletimetracker.domain.extension.orZero import com.example.util.simpletimetracker.domain.interactor.AddRunningRecordMediator import com.example.util.simpletimetracker.domain.interactor.PrefsInteractor import com.example.util.simpletimetracker.domain.interactor.RecordInteractor import com.example.util.simpletimetracker.domain.interactor.RecordTagInteractor +import com.example.util.simpletimetracker.domain.interactor.RecordTypeGoalInteractor import com.example.util.simpletimetracker.domain.interactor.RecordTypeInteractor import com.example.util.simpletimetracker.domain.interactor.RemoveRunningRecordMediator import com.example.util.simpletimetracker.domain.interactor.RunningRecordInteractor @@ -32,6 +36,7 @@ import com.example.util.simpletimetracker.domain.model.RunningRecord import com.example.util.simpletimetracker.feature_views.RecordTypeView import com.example.util.simpletimetracker.feature_views.extension.getBitmapFromView import com.example.util.simpletimetracker.feature_views.extension.measureExactly +import com.example.util.simpletimetracker.feature_views.extension.setAllMargins import com.example.util.simpletimetracker.feature_views.viewData.RecordTypeIcon import com.example.util.simpletimetracker.feature_widget.R import com.example.util.simpletimetracker.navigation.params.screen.RecordTagSelectionParams @@ -57,6 +62,9 @@ class WidgetSingleProvider : AppWidgetProvider() { @Inject lateinit var recordTypeInteractor: RecordTypeInteractor + @Inject + lateinit var recordTypeGoalInteractor: RecordTypeGoalInteractor + @Inject lateinit var recordInteractor: RecordInteractor @@ -84,6 +92,9 @@ class WidgetSingleProvider : AppWidgetProvider() { @Inject lateinit var recordRepeatInteractor: RecordRepeatInteractor + @Inject + lateinit var getCurrentRecordsDurationInteractor: GetCurrentRecordsDurationInteractor + override fun onReceive(context: Context?, intent: Intent?) { super.onReceive(context, intent) if (intent?.action == ON_CLICK_ACTION) { @@ -133,10 +144,24 @@ class WidgetSingleProvider : AppWidgetProvider() { recordTypeName = viewData.name, recordTypeColor = viewData.color, isRunning = false, + isChecked = false, ) } else { val recordType = recordTypeInteractor.get(recordTypeId) ?.takeUnless { it.hidden } + val goal = recordTypeGoalInteractor.getByType(recordTypeId).getDaily() + val dailyCurrent = getCurrentRecordsDurationInteractor.getDailyCurrent( + typeId = recordTypeId, + runningRecord = runningRecord, + ) + val isChecked = if (recordType != null) { + recordTypeViewDataMapper.mapGoalCheckmark( + goal = goal, + dailyCurrent = dailyCurrent, + ) + } else { + null + } view = prepareView( context = context, recordTypeIcon = recordType?.icon @@ -145,6 +170,7 @@ class WidgetSingleProvider : AppWidgetProvider() { recordTypeColor = recordType?.color ?.let { colorMapper.mapToColorInt(it, isDarkTheme) }, isRunning = runningRecord != null && recordType != null, + isChecked = isChecked, ) } } @@ -173,6 +199,7 @@ class WidgetSingleProvider : AppWidgetProvider() { recordTypeName: String?, recordTypeColor: Int?, isRunning: Boolean, + isChecked: Boolean?, ): View { val icon = recordTypeIcon ?: RecordTypeIcon.Image(R.drawable.unknown) @@ -198,9 +225,12 @@ class WidgetSingleProvider : AppWidgetProvider() { getContainer().radius = resources.getDimensionPixelOffset(R.dimen.widget_universal_corner_radius).toFloat() getContainer().cardElevation = 0f getContainer().useCompatPadding = false + getCheckmarkOutline().setAllMargins(4) itemIcon = icon itemName = name itemColor = color + itemWithCheck = isChecked != null + itemIsChecked = isChecked.orFalse() alpha = viewAlpha }.let(container::addView)