A fork of Simple Time Tracker with WearOS support. (Now integrated upstream)
0

Configure Feed

Select the types of activity you want to include in your feed.

rename widget to widget single

razeeman (Apr 29, 2023, 3:25 PM +0300) e6bc6a9c 0694d5d6

+516 -519
+4 -4
features/feature_widget/src/main/AndroidManifest.xml
··· 4 4 <application android:theme="@style/AppTheme"> 5 5 6 6 <activity 7 - android:name=".configure.view.WidgetConfigureActivity" 7 + android:name=".single.settings.WidgetSingleSettingsActivity" 8 8 android:exported="true"> 9 9 <intent-filter> 10 10 <action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" /> ··· 26 26 android:noHistory="true" /> 27 27 28 28 <activity 29 - android:name=".widget.WidgetTagSelectionActivity" 29 + android:name=".single.WidgetSingleTagSelectionActivity" 30 30 android:documentLaunchMode="intoExisting" 31 31 android:excludeFromRecents="true" 32 32 android:noHistory="true" /> 33 33 34 34 <receiver 35 - android:name=".widget.WidgetProvider" 35 + android:name=".single.WidgetSingleProvider" 36 36 android:exported="false" 37 37 android:label="@string/widget_name"> 38 38 <intent-filter> ··· 40 40 </intent-filter> 41 41 <meta-data 42 42 android:name="android.appwidget.provider" 43 - android:resource="@xml/widget_info" /> 43 + android:resource="@xml/widget_single_info" /> 44 44 </receiver> 45 45 46 46 <receiver
-16
features/feature_widget/src/main/res/layout/widget_configure_activity.xml
··· 1 - <?xml version="1.0" encoding="utf-8"?> 2 - <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 - xmlns:tools="http://schemas.android.com/tools" 4 - android:layout_width="match_parent" 5 - android:layout_height="match_parent" 6 - android:orientation="vertical" 7 - android:paddingTop="12dp" 8 - android:paddingBottom="12dp"> 9 - 10 - <androidx.recyclerview.widget.RecyclerView 11 - android:id="@+id/rvWidgetConfigureRecordType" 12 - android:layout_width="match_parent" 13 - android:layout_height="match_parent" 14 - tools:listitem="@layout/item_widget_record_type_layout" /> 15 - 16 - </LinearLayout>
+16
features/feature_widget/src/main/res/layout/widget_single_settings_configure_activity.xml
··· 1 + <?xml version="1.0" encoding="utf-8"?> 2 + <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 + xmlns:tools="http://schemas.android.com/tools" 4 + android:layout_width="match_parent" 5 + android:layout_height="match_parent" 6 + android:orientation="vertical" 7 + android:paddingTop="12dp" 8 + android:paddingBottom="12dp"> 9 + 10 + <androidx.recyclerview.widget.RecyclerView 11 + android:id="@+id/rvWidgetSingleSettingsRecordType" 12 + android:layout_width="match_parent" 13 + android:layout_height="match_parent" 14 + tools:listitem="@layout/item_widget_record_type_layout" /> 15 + 16 + </LinearLayout>
-13
features/feature_widget/src/main/res/xml/widget_info.xml
··· 1 - <?xml version="1.0" encoding="utf-8"?> 2 - <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" 3 - xmlns:tools="http://schemas.android.com/tools" 4 - android:configure="com.example.util.simpletimetracker.feature_widget.configure.view.WidgetConfigureActivity" 5 - android:initialLayout="@layout/widget_layout" 6 - android:minWidth="20dp" 7 - android:minHeight="20dp" 8 - android:previewImage="@drawable/preview_widget_single" 9 - android:resizeMode="none" 10 - android:updatePeriodMillis="1800000" 11 - android:widgetCategory="home_screen" 12 - android:widgetFeatures="reconfigurable" 13 - tools:targetApi="p" />
+13
features/feature_widget/src/main/res/xml/widget_single_info.xml
··· 1 + <?xml version="1.0" encoding="utf-8"?> 2 + <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" 3 + xmlns:tools="http://schemas.android.com/tools" 4 + android:configure="com.example.util.simpletimetracker.feature_widget.single.settings.WidgetSingleSettingsActivity" 5 + android:initialLayout="@layout/widget_layout" 6 + android:minWidth="20dp" 7 + android:minHeight="20dp" 8 + android:previewImage="@drawable/preview_widget_single" 9 + android:resizeMode="none" 10 + android:updatePeriodMillis="1800000" 11 + android:widgetCategory="home_screen" 12 + android:widgetFeatures="reconfigurable" 13 + tools:targetApi="p" />
+3 -3
app/src/androidTest/java/com/example/util/simpletimetracker/Widget.kt
··· 5 5 import androidx.test.espresso.matcher.ViewMatchers.withId 6 6 import androidx.test.espresso.matcher.ViewMatchers.withText 7 7 import androidx.test.ext.junit.runners.AndroidJUnit4 8 - import com.example.util.simpletimetracker.feature_widget.configure.view.WidgetConfigureActivity 8 + import com.example.util.simpletimetracker.feature_widget.single.settings.WidgetSingleSettingsActivity 9 9 import com.example.util.simpletimetracker.utils.BaseUiTest 10 10 import com.example.util.simpletimetracker.utils.Widget 11 11 import com.example.util.simpletimetracker.utils.checkViewDoesNotExist ··· 21 21 @RunWith(AndroidJUnit4::class) 22 22 class Widget : BaseUiTest() { 23 23 24 - private lateinit var scenarioRule: ActivityScenario<WidgetConfigureActivity> 24 + private lateinit var scenarioRule: ActivityScenario<WidgetSingleSettingsActivity> 25 25 26 26 override fun after() { 27 27 super.after() ··· 38 38 testUtils.addActivity(name = name1, color = firstColor) 39 39 testUtils.addActivity(name = name2, color = lastColor) 40 40 testUtils.addActivity(name = name3, archived = true) 41 - scenarioRule = ActivityScenario.launch(WidgetConfigureActivity::class.java) 41 + scenarioRule = ActivityScenario.launch(WidgetSingleSettingsActivity::class.java) 42 42 43 43 // Check data 44 44 checkType(firstColor, name1)
+3 -3
features/feature_widget/src/main/java/com/example/util/simpletimetracker/feature_widget/interactor/WidgetManager.kt
··· 7 7 import com.example.util.simpletimetracker.domain.model.WidgetType 8 8 import com.example.util.simpletimetracker.feature_widget.statistics.WidgetStatisticsChartProvider 9 9 import com.example.util.simpletimetracker.feature_widget.universal.WidgetUniversalProvider 10 - import com.example.util.simpletimetracker.feature_widget.widget.WidgetProvider 10 + import com.example.util.simpletimetracker.feature_widget.single.WidgetSingleProvider 11 11 import dagger.hilt.android.qualifiers.ApplicationContext 12 12 import javax.inject.Inject 13 13 import javax.inject.Singleton ··· 18 18 ) { 19 19 20 20 fun updateWidget(widgetId: Int) { 21 - val intent = Intent(context, WidgetProvider::class.java) 21 + val intent = Intent(context, WidgetSingleProvider::class.java) 22 22 intent.action = AppWidgetManager.ACTION_APPWIDGET_UPDATE 23 23 intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, intArrayOf(widgetId)) 24 24 context.sendBroadcast(intent) ··· 38 38 39 39 val providers = widgetsToUpdate.map { type -> 40 40 when (type) { 41 - WidgetType.RECORD_TYPE -> WidgetProvider::class.java 41 + WidgetType.RECORD_TYPE -> WidgetSingleProvider::class.java 42 42 WidgetType.UNIVERSAL -> WidgetUniversalProvider::class.java 43 43 WidgetType.STATISTICS_CHART -> WidgetStatisticsChartProvider::class.java 44 44 }
+251
features/feature_widget/src/main/java/com/example/util/simpletimetracker/feature_widget/single/WidgetSingleProvider.kt
··· 1 + package com.example.util.simpletimetracker.feature_widget.single 2 + 3 + import android.app.PendingIntent 4 + import android.appwidget.AppWidgetManager 5 + import android.appwidget.AppWidgetProvider 6 + import android.content.Context 7 + import android.content.Intent 8 + import android.graphics.Color 9 + import android.os.SystemClock 10 + import android.view.ContextThemeWrapper 11 + import android.view.LayoutInflater 12 + import android.view.View 13 + import android.widget.FrameLayout 14 + import android.widget.RemoteViews 15 + import com.example.util.simpletimetracker.core.mapper.ColorMapper 16 + import com.example.util.simpletimetracker.core.mapper.IconMapper 17 + import com.example.util.simpletimetracker.core.mapper.RecordTypeViewDataMapper 18 + import com.example.util.simpletimetracker.core.repo.ResourceRepo 19 + import com.example.util.simpletimetracker.core.utils.PendingIntents 20 + import com.example.util.simpletimetracker.domain.extension.orZero 21 + import com.example.util.simpletimetracker.domain.interactor.AddRunningRecordMediator 22 + import com.example.util.simpletimetracker.domain.interactor.PrefsInteractor 23 + import com.example.util.simpletimetracker.domain.interactor.RecordInteractor 24 + import com.example.util.simpletimetracker.domain.interactor.RecordTagInteractor 25 + import com.example.util.simpletimetracker.domain.interactor.RecordTypeInteractor 26 + import com.example.util.simpletimetracker.domain.interactor.RemoveRunningRecordMediator 27 + import com.example.util.simpletimetracker.domain.interactor.RunningRecordInteractor 28 + import com.example.util.simpletimetracker.domain.interactor.WidgetInteractor 29 + import com.example.util.simpletimetracker.domain.model.RecordType 30 + import com.example.util.simpletimetracker.domain.model.RunningRecord 31 + import com.example.util.simpletimetracker.feature_views.RecordTypeView 32 + import com.example.util.simpletimetracker.feature_views.extension.getBitmapFromView 33 + import com.example.util.simpletimetracker.feature_views.extension.measureExactly 34 + import com.example.util.simpletimetracker.feature_views.viewData.RecordTypeIcon 35 + import com.example.util.simpletimetracker.feature_widget.R 36 + import com.example.util.simpletimetracker.navigation.params.screen.RecordTagSelectionParams 37 + import dagger.hilt.android.AndroidEntryPoint 38 + import kotlinx.coroutines.CoroutineScope 39 + import kotlinx.coroutines.Dispatchers 40 + import kotlinx.coroutines.launch 41 + import kotlinx.coroutines.runBlocking 42 + import javax.inject.Inject 43 + 44 + @AndroidEntryPoint 45 + class WidgetSingleProvider : AppWidgetProvider() { 46 + 47 + @Inject 48 + lateinit var addRunningRecordMediator: AddRunningRecordMediator 49 + 50 + @Inject 51 + lateinit var removeRunningRecordMediator: RemoveRunningRecordMediator 52 + 53 + @Inject 54 + lateinit var runningRecordInteractor: RunningRecordInteractor 55 + 56 + @Inject 57 + lateinit var recordTypeInteractor: RecordTypeInteractor 58 + 59 + @Inject 60 + lateinit var recordInteractor: RecordInteractor 61 + 62 + @Inject 63 + lateinit var recordTagInteractor: RecordTagInteractor 64 + 65 + @Inject 66 + lateinit var widgetInteractor: WidgetInteractor 67 + 68 + @Inject 69 + lateinit var recordTypeViewDataMapper: RecordTypeViewDataMapper 70 + 71 + @Inject 72 + lateinit var colorMapper: ColorMapper 73 + 74 + @Inject 75 + lateinit var iconMapper: IconMapper 76 + 77 + @Inject 78 + lateinit var resourceRepo: ResourceRepo 79 + 80 + @Inject 81 + lateinit var prefsInteractor: PrefsInteractor 82 + 83 + override fun onReceive(context: Context?, intent: Intent?) { 84 + super.onReceive(context, intent) 85 + if (intent?.action == ON_CLICK_ACTION) { 86 + onClick(context, intent.getIntExtra(ARGS_WIDGET_ID, 0)) 87 + } 88 + } 89 + 90 + override fun onUpdate( 91 + context: Context?, 92 + appWidgetManager: AppWidgetManager?, 93 + appWidgetIds: IntArray? 94 + ) { 95 + appWidgetIds?.forEach { widgetId -> 96 + updateAppWidget(context, appWidgetManager, widgetId) 97 + } 98 + } 99 + 100 + override fun onDeleted(context: Context?, appWidgetIds: IntArray?) { 101 + CoroutineScope(Dispatchers.Main).launch { 102 + appWidgetIds?.forEach { prefsInteractor.removeWidget(it) } 103 + } 104 + } 105 + 106 + private fun updateAppWidget( 107 + context: Context?, 108 + appWidgetManager: AppWidgetManager?, 109 + appWidgetId: Int 110 + ) { 111 + if (context == null || appWidgetManager == null) return 112 + 113 + var recordType: RecordType? 114 + var runningRecord: RunningRecord? 115 + var isDarkTheme: Boolean 116 + runBlocking { 117 + val recordTypeId = prefsInteractor.getWidget(appWidgetId) 118 + recordType = recordTypeInteractor.get(recordTypeId)?.takeUnless { it.hidden } 119 + runningRecord = runningRecordInteractor.get(recordTypeId) 120 + isDarkTheme = prefsInteractor.getDarkMode() 121 + } 122 + 123 + val view = prepareView(context, recordType, runningRecord, isDarkTheme) 124 + measureView(context, view) 125 + val bitmap = view.getBitmapFromView() 126 + 127 + val views = RemoteViews(context.packageName, R.layout.widget_layout) 128 + if (runningRecord != null) { 129 + val timeStarted = runningRecord?.timeStarted.orZero() 130 + val base = SystemClock.elapsedRealtime() - (System.currentTimeMillis() - timeStarted) 131 + views.setChronometer(R.id.timerWidget, base, null, true) 132 + views.setViewVisibility(R.id.timerWidget, View.VISIBLE) 133 + } else { 134 + views.setViewVisibility(R.id.timerWidget, View.GONE) 135 + } 136 + views.setImageViewBitmap(R.id.ivWidgetBackground, bitmap) 137 + views.setOnClickPendingIntent(R.id.btnWidget, getPendingSelfIntent(context, appWidgetId)) 138 + 139 + appWidgetManager.updateAppWidget(appWidgetId, views) 140 + } 141 + 142 + private fun prepareView( 143 + context: Context, 144 + recordType: RecordType?, 145 + runningRecord: RunningRecord?, 146 + isDarkTheme: Boolean, 147 + ): View { 148 + val icon = recordType?.icon 149 + ?.let(iconMapper::mapIcon) 150 + ?: RecordTypeIcon.Image(R.drawable.unknown) 151 + 152 + val name = recordType?.name 153 + ?: R.string.widget_load_error.let(resourceRepo::getString) 154 + 155 + val color = if (runningRecord != null && recordType != null) { 156 + colorMapper.mapToColorInt(recordType.color, isDarkTheme) 157 + } else { 158 + Color.BLACK 159 + } 160 + 161 + val viewAlpha = if (runningRecord != null && recordType != null) { 162 + ENABLED_ALPHA 163 + } else { 164 + DISABLED_ALPHA 165 + } 166 + 167 + // TODO setting alpha on cardView doesn't work for some reason, wrap in layout before setting 168 + val container = FrameLayout(ContextThemeWrapper(context, R.style.AppTheme)) 169 + RecordTypeView(ContextThemeWrapper(context, R.style.AppTheme)).apply { 170 + cardElevation = 0f 171 + useCompatPadding = false 172 + itemIcon = icon 173 + itemName = name 174 + itemColor = color 175 + alpha = viewAlpha 176 + }.let(container::addView) 177 + 178 + return container 179 + } 180 + 181 + private fun measureView(context: Context, view: View) { 182 + var width = context.resources.getDimensionPixelSize(R.dimen.record_type_card_width) 183 + var height = context.resources.getDimensionPixelSize(R.dimen.record_type_card_height) 184 + val inflater = LayoutInflater.from(context) 185 + 186 + val entireView: View = inflater.inflate(R.layout.widget_layout, null) 187 + entireView.measureExactly(width = width, height = height) 188 + 189 + val imageView = entireView.findViewById<View>(R.id.ivWidgetBackground) 190 + width = imageView.measuredWidth 191 + height = imageView.measuredHeight 192 + view.measureExactly(width = width, height = height) 193 + } 194 + 195 + private fun onClick( 196 + context: Context?, 197 + widgetId: Int 198 + ) { 199 + CoroutineScope(Dispatchers.Main).launch { 200 + val recordTypeId = prefsInteractor.getWidget(widgetId) 201 + 202 + // If recordType removed - update widget and exit 203 + recordTypeInteractor.get(recordTypeId) 204 + ?.takeUnless { it.hidden } 205 + ?: run { 206 + widgetInteractor.updateWidget(widgetId) 207 + return@launch 208 + } 209 + 210 + val runningRecord = runningRecordInteractor.get(recordTypeId) 211 + if (runningRecord != null) { 212 + // Stop running record, add new record 213 + removeRunningRecordMediator.removeWithRecordAdd(runningRecord) 214 + } else { 215 + // Start running record 216 + addRunningRecordMediator.tryStartTimer( 217 + typeId = recordTypeId, 218 + onNeedToShowTagSelection = { showTagSelection(context, recordTypeId) } 219 + ) 220 + } 221 + } 222 + } 223 + 224 + private fun showTagSelection(context: Context?, typeId: Long) { 225 + context ?: return 226 + 227 + WidgetSingleTagSelectionActivity.getStartIntent( 228 + context = context, 229 + data = RecordTagSelectionParams(typeId) 230 + ).let(context::startActivity) 231 + } 232 + 233 + private fun getPendingSelfIntent( 234 + context: Context, 235 + widgetId: Int 236 + ): PendingIntent { 237 + val intent = Intent(context, javaClass) 238 + intent.action = ON_CLICK_ACTION 239 + intent.putExtra(ARGS_WIDGET_ID, widgetId) 240 + return PendingIntent.getBroadcast(context, widgetId, intent, PendingIntents.getFlags()) 241 + } 242 + 243 + companion object { 244 + private const val ON_CLICK_ACTION = 245 + "com.example.util.simpletimetracker.feature_widget.widget.onclick" 246 + private const val ARGS_WIDGET_ID = "widgetId" 247 + 248 + private const val ENABLED_ALPHA = 1f 249 + private const val DISABLED_ALPHA = 0.5f 250 + } 251 + }
+62
features/feature_widget/src/main/java/com/example/util/simpletimetracker/feature_widget/single/WidgetSingleTagSelectionActivity.kt
··· 1 + package com.example.util.simpletimetracker.feature_widget.single 2 + 3 + import android.content.Context 4 + import android.content.Intent 5 + import android.os.Bundle 6 + import androidx.fragment.app.commit 7 + import com.example.util.simpletimetracker.core.base.BaseActivity 8 + import com.example.util.simpletimetracker.core.dialog.OnTagSelectedListener 9 + import com.example.util.simpletimetracker.core.manager.ThemeManager 10 + import com.example.util.simpletimetracker.core.utils.activityArgumentDelegate 11 + import com.example.util.simpletimetracker.feature_widget.R 12 + import com.example.util.simpletimetracker.navigation.ScreenFactory 13 + import com.example.util.simpletimetracker.navigation.params.screen.RecordTagSelectionParams 14 + import dagger.hilt.android.AndroidEntryPoint 15 + import javax.inject.Inject 16 + 17 + @AndroidEntryPoint 18 + class WidgetSingleTagSelectionActivity : 19 + BaseActivity(), 20 + OnTagSelectedListener { 21 + 22 + @Inject 23 + lateinit var themeManager: ThemeManager 24 + 25 + @Inject 26 + lateinit var screenFactory: ScreenFactory 27 + 28 + private val params: RecordTagSelectionParams by activityArgumentDelegate( 29 + key = ARGS_PARAMS, default = RecordTagSelectionParams() 30 + ) 31 + 32 + override fun onCreate(savedInstanceState: Bundle?) { 33 + super.onCreate(savedInstanceState) 34 + 35 + themeManager.setTheme(this) 36 + setContentView(R.layout.widget_tag_selection_activity) 37 + 38 + screenFactory.getFragment(params)?.let { 39 + supportFragmentManager.commit { 40 + replace(R.id.containerWidgetRecordTagSelection, it) 41 + } 42 + } 43 + } 44 + 45 + override fun onTagSelected() { 46 + finish() 47 + } 48 + 49 + companion object { 50 + private const val ARGS_PARAMS = "args_params" 51 + 52 + fun getStartIntent( 53 + context: Context, 54 + data: RecordTagSelectionParams, 55 + ): Intent { 56 + return Intent(context, WidgetSingleTagSelectionActivity::class.java).apply { 57 + flags = Intent.FLAG_ACTIVITY_NEW_TASK 58 + putExtra(ARGS_PARAMS, data) 59 + } 60 + } 61 + } 62 + }
-251
features/feature_widget/src/main/java/com/example/util/simpletimetracker/feature_widget/widget/WidgetProvider.kt
··· 1 - package com.example.util.simpletimetracker.feature_widget.widget 2 - 3 - import android.app.PendingIntent 4 - import android.appwidget.AppWidgetManager 5 - import android.appwidget.AppWidgetProvider 6 - import android.content.Context 7 - import android.content.Intent 8 - import android.graphics.Color 9 - import android.os.SystemClock 10 - import android.view.ContextThemeWrapper 11 - import android.view.LayoutInflater 12 - import android.view.View 13 - import android.widget.FrameLayout 14 - import android.widget.RemoteViews 15 - import com.example.util.simpletimetracker.core.mapper.ColorMapper 16 - import com.example.util.simpletimetracker.core.mapper.IconMapper 17 - import com.example.util.simpletimetracker.core.mapper.RecordTypeViewDataMapper 18 - import com.example.util.simpletimetracker.core.repo.ResourceRepo 19 - import com.example.util.simpletimetracker.core.utils.PendingIntents 20 - import com.example.util.simpletimetracker.domain.extension.orZero 21 - import com.example.util.simpletimetracker.domain.interactor.AddRunningRecordMediator 22 - import com.example.util.simpletimetracker.domain.interactor.PrefsInteractor 23 - import com.example.util.simpletimetracker.domain.interactor.RecordInteractor 24 - import com.example.util.simpletimetracker.domain.interactor.RecordTagInteractor 25 - import com.example.util.simpletimetracker.domain.interactor.RecordTypeInteractor 26 - import com.example.util.simpletimetracker.domain.interactor.RemoveRunningRecordMediator 27 - import com.example.util.simpletimetracker.domain.interactor.RunningRecordInteractor 28 - import com.example.util.simpletimetracker.domain.interactor.WidgetInteractor 29 - import com.example.util.simpletimetracker.domain.model.RecordType 30 - import com.example.util.simpletimetracker.domain.model.RunningRecord 31 - import com.example.util.simpletimetracker.feature_views.RecordTypeView 32 - import com.example.util.simpletimetracker.feature_views.extension.getBitmapFromView 33 - import com.example.util.simpletimetracker.feature_views.extension.measureExactly 34 - import com.example.util.simpletimetracker.feature_views.viewData.RecordTypeIcon 35 - import com.example.util.simpletimetracker.feature_widget.R 36 - import com.example.util.simpletimetracker.navigation.params.screen.RecordTagSelectionParams 37 - import dagger.hilt.android.AndroidEntryPoint 38 - import kotlinx.coroutines.CoroutineScope 39 - import kotlinx.coroutines.Dispatchers 40 - import kotlinx.coroutines.launch 41 - import kotlinx.coroutines.runBlocking 42 - import javax.inject.Inject 43 - 44 - @AndroidEntryPoint 45 - class WidgetProvider : AppWidgetProvider() { 46 - 47 - @Inject 48 - lateinit var addRunningRecordMediator: AddRunningRecordMediator 49 - 50 - @Inject 51 - lateinit var removeRunningRecordMediator: RemoveRunningRecordMediator 52 - 53 - @Inject 54 - lateinit var runningRecordInteractor: RunningRecordInteractor 55 - 56 - @Inject 57 - lateinit var recordTypeInteractor: RecordTypeInteractor 58 - 59 - @Inject 60 - lateinit var recordInteractor: RecordInteractor 61 - 62 - @Inject 63 - lateinit var recordTagInteractor: RecordTagInteractor 64 - 65 - @Inject 66 - lateinit var widgetInteractor: WidgetInteractor 67 - 68 - @Inject 69 - lateinit var recordTypeViewDataMapper: RecordTypeViewDataMapper 70 - 71 - @Inject 72 - lateinit var colorMapper: ColorMapper 73 - 74 - @Inject 75 - lateinit var iconMapper: IconMapper 76 - 77 - @Inject 78 - lateinit var resourceRepo: ResourceRepo 79 - 80 - @Inject 81 - lateinit var prefsInteractor: PrefsInteractor 82 - 83 - override fun onReceive(context: Context?, intent: Intent?) { 84 - super.onReceive(context, intent) 85 - if (intent?.action == ON_CLICK_ACTION) { 86 - onClick(context, intent.getIntExtra(ARGS_WIDGET_ID, 0)) 87 - } 88 - } 89 - 90 - override fun onUpdate( 91 - context: Context?, 92 - appWidgetManager: AppWidgetManager?, 93 - appWidgetIds: IntArray? 94 - ) { 95 - appWidgetIds?.forEach { widgetId -> 96 - updateAppWidget(context, appWidgetManager, widgetId) 97 - } 98 - } 99 - 100 - override fun onDeleted(context: Context?, appWidgetIds: IntArray?) { 101 - CoroutineScope(Dispatchers.Main).launch { 102 - appWidgetIds?.forEach { prefsInteractor.removeWidget(it) } 103 - } 104 - } 105 - 106 - private fun updateAppWidget( 107 - context: Context?, 108 - appWidgetManager: AppWidgetManager?, 109 - appWidgetId: Int 110 - ) { 111 - if (context == null || appWidgetManager == null) return 112 - 113 - var recordType: RecordType? 114 - var runningRecord: RunningRecord? 115 - var isDarkTheme: Boolean 116 - runBlocking { 117 - val recordTypeId = prefsInteractor.getWidget(appWidgetId) 118 - recordType = recordTypeInteractor.get(recordTypeId)?.takeUnless { it.hidden } 119 - runningRecord = runningRecordInteractor.get(recordTypeId) 120 - isDarkTheme = prefsInteractor.getDarkMode() 121 - } 122 - 123 - val view = prepareView(context, recordType, runningRecord, isDarkTheme) 124 - measureView(context, view) 125 - val bitmap = view.getBitmapFromView() 126 - 127 - val views = RemoteViews(context.packageName, R.layout.widget_layout) 128 - if (runningRecord != null) { 129 - val timeStarted = runningRecord?.timeStarted.orZero() 130 - val base = SystemClock.elapsedRealtime() - (System.currentTimeMillis() - timeStarted) 131 - views.setChronometer(R.id.timerWidget, base, null, true) 132 - views.setViewVisibility(R.id.timerWidget, View.VISIBLE) 133 - } else { 134 - views.setViewVisibility(R.id.timerWidget, View.GONE) 135 - } 136 - views.setImageViewBitmap(R.id.ivWidgetBackground, bitmap) 137 - views.setOnClickPendingIntent(R.id.btnWidget, getPendingSelfIntent(context, appWidgetId)) 138 - 139 - appWidgetManager.updateAppWidget(appWidgetId, views) 140 - } 141 - 142 - private fun prepareView( 143 - context: Context, 144 - recordType: RecordType?, 145 - runningRecord: RunningRecord?, 146 - isDarkTheme: Boolean, 147 - ): View { 148 - val icon = recordType?.icon 149 - ?.let(iconMapper::mapIcon) 150 - ?: RecordTypeIcon.Image(R.drawable.unknown) 151 - 152 - val name = recordType?.name 153 - ?: R.string.widget_load_error.let(resourceRepo::getString) 154 - 155 - val color = if (runningRecord != null && recordType != null) { 156 - colorMapper.mapToColorInt(recordType.color, isDarkTheme) 157 - } else { 158 - Color.BLACK 159 - } 160 - 161 - val viewAlpha = if (runningRecord != null && recordType != null) { 162 - ENABLED_ALPHA 163 - } else { 164 - DISABLED_ALPHA 165 - } 166 - 167 - // TODO setting alpha on cardView doesn't work for some reason, wrap in layout before setting 168 - val container = FrameLayout(ContextThemeWrapper(context, R.style.AppTheme)) 169 - RecordTypeView(ContextThemeWrapper(context, R.style.AppTheme)).apply { 170 - cardElevation = 0f 171 - useCompatPadding = false 172 - itemIcon = icon 173 - itemName = name 174 - itemColor = color 175 - alpha = viewAlpha 176 - }.let(container::addView) 177 - 178 - return container 179 - } 180 - 181 - private fun measureView(context: Context, view: View) { 182 - var width = context.resources.getDimensionPixelSize(R.dimen.record_type_card_width) 183 - var height = context.resources.getDimensionPixelSize(R.dimen.record_type_card_height) 184 - val inflater = LayoutInflater.from(context) 185 - 186 - val entireView: View = inflater.inflate(R.layout.widget_layout, null) 187 - entireView.measureExactly(width = width, height = height) 188 - 189 - val imageView = entireView.findViewById<View>(R.id.ivWidgetBackground) 190 - width = imageView.measuredWidth 191 - height = imageView.measuredHeight 192 - view.measureExactly(width = width, height = height) 193 - } 194 - 195 - private fun onClick( 196 - context: Context?, 197 - widgetId: Int 198 - ) { 199 - CoroutineScope(Dispatchers.Main).launch { 200 - val recordTypeId = prefsInteractor.getWidget(widgetId) 201 - 202 - // If recordType removed - update widget and exit 203 - recordTypeInteractor.get(recordTypeId) 204 - ?.takeUnless { it.hidden } 205 - ?: run { 206 - widgetInteractor.updateWidget(widgetId) 207 - return@launch 208 - } 209 - 210 - val runningRecord = runningRecordInteractor.get(recordTypeId) 211 - if (runningRecord != null) { 212 - // Stop running record, add new record 213 - removeRunningRecordMediator.removeWithRecordAdd(runningRecord) 214 - } else { 215 - // Start running record 216 - addRunningRecordMediator.tryStartTimer( 217 - typeId = recordTypeId, 218 - onNeedToShowTagSelection = { showTagSelection(context, recordTypeId) } 219 - ) 220 - } 221 - } 222 - } 223 - 224 - private fun showTagSelection(context: Context?, typeId: Long) { 225 - context ?: return 226 - 227 - WidgetTagSelectionActivity.getStartIntent( 228 - context = context, 229 - data = RecordTagSelectionParams(typeId) 230 - ).let(context::startActivity) 231 - } 232 - 233 - private fun getPendingSelfIntent( 234 - context: Context, 235 - widgetId: Int 236 - ): PendingIntent { 237 - val intent = Intent(context, javaClass) 238 - intent.action = ON_CLICK_ACTION 239 - intent.putExtra(ARGS_WIDGET_ID, widgetId) 240 - return PendingIntent.getBroadcast(context, widgetId, intent, PendingIntents.getFlags()) 241 - } 242 - 243 - companion object { 244 - private const val ON_CLICK_ACTION = 245 - "com.example.util.simpletimetracker.feature_widget.widget.onclick" 246 - private const val ARGS_WIDGET_ID = "widgetId" 247 - 248 - private const val ENABLED_ALPHA = 1f 249 - private const val DISABLED_ALPHA = 0.5f 250 - } 251 - }
-62
features/feature_widget/src/main/java/com/example/util/simpletimetracker/feature_widget/widget/WidgetTagSelectionActivity.kt
··· 1 - package com.example.util.simpletimetracker.feature_widget.widget 2 - 3 - import android.content.Context 4 - import android.content.Intent 5 - import android.os.Bundle 6 - import androidx.fragment.app.commit 7 - import com.example.util.simpletimetracker.core.base.BaseActivity 8 - import com.example.util.simpletimetracker.core.dialog.OnTagSelectedListener 9 - import com.example.util.simpletimetracker.core.manager.ThemeManager 10 - import com.example.util.simpletimetracker.core.utils.activityArgumentDelegate 11 - import com.example.util.simpletimetracker.feature_widget.R 12 - import com.example.util.simpletimetracker.navigation.ScreenFactory 13 - import com.example.util.simpletimetracker.navigation.params.screen.RecordTagSelectionParams 14 - import dagger.hilt.android.AndroidEntryPoint 15 - import javax.inject.Inject 16 - 17 - @AndroidEntryPoint 18 - class WidgetTagSelectionActivity : 19 - BaseActivity(), 20 - OnTagSelectedListener { 21 - 22 - @Inject 23 - lateinit var themeManager: ThemeManager 24 - 25 - @Inject 26 - lateinit var screenFactory: ScreenFactory 27 - 28 - private val params: RecordTagSelectionParams by activityArgumentDelegate( 29 - key = ARGS_PARAMS, default = RecordTagSelectionParams() 30 - ) 31 - 32 - override fun onCreate(savedInstanceState: Bundle?) { 33 - super.onCreate(savedInstanceState) 34 - 35 - themeManager.setTheme(this) 36 - setContentView(R.layout.widget_tag_selection_activity) 37 - 38 - screenFactory.getFragment(params)?.let { 39 - supportFragmentManager.commit { 40 - replace(R.id.containerWidgetRecordTagSelection, it) 41 - } 42 - } 43 - } 44 - 45 - override fun onTagSelected() { 46 - finish() 47 - } 48 - 49 - companion object { 50 - private const val ARGS_PARAMS = "args_params" 51 - 52 - fun getStartIntent( 53 - context: Context, 54 - data: RecordTagSelectionParams, 55 - ): Intent { 56 - return Intent(context, WidgetTagSelectionActivity::class.java).apply { 57 - flags = Intent.FLAG_ACTIVITY_NEW_TASK 58 - putExtra(ARGS_PARAMS, data) 59 - } 60 - } 61 - } 62 - }
-24
features/feature_widget/src/main/java/com/example/util/simpletimetracker/feature_widget/configure/adapter/WidgetAdapterDelegate.kt
··· 1 - package com.example.util.simpletimetracker.feature_widget.configure.adapter 2 - 3 - import com.example.util.simpletimetracker.feature_base_adapter.createRecyclerBindingAdapterDelegate 4 - import com.example.util.simpletimetracker.feature_views.extension.setOnClickWith 5 - import com.example.util.simpletimetracker.feature_base_adapter.recordType.RecordTypeViewData as ViewData 6 - import com.example.util.simpletimetracker.feature_widget.databinding.ItemWidgetRecordTypeLayoutBinding as Binding 7 - 8 - fun createWidgetAdapterDelegate( 9 - onItemClick: ((ViewData) -> Unit) 10 - ) = createRecyclerBindingAdapterDelegate<ViewData, Binding>( 11 - Binding::inflate 12 - ) { binding, item, _ -> 13 - 14 - with(binding.viewRecordTypeItem) { 15 - item as ViewData 16 - 17 - itemColor = item.color 18 - itemIcon = item.iconId 19 - itemIconColor = item.iconColor 20 - itemIconAlpha = item.iconAlpha 21 - itemName = item.name 22 - setOnClickWith(item, onItemClick) 23 - } 24 - }
-5
features/feature_widget/src/main/java/com/example/util/simpletimetracker/feature_widget/configure/extra/WidgetExtra.kt
··· 1 - package com.example.util.simpletimetracker.feature_widget.configure.extra 2 - 3 - data class WidgetExtra( 4 - val widgetId: Int 5 - )
-85
features/feature_widget/src/main/java/com/example/util/simpletimetracker/feature_widget/configure/view/WidgetConfigureActivity.kt
··· 1 - package com.example.util.simpletimetracker.feature_widget.configure.view 2 - 3 - import android.app.Activity 4 - import android.appwidget.AppWidgetManager 5 - import android.content.Intent 6 - import android.os.Bundle 7 - import androidx.activity.viewModels 8 - import com.example.util.simpletimetracker.core.base.BaseActivity 9 - import com.example.util.simpletimetracker.core.manager.ThemeManager 10 - import com.example.util.simpletimetracker.feature_base_adapter.BaseRecyclerAdapter 11 - import com.example.util.simpletimetracker.feature_base_adapter.empty.createEmptyAdapterDelegate 12 - import com.example.util.simpletimetracker.feature_base_adapter.loader.createLoaderAdapterDelegate 13 - import com.example.util.simpletimetracker.feature_widget.configure.adapter.createWidgetAdapterDelegate 14 - import com.example.util.simpletimetracker.feature_widget.configure.extra.WidgetExtra 15 - import com.example.util.simpletimetracker.feature_widget.configure.viewModel.WidgetViewModel 16 - import com.example.util.simpletimetracker.feature_widget.databinding.WidgetConfigureActivityBinding 17 - import com.google.android.flexbox.FlexDirection 18 - import com.google.android.flexbox.FlexWrap 19 - import com.google.android.flexbox.FlexboxLayoutManager 20 - import com.google.android.flexbox.JustifyContent 21 - import dagger.hilt.android.AndroidEntryPoint 22 - import javax.inject.Inject 23 - 24 - @AndroidEntryPoint 25 - class WidgetConfigureActivity : BaseActivity() { 26 - 27 - @Inject 28 - lateinit var themeManager: ThemeManager 29 - 30 - private val viewModel: WidgetViewModel by viewModels() 31 - 32 - private val typesAdapter: BaseRecyclerAdapter by lazy { 33 - BaseRecyclerAdapter( 34 - createWidgetAdapterDelegate(viewModel::onRecordTypeClick), 35 - createEmptyAdapterDelegate(), 36 - createLoaderAdapterDelegate() 37 - ) 38 - } 39 - 40 - override fun onCreate(savedInstanceState: Bundle?) { 41 - super.onCreate(savedInstanceState) 42 - // Set the result to CANCELED. This will cause the widget host to cancel 43 - // out of the widget placement if they press the back button. 44 - setResult(RESULT_CANCELED) 45 - 46 - initUi() 47 - initViewModel() 48 - } 49 - 50 - private fun initUi() { 51 - themeManager.setTheme(this) 52 - val binding = WidgetConfigureActivityBinding.inflate(layoutInflater) 53 - setContentView(binding.root) 54 - 55 - binding.rvWidgetConfigureRecordType.apply { 56 - layoutManager = FlexboxLayoutManager(context).apply { 57 - flexDirection = FlexDirection.ROW 58 - justifyContent = JustifyContent.CENTER 59 - flexWrap = FlexWrap.WRAP 60 - } 61 - adapter = typesAdapter 62 - } 63 - } 64 - 65 - private fun initViewModel(): Unit = with(viewModel) { 66 - val widgetId = intent?.extras 67 - ?.getInt( 68 - AppWidgetManager.EXTRA_APPWIDGET_ID, 69 - AppWidgetManager.INVALID_APPWIDGET_ID 70 - ) 71 - ?: AppWidgetManager.INVALID_APPWIDGET_ID 72 - 73 - extra = WidgetExtra(widgetId) 74 - recordTypes.observe(typesAdapter::replace) 75 - handled.observe(::exit) 76 - } 77 - 78 - private fun exit(widgetId: Int) { 79 - val resultValue = Intent().apply { 80 - putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId) 81 - } 82 - setResult(Activity.RESULT_OK, resultValue) 83 - finish() 84 - } 85 - }
-53
features/feature_widget/src/main/java/com/example/util/simpletimetracker/feature_widget/configure/viewModel/WidgetViewModel.kt
··· 1 - package com.example.util.simpletimetracker.feature_widget.configure.viewModel 2 - 3 - import androidx.lifecycle.LiveData 4 - import androidx.lifecycle.MutableLiveData 5 - import androidx.lifecycle.ViewModel 6 - import androidx.lifecycle.viewModelScope 7 - import com.example.util.simpletimetracker.feature_base_adapter.ViewHolderType 8 - import com.example.util.simpletimetracker.domain.interactor.WidgetInteractor 9 - import com.example.util.simpletimetracker.core.mapper.RecordTypeViewDataMapper 10 - import com.example.util.simpletimetracker.feature_base_adapter.recordType.RecordTypeViewData 11 - import com.example.util.simpletimetracker.domain.interactor.PrefsInteractor 12 - import com.example.util.simpletimetracker.domain.interactor.RecordTypeInteractor 13 - import com.example.util.simpletimetracker.feature_widget.configure.extra.WidgetExtra 14 - import dagger.hilt.android.lifecycle.HiltViewModel 15 - import kotlinx.coroutines.launch 16 - import javax.inject.Inject 17 - 18 - @HiltViewModel 19 - class WidgetViewModel @Inject constructor( 20 - private val recordTypeInteractor: RecordTypeInteractor, 21 - private val prefsInteractor: PrefsInteractor, 22 - private val widgetInteractor: WidgetInteractor, 23 - private val recordTypeViewDataMapper: RecordTypeViewDataMapper 24 - ) : ViewModel() { 25 - 26 - lateinit var extra: WidgetExtra 27 - 28 - val recordTypes: LiveData<List<ViewHolderType>> by lazy { 29 - MutableLiveData<List<ViewHolderType>>().let { initial -> 30 - viewModelScope.launch { initial.value = loadRecordTypesViewData() } 31 - initial 32 - } 33 - } 34 - val handled: LiveData<Int> = MutableLiveData() 35 - 36 - fun onRecordTypeClick(item: RecordTypeViewData) { 37 - viewModelScope.launch { 38 - prefsInteractor.setWidget(extra.widgetId, item.id) 39 - widgetInteractor.updateWidget(extra.widgetId) 40 - (handled as MutableLiveData).value = extra.widgetId 41 - } 42 - } 43 - 44 - private suspend fun loadRecordTypesViewData(): List<ViewHolderType> { 45 - val isDarkTheme = prefsInteractor.getDarkMode() 46 - 47 - return recordTypeInteractor.getAll() 48 - .filter { !it.hidden } 49 - .map { recordTypeViewDataMapper.map(it, isDarkTheme) } 50 - .takeUnless { it.isEmpty() } 51 - ?: recordTypeViewDataMapper.mapToEmpty() 52 - } 53 - }
+83
features/feature_widget/src/main/java/com/example/util/simpletimetracker/feature_widget/single/settings/WidgetSingleSettingsActivity.kt
··· 1 + package com.example.util.simpletimetracker.feature_widget.single.settings 2 + 3 + import android.app.Activity 4 + import android.appwidget.AppWidgetManager 5 + import android.content.Intent 6 + import android.os.Bundle 7 + import androidx.activity.viewModels 8 + import com.example.util.simpletimetracker.core.base.BaseActivity 9 + import com.example.util.simpletimetracker.core.manager.ThemeManager 10 + import com.example.util.simpletimetracker.feature_base_adapter.BaseRecyclerAdapter 11 + import com.example.util.simpletimetracker.feature_base_adapter.empty.createEmptyAdapterDelegate 12 + import com.example.util.simpletimetracker.feature_base_adapter.loader.createLoaderAdapterDelegate 13 + import com.example.util.simpletimetracker.feature_widget.databinding.WidgetSingleSettingsConfigureActivityBinding 14 + import com.example.util.simpletimetracker.feature_widget.single.settings.adapter.createWidgetSingleSettingsAdapterDelegate 15 + import com.google.android.flexbox.FlexDirection 16 + import com.google.android.flexbox.FlexWrap 17 + import com.google.android.flexbox.FlexboxLayoutManager 18 + import com.google.android.flexbox.JustifyContent 19 + import dagger.hilt.android.AndroidEntryPoint 20 + import javax.inject.Inject 21 + 22 + @AndroidEntryPoint 23 + class WidgetSingleSettingsActivity : BaseActivity() { 24 + 25 + @Inject 26 + lateinit var themeManager: ThemeManager 27 + 28 + private val viewModel: WidgetSingleSettingsViewModel by viewModels() 29 + 30 + private val typesAdapter: BaseRecyclerAdapter by lazy { 31 + BaseRecyclerAdapter( 32 + createWidgetSingleSettingsAdapterDelegate(viewModel::onRecordTypeClick), 33 + createEmptyAdapterDelegate(), 34 + createLoaderAdapterDelegate() 35 + ) 36 + } 37 + 38 + override fun onCreate(savedInstanceState: Bundle?) { 39 + super.onCreate(savedInstanceState) 40 + // Set the result to CANCELED. This will cause the widget host to cancel 41 + // out of the widget placement if they press the back button. 42 + setResult(RESULT_CANCELED) 43 + 44 + initUi() 45 + initViewModel() 46 + } 47 + 48 + private fun initUi() { 49 + themeManager.setTheme(this) 50 + val binding = WidgetSingleSettingsConfigureActivityBinding.inflate(layoutInflater) 51 + setContentView(binding.root) 52 + 53 + binding.rvWidgetSingleSettingsRecordType.apply { 54 + layoutManager = FlexboxLayoutManager(context).apply { 55 + flexDirection = FlexDirection.ROW 56 + justifyContent = JustifyContent.CENTER 57 + flexWrap = FlexWrap.WRAP 58 + } 59 + adapter = typesAdapter 60 + } 61 + } 62 + 63 + private fun initViewModel(): Unit = with(viewModel) { 64 + val widgetId = intent?.extras 65 + ?.getInt( 66 + AppWidgetManager.EXTRA_APPWIDGET_ID, 67 + AppWidgetManager.INVALID_APPWIDGET_ID 68 + ) 69 + ?: AppWidgetManager.INVALID_APPWIDGET_ID 70 + 71 + extra = WidgetSingleSettingsExtra(widgetId) 72 + recordTypes.observe(typesAdapter::replace) 73 + handled.observe(::exit) 74 + } 75 + 76 + private fun exit(widgetId: Int) { 77 + val resultValue = Intent().apply { 78 + putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId) 79 + } 80 + setResult(Activity.RESULT_OK, resultValue) 81 + finish() 82 + } 83 + }
+5
features/feature_widget/src/main/java/com/example/util/simpletimetracker/feature_widget/single/settings/WidgetSingleSettingsExtra.kt
··· 1 + package com.example.util.simpletimetracker.feature_widget.single.settings 2 + 3 + data class WidgetSingleSettingsExtra( 4 + val widgetId: Int 5 + )
+52
features/feature_widget/src/main/java/com/example/util/simpletimetracker/feature_widget/single/settings/WidgetSingleSettingsViewModel.kt
··· 1 + package com.example.util.simpletimetracker.feature_widget.single.settings 2 + 3 + import androidx.lifecycle.LiveData 4 + import androidx.lifecycle.MutableLiveData 5 + import androidx.lifecycle.ViewModel 6 + import androidx.lifecycle.viewModelScope 7 + import com.example.util.simpletimetracker.feature_base_adapter.ViewHolderType 8 + import com.example.util.simpletimetracker.domain.interactor.WidgetInteractor 9 + import com.example.util.simpletimetracker.core.mapper.RecordTypeViewDataMapper 10 + import com.example.util.simpletimetracker.feature_base_adapter.recordType.RecordTypeViewData 11 + import com.example.util.simpletimetracker.domain.interactor.PrefsInteractor 12 + import com.example.util.simpletimetracker.domain.interactor.RecordTypeInteractor 13 + import dagger.hilt.android.lifecycle.HiltViewModel 14 + import kotlinx.coroutines.launch 15 + import javax.inject.Inject 16 + 17 + @HiltViewModel 18 + class WidgetSingleSettingsViewModel @Inject constructor( 19 + private val recordTypeInteractor: RecordTypeInteractor, 20 + private val prefsInteractor: PrefsInteractor, 21 + private val widgetInteractor: WidgetInteractor, 22 + private val recordTypeViewDataMapper: RecordTypeViewDataMapper 23 + ) : ViewModel() { 24 + 25 + lateinit var extra: WidgetSingleSettingsExtra 26 + 27 + val recordTypes: LiveData<List<ViewHolderType>> by lazy { 28 + MutableLiveData<List<ViewHolderType>>().let { initial -> 29 + viewModelScope.launch { initial.value = loadRecordTypesViewData() } 30 + initial 31 + } 32 + } 33 + val handled: LiveData<Int> = MutableLiveData() 34 + 35 + fun onRecordTypeClick(item: RecordTypeViewData) { 36 + viewModelScope.launch { 37 + prefsInteractor.setWidget(extra.widgetId, item.id) 38 + widgetInteractor.updateWidget(extra.widgetId) 39 + (handled as MutableLiveData).value = extra.widgetId 40 + } 41 + } 42 + 43 + private suspend fun loadRecordTypesViewData(): List<ViewHolderType> { 44 + val isDarkTheme = prefsInteractor.getDarkMode() 45 + 46 + return recordTypeInteractor.getAll() 47 + .filter { !it.hidden } 48 + .map { recordTypeViewDataMapper.map(it, isDarkTheme) } 49 + .takeUnless { it.isEmpty() } 50 + ?: recordTypeViewDataMapper.mapToEmpty() 51 + } 52 + }
+24
features/feature_widget/src/main/java/com/example/util/simpletimetracker/feature_widget/single/settings/adapter/WidgetSingleSettingsAdapterDelegate.kt
··· 1 + package com.example.util.simpletimetracker.feature_widget.single.settings.adapter 2 + 3 + import com.example.util.simpletimetracker.feature_base_adapter.createRecyclerBindingAdapterDelegate 4 + import com.example.util.simpletimetracker.feature_views.extension.setOnClickWith 5 + import com.example.util.simpletimetracker.feature_base_adapter.recordType.RecordTypeViewData as ViewData 6 + import com.example.util.simpletimetracker.feature_widget.databinding.ItemWidgetRecordTypeLayoutBinding as Binding 7 + 8 + fun createWidgetSingleSettingsAdapterDelegate( 9 + onItemClick: ((ViewData) -> Unit) 10 + ) = createRecyclerBindingAdapterDelegate<ViewData, Binding>( 11 + Binding::inflate 12 + ) { binding, item, _ -> 13 + 14 + with(binding.viewRecordTypeItem) { 15 + item as ViewData 16 + 17 + itemColor = item.color 18 + itemIcon = item.iconId 19 + itemIconColor = item.iconColor 20 + itemIconAlpha = item.iconAlpha 21 + itemName = item.name 22 + setOnClickWith(item, onItemClick) 23 + } 24 + }