From 68f4e32ce24d682978bf584bc19a774d4545988c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ensar=20Saraj=C4=8Di=C4=87?= Date: Thu, 28 Sep 2023 15:09:52 +0200 Subject: [PATCH] Migrate BrightDisplayActivity to compose --- .../activities/BrightDisplayActivity.kt | 133 ++++++++++-------- .../flashlight/screens/BrightDisplayScreen.kt | 80 +++++++++++ .../flashlight/views/SleepTimer.kt | 73 ++++++++++ 3 files changed, 231 insertions(+), 55 deletions(-) create mode 100644 app/src/main/kotlin/com/simplemobiletools/flashlight/screens/BrightDisplayScreen.kt create mode 100644 app/src/main/kotlin/com/simplemobiletools/flashlight/views/SleepTimer.kt diff --git a/app/src/main/kotlin/com/simplemobiletools/flashlight/activities/BrightDisplayActivity.kt b/app/src/main/kotlin/com/simplemobiletools/flashlight/activities/BrightDisplayActivity.kt index 4ab6945..bfee919 100644 --- a/app/src/main/kotlin/com/simplemobiletools/flashlight/activities/BrightDisplayActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/flashlight/activities/BrightDisplayActivity.kt @@ -1,23 +1,31 @@ package com.simplemobiletools.flashlight.activities +import android.app.Application import android.content.pm.ActivityInfo -import android.graphics.drawable.ColorDrawable import android.os.Bundle import android.view.WindowManager -import android.widget.RelativeLayout +import androidx.activity.compose.setContent +import androidx.activity.viewModels +import androidx.compose.runtime.getValue +import androidx.lifecycle.AndroidViewModel +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.extensions.* -import com.simplemobiletools.flashlight.databinding.ActivityBrightDisplayBinding +import com.simplemobiletools.commons.extensions.getFormattedDuration import com.simplemobiletools.flashlight.extensions.config import com.simplemobiletools.flashlight.helpers.stopSleepTimerCountDown import com.simplemobiletools.flashlight.models.Events +import com.simplemobiletools.flashlight.screens.BrightDisplayScreen +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow import org.greenrobot.eventbus.EventBus import org.greenrobot.eventbus.Subscribe import org.greenrobot.eventbus.ThreadMode import kotlin.system.exitProcess class BrightDisplayActivity : SimpleActivity() { - private val binding by viewBinding(ActivityBrightDisplayBinding::inflate) + private val viewModel by viewModels() override fun onCreate(savedInstanceState: Bundle?) { window.addFlags( @@ -29,29 +37,35 @@ class BrightDisplayActivity : SimpleActivity() { useDynamicTheme = false super.onCreate(savedInstanceState) - setContentView(binding.root) - supportActionBar?.hide() - setBackgroundColor(config.brightDisplayColor) + enableEdgeToEdgeSimple() + setContent { + AppThemeSurface { + val backgroundColor by viewModel.backgroundColor.collectAsStateWithLifecycle() + val timerVisible by viewModel.timerVisible.collectAsStateWithLifecycle() + val timerText by viewModel.timerText.collectAsStateWithLifecycle() - binding.brightDisplayChangeColor.setOnClickListener { - ColorPickerDialog(this, config.brightDisplayColor, true, currentColorCallback = { - setBackgroundColor(it) - }) { wasPositivePressed, color -> - if (wasPositivePressed) { - config.brightDisplayColor = color - - val contrastColor = color.getContrastColor() - binding.brightDisplayChangeColor.apply { - setTextColor(contrastColor) - background.applyColorFilter(contrastColor) + BrightDisplayScreen( + backgroundColor = backgroundColor, + onChangeColorPress = { + ColorPickerDialog(this, config.brightDisplayColor, true, currentColorCallback = { + viewModel.updateBackgroundColor(it) + }) { wasPositivePressed, color -> + if (wasPositivePressed) { + config.brightDisplayColor = color + viewModel.updateBackgroundColor(color) + } else { + viewModel.updateBackgroundColor(config.brightDisplayColor) + } + } + }, + timerVisible = timerVisible, + timerText = timerText, + onTimerCloseClick = { + stopSleepTimer() } - } else { - setBackgroundColor(config.brightDisplayColor) - } + ) } } - - binding.sleepTimerStop.setOnClickListener { stopSleepTimer() } } override fun onResume() { @@ -59,8 +73,6 @@ class BrightDisplayActivity : SimpleActivity() { window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) toggleBrightness(true) requestedOrientation = if (config.forcePortraitMode) ActivityInfo.SCREEN_ORIENTATION_PORTRAIT else ActivityInfo.SCREEN_ORIENTATION_SENSOR - - (binding.sleepTimerHolder.layoutParams as RelativeLayout.LayoutParams).bottomMargin = navigationBarHeight } override fun onPause() { @@ -69,28 +81,6 @@ class BrightDisplayActivity : SimpleActivity() { toggleBrightness(false) } - override fun onStart() { - super.onStart() - EventBus.getDefault().register(this) - } - - override fun onStop() { - super.onStop() - EventBus.getDefault().unregister(this) - } - - private fun setBackgroundColor(color: Int) { - binding.apply { - brightDisplay.background = ColorDrawable(color) - - val contrastColor = config.brightDisplayColor.getContrastColor() - brightDisplayChangeColor.apply { - setTextColor(contrastColor) - background.applyColorFilter(contrastColor) - } - } - } - private fun toggleBrightness(increase: Boolean) { val layout = window.attributes layout.screenBrightness = (if (increase) 1 else 0).toFloat() @@ -98,17 +88,50 @@ class BrightDisplayActivity : SimpleActivity() { } private fun stopSleepTimer() { - binding.sleepTimerHolder.fadeOut() + viewModel.hideTimer() stopSleepTimerCountDown() } - @Subscribe(threadMode = ThreadMode.MAIN) - fun sleepTimerChanged(event: Events.SleepTimerChanged) { - binding.sleepTimerValue.text = event.seconds.getFormattedDuration() - binding.sleepTimerHolder.beVisible() - if (event.seconds == 0) { - exitProcess(0) + internal class BrightDisplayViewModel( + application: Application + ) : AndroidViewModel(application) { + + + private val _timerText: MutableStateFlow = MutableStateFlow("00:00") + val timerText = _timerText.asStateFlow() + + private val _timerVisible: MutableStateFlow = MutableStateFlow(false) + val timerVisible = _timerVisible.asStateFlow() + + private val _backgroundColor: MutableStateFlow = MutableStateFlow(application.config.backgroundColor) + val backgroundColor = _backgroundColor.asStateFlow() + + init { + EventBus.getDefault().register(this) + } + + @Subscribe(threadMode = ThreadMode.MAIN) + fun sleepTimerChanged(event: Events.SleepTimerChanged) { + _timerText.value = event.seconds.getFormattedDuration() + _timerVisible.value = true + + if (event.seconds == 0) { + exitProcess(0) + } + } + + fun updateBackgroundColor(color: Int) { + _backgroundColor.value = color + } + + fun hideTimer() { + _timerVisible.value = false + } + + override fun onCleared() { + super.onCleared() + EventBus.getDefault().unregister(this) } } } diff --git a/app/src/main/kotlin/com/simplemobiletools/flashlight/screens/BrightDisplayScreen.kt b/app/src/main/kotlin/com/simplemobiletools/flashlight/screens/BrightDisplayScreen.kt new file mode 100644 index 0000000..ad309aa --- /dev/null +++ b/app/src/main/kotlin/com/simplemobiletools/flashlight/screens/BrightDisplayScreen.kt @@ -0,0 +1,80 @@ +package com.simplemobiletools.flashlight.screens + +import androidx.compose.animation.* +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.layout.* +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.toArgb +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import com.simplemobiletools.commons.compose.extensions.MyDevices +import com.simplemobiletools.commons.compose.theme.AppThemeSurface +import com.simplemobiletools.commons.extensions.getContrastColor +import com.simplemobiletools.flashlight.R +import com.simplemobiletools.flashlight.views.SleepTimer + +@Composable +internal fun BrightDisplayScreen( + backgroundColor: Int, + timerText: String?, + timerVisible: Boolean, + onChangeColorPress: () -> Unit, + onTimerCloseClick: () -> Unit +) { + Box( + modifier = Modifier + .fillMaxSize() + .background(Color(backgroundColor)) + ) { + TextButton( + modifier = Modifier + .wrapContentSize() + .align(Alignment.Center) + .border( + width = 1.dp, + color = Color(backgroundColor.getContrastColor()), + shape = MaterialTheme.shapes.extraLarge + ), + onClick = onChangeColorPress + ) { + Text( + text = stringResource(id = R.string.change_color), + color = Color(backgroundColor.getContrastColor()) + ) + } + + AnimatedVisibility( + modifier = Modifier.align(Alignment.BottomEnd) + .navigationBarsPadding(), + visible = timerVisible, + enter = fadeIn(), + exit = fadeOut() + ) { + SleepTimer( + timerText = timerText ?: "", + onCloseClick = onTimerCloseClick + ) + } + } +} + +@Composable +@MyDevices +private fun BrightDisplayScreenPreview() { + AppThemeSurface { + BrightDisplayScreen( + backgroundColor = MaterialTheme.colorScheme.background.toArgb(), + timerText = "00:00", + timerVisible = true, + onChangeColorPress = {}, + onTimerCloseClick = {} + ) + } +} diff --git a/app/src/main/kotlin/com/simplemobiletools/flashlight/views/SleepTimer.kt b/app/src/main/kotlin/com/simplemobiletools/flashlight/views/SleepTimer.kt new file mode 100644 index 0000000..5807d13 --- /dev/null +++ b/app/src/main/kotlin/com/simplemobiletools/flashlight/views/SleepTimer.kt @@ -0,0 +1,73 @@ +package com.simplemobiletools.flashlight.views + +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.wrapContentSize +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.RectangleShape +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import com.simplemobiletools.commons.compose.extensions.MyDevices +import com.simplemobiletools.commons.compose.theme.AppThemeSurface +import com.simplemobiletools.flashlight.R + +@Composable +internal fun SleepTimer( + modifier: Modifier = Modifier, + timerText: String, + onCloseClick: () -> Unit +) { + Row( + modifier = modifier + .wrapContentSize() + .background(MaterialTheme.colorScheme.background) + .border( + width = 1.dp, + color = Color.Gray, + shape = RectangleShape + ) + ) { + Text( + modifier = Modifier + .align(Alignment.CenterVertically) + .padding(12.dp, 0.dp), + text = stringResource(id = R.string.sleep_timer) + ) + Text( + modifier = Modifier.align(Alignment.CenterVertically), + text = timerText + ) + IconButton( + modifier = Modifier + .align(Alignment.CenterVertically) + .padding(8.dp), + onClick = onCloseClick, + ) { + Icon( + painter = painterResource(id = R.drawable.ic_cross_vector), + contentDescription = stringResource(id = R.string.close) + ) + } + } +} + +@Composable +@MyDevices +internal fun SleepTimerPreview() { + AppThemeSurface { + SleepTimer( + timerText = "00:00", + onCloseClick = {} + ) + } +}