Migrate WidgetTorchConfigureActivity to compose

This commit is contained in:
Ensar Sarajčić
2023-09-28 17:24:53 +02:00
parent 2a5011fb22
commit 4c5deb10e4
6 changed files with 97 additions and 273 deletions

View File

@ -1,15 +1,12 @@
package com.simplemobiletools.flashlight.activities package com.simplemobiletools.flashlight.activities
import android.app.Activity import android.app.Activity
import android.app.Application
import android.appwidget.AppWidgetManager import android.appwidget.AppWidgetManager
import android.content.Intent import android.content.Intent
import android.graphics.Color
import android.os.Bundle import android.os.Bundle
import androidx.activity.compose.setContent import androidx.activity.compose.setContent
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.simplemobiletools.commons.compose.extensions.enableEdgeToEdgeSimple import com.simplemobiletools.commons.compose.extensions.enableEdgeToEdgeSimple
import com.simplemobiletools.commons.compose.theme.AppThemeSurface import com.simplemobiletools.commons.compose.theme.AppThemeSurface
@ -18,14 +15,13 @@ import com.simplemobiletools.commons.dialogs.FeatureLockedDialog
import com.simplemobiletools.commons.extensions.isOrWasThankYouInstalled import com.simplemobiletools.commons.extensions.isOrWasThankYouInstalled
import com.simplemobiletools.commons.helpers.IS_CUSTOMIZING_COLORS import com.simplemobiletools.commons.helpers.IS_CUSTOMIZING_COLORS
import com.simplemobiletools.flashlight.R import com.simplemobiletools.flashlight.R
import com.simplemobiletools.flashlight.activities.viewmodel.WidgetConfigureViewModel
import com.simplemobiletools.flashlight.extensions.config import com.simplemobiletools.flashlight.extensions.config
import com.simplemobiletools.flashlight.helpers.MyWidgetBrightDisplayProvider import com.simplemobiletools.flashlight.helpers.MyWidgetBrightDisplayProvider
import com.simplemobiletools.flashlight.screens.WidgetBrightDisplayConfigureScreen import com.simplemobiletools.flashlight.screens.WidgetConfigureScreen
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
class WidgetBrightDisplayConfigureActivity : SimpleActivity() { class WidgetBrightDisplayConfigureActivity : SimpleActivity() {
private val viewModel by viewModels<WidgetBrightDisplayConfigureViewModel>() private val viewModel by viewModels<WidgetConfigureViewModel>()
private var mFeatureLockedDialog: FeatureLockedDialog? = null private var mFeatureLockedDialog: FeatureLockedDialog? = null
@ -47,7 +43,8 @@ class WidgetBrightDisplayConfigureActivity : SimpleActivity() {
val widgetColor by viewModel.widgetColor.collectAsStateWithLifecycle() val widgetColor by viewModel.widgetColor.collectAsStateWithLifecycle()
val widgetAlpha by viewModel.widgetAlpha.collectAsStateWithLifecycle() val widgetAlpha by viewModel.widgetAlpha.collectAsStateWithLifecycle()
WidgetBrightDisplayConfigureScreen( WidgetConfigureScreen(
widgetDrawable = R.drawable.ic_bright_display_vector,
widgetColor = widgetColor, widgetColor = widgetColor,
widgetAlpha = widgetAlpha, widgetAlpha = widgetAlpha,
onSliderChanged = { onSliderChanged = {
@ -106,40 +103,4 @@ class WidgetBrightDisplayConfigureActivity : SimpleActivity() {
sendBroadcast(this) sendBroadcast(this)
} }
} }
internal class WidgetBrightDisplayConfigureViewModel(
application: Application
) : AndroidViewModel(application) {
private val _widgetAlpha = MutableStateFlow(0f)
val widgetAlpha = _widgetAlpha.asStateFlow()
private val _widgetId = MutableStateFlow(0)
val widgetId = _widgetId.asStateFlow()
private val _widgetColor = MutableStateFlow(0)
val widgetColor = _widgetColor.asStateFlow()
fun changeAlpha(newAlpha: Float) {
_widgetAlpha.value = newAlpha
}
fun updateColor(newColor: Int) {
_widgetColor.value = newColor
}
fun setWidgetId(widgetId: Int) {
_widgetId.value = widgetId
}
init {
_widgetColor.value = application.config.widgetBgColor
if (_widgetColor.value == application.resources.getColor(R.color.default_widget_bg_color) && application.config.isUsingSystemTheme) {
_widgetColor.value = application.resources.getColor(R.color.you_primary_color, application.theme)
}
_widgetAlpha.value = Color.alpha(_widgetColor.value) / 255f
}
}
} }

View File

@ -3,60 +3,70 @@ package com.simplemobiletools.flashlight.activities
import android.app.Activity import android.app.Activity
import android.appwidget.AppWidgetManager import android.appwidget.AppWidgetManager
import android.content.Intent import android.content.Intent
import android.content.res.ColorStateList
import android.graphics.Color
import android.os.Bundle import android.os.Bundle
import android.widget.SeekBar import androidx.activity.compose.setContent
import androidx.activity.viewModels
import androidx.compose.runtime.getValue
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.simplemobiletools.commons.compose.extensions.enableEdgeToEdgeSimple
import com.simplemobiletools.commons.compose.theme.AppThemeSurface
import com.simplemobiletools.commons.dialogs.ColorPickerDialog import com.simplemobiletools.commons.dialogs.ColorPickerDialog
import com.simplemobiletools.commons.dialogs.FeatureLockedDialog import com.simplemobiletools.commons.dialogs.FeatureLockedDialog
import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.extensions.isOrWasThankYouInstalled
import com.simplemobiletools.commons.helpers.IS_CUSTOMIZING_COLORS import com.simplemobiletools.commons.helpers.IS_CUSTOMIZING_COLORS
import com.simplemobiletools.flashlight.R import com.simplemobiletools.flashlight.R
import com.simplemobiletools.flashlight.databinding.WidgetTorchConfigBinding import com.simplemobiletools.flashlight.activities.viewmodel.WidgetConfigureViewModel
import com.simplemobiletools.flashlight.extensions.config import com.simplemobiletools.flashlight.extensions.config
import com.simplemobiletools.flashlight.extensions.updateBrightDisplayWidget import com.simplemobiletools.flashlight.extensions.updateBrightDisplayWidget
import com.simplemobiletools.flashlight.helpers.MyWidgetTorchProvider import com.simplemobiletools.flashlight.helpers.MyWidgetTorchProvider
import com.simplemobiletools.flashlight.screens.WidgetConfigureScreen
class WidgetTorchConfigureActivity : SimpleActivity() { class WidgetTorchConfigureActivity : SimpleActivity() {
private val binding by viewBinding(WidgetTorchConfigBinding::inflate) private val viewModel by viewModels<WidgetConfigureViewModel>()
private var mWidgetAlpha = 0f
private var mWidgetId = 0
private var mWidgetColor = 0
private var mWidgetColorWithoutTransparency = 0
private var mFeatureLockedDialog: FeatureLockedDialog? = null private var mFeatureLockedDialog: FeatureLockedDialog? = null
public override fun onCreate(savedInstanceState: Bundle?) { public override fun onCreate(savedInstanceState: Bundle?) {
useDynamicTheme = false useDynamicTheme = false
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setResult(Activity.RESULT_CANCELED) setResult(Activity.RESULT_CANCELED)
setContentView(binding.root)
initVariables()
val isCustomizingColors = intent.extras?.getBoolean(IS_CUSTOMIZING_COLORS) ?: false val isCustomizingColors = intent.extras?.getBoolean(IS_CUSTOMIZING_COLORS) ?: false
mWidgetId = intent.extras?.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID) ?: AppWidgetManager.INVALID_APPWIDGET_ID viewModel.setWidgetId(intent.extras?.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID) ?: AppWidgetManager.INVALID_APPWIDGET_ID)
if (mWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID && !isCustomizingColors) { if (viewModel.widgetId.value == AppWidgetManager.INVALID_APPWIDGET_ID && !isCustomizingColors) {
finish() finish()
} }
binding.apply { enableEdgeToEdgeSimple()
configSave.setOnClickListener { saveConfig() } setContent {
configWidgetColor.setOnClickListener { pickBackgroundColor() } AppThemeSurface {
val widgetColor by viewModel.widgetColor.collectAsStateWithLifecycle()
val widgetAlpha by viewModel.widgetAlpha.collectAsStateWithLifecycle()
val primaryColor = getProperPrimaryColor() WidgetConfigureScreen(
configWidgetSeekbar.setColors(getProperTextColor(), primaryColor, primaryColor) widgetDrawable = R.drawable.ic_flashlight_vector,
widgetColor = widgetColor,
if (!isCustomizingColors && !isOrWasThankYouInstalled()) { widgetAlpha = widgetAlpha,
mFeatureLockedDialog = FeatureLockedDialog(this@WidgetTorchConfigureActivity) { onSliderChanged = {
if (!isOrWasThankYouInstalled()) { viewModel.changeAlpha(it)
finish() },
onColorPressed = {
pickBackgroundColor()
},
onSavePressed = {
saveConfig()
} }
)
}
}
if (!isCustomizingColors && !isOrWasThankYouInstalled()) {
mFeatureLockedDialog = FeatureLockedDialog(this) {
if (!isOrWasThankYouInstalled()) {
finish()
} }
} }
configSave.backgroundTintList = ColorStateList.valueOf(getProperPrimaryColor())
configSave.setTextColor(getProperPrimaryColor().getContrastColor())
} }
} }
@ -69,67 +79,31 @@ class WidgetTorchConfigureActivity : SimpleActivity() {
} }
} }
private fun initVariables() {
mWidgetColor = config.widgetBgColor
if (mWidgetColor == resources.getColor(R.color.default_widget_bg_color) && config.isUsingSystemTheme) {
mWidgetColor = resources.getColor(R.color.you_primary_color, theme)
}
mWidgetAlpha = Color.alpha(mWidgetColor) / 255.toFloat()
mWidgetColorWithoutTransparency = Color.rgb(Color.red(mWidgetColor), Color.green(mWidgetColor), Color.blue(mWidgetColor))
binding.configWidgetSeekbar.apply {
setOnSeekBarChangeListener(seekbarChangeListener)
progress = (mWidgetAlpha * 100).toInt()
}
updateColors()
}
private fun saveConfig() { private fun saveConfig() {
config.widgetBgColor = mWidgetColor config.widgetBgColor = viewModel.widgetColor.value
requestWidgetUpdate() requestWidgetUpdate()
Intent().apply { Intent().apply {
putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mWidgetId) putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, viewModel.widgetId.value)
setResult(Activity.RESULT_OK, this) setResult(Activity.RESULT_OK, this)
} }
finish() finish()
} }
private fun pickBackgroundColor() { private fun pickBackgroundColor() {
ColorPickerDialog(this, mWidgetColorWithoutTransparency) { wasPositivePressed, color -> ColorPickerDialog(this, viewModel.widgetColor.value) { wasPositivePressed, color ->
if (wasPositivePressed) { if (wasPositivePressed) {
mWidgetColorWithoutTransparency = color viewModel.updateColor(color)
updateColors()
} }
} }
} }
private fun requestWidgetUpdate() { private fun requestWidgetUpdate() {
Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE, null, this, MyWidgetTorchProvider::class.java).apply { Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE, null, this, MyWidgetTorchProvider::class.java).apply {
putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, intArrayOf(mWidgetId)) putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, intArrayOf(viewModel.widgetId.value))
sendBroadcast(this) sendBroadcast(this)
} }
updateBrightDisplayWidget() updateBrightDisplayWidget()
} }
private fun updateColors() {
mWidgetColor = mWidgetColorWithoutTransparency.adjustAlpha(mWidgetAlpha)
binding.apply {
configWidgetColor.setFillWithStroke(mWidgetColor, mWidgetColor)
configImage.background.mutate().applyColorFilter(mWidgetColor)
}
}
private val seekbarChangeListener = object : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
mWidgetAlpha = progress.toFloat() / 100.toFloat()
updateColors()
}
override fun onStartTrackingTouch(seekBar: SeekBar) {}
override fun onStopTrackingTouch(seekBar: SeekBar) {}
}
} }

View File

@ -0,0 +1,45 @@
package com.simplemobiletools.flashlight.activities.viewmodel
import android.app.Application
import android.graphics.Color
import androidx.lifecycle.AndroidViewModel
import com.simplemobiletools.flashlight.R
import com.simplemobiletools.flashlight.extensions.config
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
internal class WidgetConfigureViewModel(
application: Application
) : AndroidViewModel(application) {
private val _widgetAlpha = MutableStateFlow(0f)
val widgetAlpha = _widgetAlpha.asStateFlow()
private val _widgetId = MutableStateFlow(0)
val widgetId = _widgetId.asStateFlow()
private val _widgetColor = MutableStateFlow(0)
val widgetColor = _widgetColor.asStateFlow()
fun changeAlpha(newAlpha: Float) {
_widgetAlpha.value = newAlpha
}
fun updateColor(newColor: Int) {
_widgetColor.value = newColor
}
fun setWidgetId(widgetId: Int) {
_widgetId.value = widgetId
}
init {
_widgetColor.value = application.config.widgetBgColor
if (_widgetColor.value == application.resources.getColor(R.color.default_widget_bg_color) && application.config.isUsingSystemTheme) {
_widgetColor.value = application.resources.getColor(R.color.you_primary_color, application.theme)
}
_widgetAlpha.value = Color.alpha(_widgetColor.value) / 255f
}
}

View File

@ -24,7 +24,8 @@ import com.simplemobiletools.commons.extensions.adjustAlpha
import com.simplemobiletools.flashlight.R import com.simplemobiletools.flashlight.R
@Composable @Composable
internal fun WidgetBrightDisplayConfigureScreen( internal fun WidgetConfigureScreen(
widgetDrawable: Int,
widgetColor: Int, widgetColor: Int,
widgetAlpha: Float, widgetAlpha: Float,
onSliderChanged: (Float) -> Unit, onSliderChanged: (Float) -> Unit,
@ -51,7 +52,7 @@ internal fun WidgetBrightDisplayConfigureScreen(
modifier = Modifier modifier = Modifier
.align(Alignment.Center) .align(Alignment.Center)
.size(dimensionResource(id = R.dimen.main_button_size)), .size(dimensionResource(id = R.dimen.main_button_size)),
painter = painterResource(id = R.drawable.ic_bright_display_vector), painter = painterResource(id = widgetDrawable),
contentDescription = stringResource(id = R.string.bright_display), contentDescription = stringResource(id = R.string.bright_display),
tint = Color(widgetColor.adjustAlpha(widgetAlpha)) tint = Color(widgetColor.adjustAlpha(widgetAlpha))
) )
@ -104,7 +105,8 @@ internal fun WidgetBrightDisplayConfigureScreen(
@MyDevices @MyDevices
private fun WidgetBrightDisplayConfigureScreenPreview() { private fun WidgetBrightDisplayConfigureScreenPreview() {
AppThemeSurface { AppThemeSurface {
WidgetBrightDisplayConfigureScreen( WidgetConfigureScreen(
widgetDrawable = R.drawable.ic_bright_display_vector,
widgetColor = MaterialTheme.colorScheme.primary.toArgb(), widgetColor = MaterialTheme.colorScheme.primary.toArgb(),
widgetAlpha = 1f, widgetAlpha = 1f,
onSliderChanged = {}, onSliderChanged = {},

View File

@ -1,91 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/bright_display_holder"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="@+id/bright_display"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white" />
<android.widget.TextView
android:id="@+id/bright_display_change_color"
style="@style/StrokeButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:alpha="0.5"
android:text="@string/change_color" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/sleep_timer_holder"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@color/default_background_color"
android:clickable="true"
android:visibility="gone"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
tools:visibility="visible">
<ImageView
android:id="@+id/sleep_timer_divider_top"
android:layout_width="0dp"
android:layout_height="1px"
android:background="@color/divider_grey"
app:layout_constraintBottom_toTopOf="@+id/sleep_timer_stop"
app:layout_constraintEnd_toEndOf="@+id/sleep_timer_stop"
app:layout_constraintStart_toStartOf="@+id/sleep_timer_label" />
<ImageView
android:id="@+id/sleep_timer_divider_start"
android:layout_width="1px"
android:layout_height="0dp"
android:background="@color/divider_grey"
app:layout_constraintBottom_toBottomOf="@+id/sleep_timer_stop"
app:layout_constraintStart_toStartOf="@+id/sleep_timer_label"
app:layout_constraintTop_toTopOf="@+id/sleep_timer_stop" />
<com.simplemobiletools.commons.views.MyTextView
android:id="@+id/sleep_timer_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:paddingStart="@dimen/normal_margin"
android:paddingEnd="@dimen/normal_margin"
android:text="@string/sleep_timer"
android:textSize="@dimen/big_text_size"
app:layout_constraintBottom_toBottomOf="@+id/sleep_timer_stop"
app:layout_constraintEnd_toStartOf="@+id/sleep_timer_value"
app:layout_constraintTop_toTopOf="@+id/sleep_timer_stop" />
<com.simplemobiletools.commons.views.MyTextView
android:id="@+id/sleep_timer_value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="00:00"
android:textSize="@dimen/big_text_size"
app:layout_constraintBottom_toBottomOf="@+id/sleep_timer_stop"
app:layout_constraintEnd_toStartOf="@+id/sleep_timer_stop"
app:layout_constraintTop_toTopOf="@+id/sleep_timer_stop"
tools:ignore="HardcodedText" />
<ImageView
android:id="@+id/sleep_timer_stop"
android:layout_width="@dimen/normal_icon_size"
android:layout_height="@dimen/normal_icon_size"
android:layout_marginStart="@dimen/tiny_margin"
android:layout_marginEnd="@dimen/tiny_margin"
android:background="?attr/selectableItemBackgroundBorderless"
android:padding="@dimen/medium_margin"
android:src="@drawable/ic_cross_vector"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</RelativeLayout>

View File

@ -1,67 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/config_bright_display_coordinator"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:id="@+id/config_bright_display_holder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_margin="@dimen/activity_margin">
<RelativeLayout
android:id="@+id/config_bright_display_wrapper"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@+id/config_widget_color"
android:layout_marginBottom="@dimen/activity_margin"
android:gravity="center">
<ImageView
android:id="@+id/config_image"
android:layout_width="@dimen/main_button_size"
android:layout_height="@dimen/main_button_size"
android:background="@drawable/ic_bright_display_vector" />
</RelativeLayout>
<ImageView
android:id="@+id/config_widget_color"
android:layout_width="@dimen/widget_colorpicker_size"
android:layout_height="@dimen/widget_colorpicker_size"
android:layout_above="@+id/config_save"
android:layout_margin="@dimen/tiny_margin" />
<RelativeLayout
android:id="@+id/config_widget_seekbar_holder"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignTop="@+id/config_widget_color"
android:layout_alignBottom="@+id/config_widget_color"
android:layout_marginStart="@dimen/medium_margin"
android:layout_toEndOf="@+id/config_widget_color"
android:background="@drawable/widget_config_seekbar_background">
<com.simplemobiletools.commons.views.MySeekBar
android:id="@+id/config_widget_seekbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:paddingStart="@dimen/activity_margin"
android:paddingEnd="@dimen/activity_margin" />
</RelativeLayout>
<Button
android:id="@+id/config_save"
style="@style/MyWidgetConfigSaveStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentBottom="true"
android:layout_marginTop="@dimen/tiny_margin"
android:text="@string/ok" />
</RelativeLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>