Skip to content

Commit 7f739c8

Browse files
authored
Merge pull request #213 from esensar/compose-migration
Migrate application to compose
2 parents 899d616 + 9fea2bc commit 7f739c8

File tree

80 files changed

+2028
-1521
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

80 files changed

+2028
-1521
lines changed

app/build.gradle.kts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@ android {
4343
buildFeatures {
4444
viewBinding = true
4545
buildConfig = true
46+
compose = true
47+
}
48+
49+
composeOptions {
50+
kotlinCompilerExtensionVersion = libs.versions.composeCompiler.get()
4651
}
4752

4853
buildTypes {
@@ -80,6 +85,13 @@ android {
8085

8186
tasks.withType<KotlinCompile> {
8287
kotlinOptions.jvmTarget = project.libs.versions.app.build.kotlinJVMTarget.get()
88+
kotlinOptions.freeCompilerArgs = listOf(
89+
"-opt-in=kotlin.RequiresOptIn",
90+
"-opt-in=androidx.compose.material3.ExperimentalMaterial3Api",
91+
"-opt-in=androidx.compose.material.ExperimentalMaterialApi",
92+
"-opt-in=androidx.compose.foundation.ExperimentalFoundationApi",
93+
"-Xcontext-receivers"
94+
)
8395
}
8496

8597
namespace = libs.versions.app.version.appId.get()
@@ -93,6 +105,7 @@ android {
93105
dependencies {
94106
implementation(libs.simple.tools.commons)
95107

96-
implementation(libs.androidx.constraintlayout)
97-
implementation(libs.eventbus)
108+
implementation(libs.bundles.lifecycle)
109+
implementation(libs.bundles.compose)
110+
debugImplementation(libs.bundles.compose.preview)
98111
}

app/proguard-rules.pro

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +0,0 @@
1-
# EventBus
2-
-keepattributes *Annotation*
3-
-keepclassmembers class ** {
4-
@org.greenrobot.eventbus.Subscribe <methods>;
5-
}
6-
-keep enum org.greenrobot.eventbus.ThreadMode { *; }
Lines changed: 110 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,102 @@
11
package com.simplemobiletools.flashlight.activities
22

3+
import android.app.Application
34
import android.content.pm.ActivityInfo
4-
import android.graphics.drawable.ColorDrawable
55
import android.os.Bundle
66
import android.view.WindowManager
7-
import android.widget.RelativeLayout
8-
import com.simplemobiletools.commons.dialogs.ColorPickerDialog
9-
import com.simplemobiletools.commons.extensions.*
10-
import com.simplemobiletools.flashlight.databinding.ActivityBrightDisplayBinding
7+
import androidx.activity.ComponentActivity
8+
import androidx.activity.compose.setContent
9+
import androidx.activity.viewModels
10+
import androidx.annotation.ColorInt
11+
import androidx.compose.runtime.Composable
12+
import androidx.compose.runtime.derivedStateOf
13+
import androidx.compose.runtime.getValue
14+
import androidx.compose.runtime.remember
15+
import androidx.lifecycle.AndroidViewModel
16+
import androidx.lifecycle.compose.collectAsStateWithLifecycle
17+
import androidx.lifecycle.viewModelScope
18+
import com.simplemobiletools.commons.compose.alert_dialog.rememberAlertDialogState
19+
import com.simplemobiletools.commons.compose.extensions.enableEdgeToEdgeSimple
20+
import com.simplemobiletools.commons.compose.extensions.setShowWhenLockedCompat
21+
import com.simplemobiletools.commons.compose.extensions.setTurnScreenOnCompat
22+
import com.simplemobiletools.commons.compose.theme.AppThemeSurface
23+
import com.simplemobiletools.commons.dialogs.ColorPickerAlertDialog
24+
import com.simplemobiletools.commons.extensions.getContrastColor
25+
import com.simplemobiletools.commons.extensions.getFormattedDuration
1126
import com.simplemobiletools.flashlight.extensions.config
27+
import com.simplemobiletools.flashlight.helpers.SleepTimer
1228
import com.simplemobiletools.flashlight.helpers.stopSleepTimerCountDown
13-
import com.simplemobiletools.flashlight.models.Events
14-
import org.greenrobot.eventbus.EventBus
15-
import org.greenrobot.eventbus.Subscribe
16-
import org.greenrobot.eventbus.ThreadMode
29+
import com.simplemobiletools.flashlight.screens.BrightDisplayScreen
30+
import com.simplemobiletools.flashlight.views.AnimatedSleepTimer
31+
import kotlinx.coroutines.flow.MutableStateFlow
32+
import kotlinx.coroutines.flow.asStateFlow
33+
import kotlinx.coroutines.flow.launchIn
34+
import kotlinx.coroutines.flow.onEach
1735
import kotlin.system.exitProcess
1836

19-
class BrightDisplayActivity : SimpleActivity() {
20-
private val binding by viewBinding(ActivityBrightDisplayBinding::inflate)
37+
class BrightDisplayActivity : ComponentActivity() {
38+
private val viewModel by viewModels<BrightDisplayViewModel>()
39+
private val preferences by lazy { config }
2140

2241
override fun onCreate(savedInstanceState: Bundle?) {
23-
window.addFlags(
24-
WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD or
25-
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or
26-
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON or
27-
WindowManager.LayoutParams.FLAG_FULLSCREEN
28-
)
29-
30-
useDynamicTheme = false
42+
setShowWhenLockedCompat(true)
43+
setTurnScreenOnCompat(true)
3144
super.onCreate(savedInstanceState)
32-
setContentView(binding.root)
33-
supportActionBar?.hide()
34-
setBackgroundColor(config.brightDisplayColor)
35-
36-
binding.brightDisplayChangeColor.setOnClickListener {
37-
ColorPickerDialog(this, config.brightDisplayColor, true, currentColorCallback = {
38-
setBackgroundColor(it)
39-
}) { wasPositivePressed, color ->
40-
if (wasPositivePressed) {
41-
config.brightDisplayColor = color
42-
43-
val contrastColor = color.getContrastColor()
44-
binding.brightDisplayChangeColor.apply {
45-
setTextColor(contrastColor)
46-
background.applyColorFilter(contrastColor)
45+
enableEdgeToEdgeSimple()
46+
setContent {
47+
AppThemeSurface {
48+
val brightDisplayColor by preferences.brightDisplayColorFlow.collectAsStateWithLifecycle(preferences.brightDisplayColor)
49+
val colorPickerDialogState = getColorPickerDialogState(brightDisplayColor)
50+
51+
ScreenContent(colorPickerDialogState::show)
52+
}
53+
}
54+
}
55+
56+
@Composable
57+
private fun getColorPickerDialogState(
58+
@ColorInt
59+
brightDisplayColor: Int
60+
) = rememberAlertDialogState().apply {
61+
DialogMember {
62+
ColorPickerAlertDialog(
63+
alertDialogState = this,
64+
color = brightDisplayColor,
65+
removeDimmedBackground = true,
66+
onActiveColorChange = viewModel::updateBackgroundColor,
67+
onButtonPressed = { wasPositivePressed, color ->
68+
if (wasPositivePressed) {
69+
config.brightDisplayColor = color
70+
viewModel.updateBackgroundColor(color)
71+
} else {
72+
viewModel.updateBackgroundColor(config.brightDisplayColor)
4773
}
48-
} else {
49-
setBackgroundColor(config.brightDisplayColor)
5074
}
51-
}
75+
)
5276
}
77+
}
5378

54-
binding.sleepTimerStop.setOnClickListener { stopSleepTimer() }
79+
@Composable
80+
private fun ScreenContent(onChangeColorButtonPress: () -> Unit) {
81+
val backgroundColor by viewModel.backgroundColor.collectAsStateWithLifecycle()
82+
val contrastColor by remember { derivedStateOf { backgroundColor.getContrastColor() } }
83+
val timerVisible by viewModel.timerVisible.collectAsStateWithLifecycle()
84+
val timerText by viewModel.timerText.collectAsStateWithLifecycle()
85+
BrightDisplayScreen(
86+
backgroundColor = backgroundColor,
87+
contrastColor = contrastColor,
88+
onChangeColorPress = onChangeColorButtonPress,
89+
sleepTimer = {
90+
AnimatedSleepTimer(timerText = timerText, timerVisible = timerVisible, onTimerClosePress = ::stopSleepTimer)
91+
}
92+
)
5593
}
5694

5795
override fun onResume() {
5896
super.onResume()
5997
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
6098
toggleBrightness(true)
6199
requestedOrientation = if (config.forcePortraitMode) ActivityInfo.SCREEN_ORIENTATION_PORTRAIT else ActivityInfo.SCREEN_ORIENTATION_SENSOR
62-
63-
(binding.sleepTimerHolder.layoutParams as RelativeLayout.LayoutParams).bottomMargin = navigationBarHeight
64100
}
65101

66102
override fun onPause() {
@@ -69,46 +105,51 @@ class BrightDisplayActivity : SimpleActivity() {
69105
toggleBrightness(false)
70106
}
71107

72-
override fun onStart() {
73-
super.onStart()
74-
EventBus.getDefault().register(this)
75-
}
76-
77-
override fun onStop() {
78-
super.onStop()
79-
EventBus.getDefault().unregister(this)
80-
}
81-
82-
private fun setBackgroundColor(color: Int) {
83-
binding.apply {
84-
brightDisplay.background = ColorDrawable(color)
85-
86-
val contrastColor = config.brightDisplayColor.getContrastColor()
87-
brightDisplayChangeColor.apply {
88-
setTextColor(contrastColor)
89-
background.applyColorFilter(contrastColor)
90-
}
91-
}
92-
}
93-
94108
private fun toggleBrightness(increase: Boolean) {
95109
val layout = window.attributes
96110
layout.screenBrightness = (if (increase) 1 else 0).toFloat()
97111
window.attributes = layout
98112
}
99113

100114
private fun stopSleepTimer() {
101-
binding.sleepTimerHolder.fadeOut()
115+
viewModel.hideTimer()
102116
stopSleepTimerCountDown()
103117
}
104118

105-
@Subscribe(threadMode = ThreadMode.MAIN)
106-
fun sleepTimerChanged(event: Events.SleepTimerChanged) {
107-
binding.sleepTimerValue.text = event.seconds.getFormattedDuration()
108-
binding.sleepTimerHolder.beVisible()
109119

110-
if (event.seconds == 0) {
111-
exitProcess(0)
120+
internal class BrightDisplayViewModel(
121+
application: Application
122+
) : AndroidViewModel(application) {
123+
124+
125+
private val _timerText: MutableStateFlow<String> = MutableStateFlow("00:00")
126+
val timerText = _timerText.asStateFlow()
127+
128+
private val _timerVisible: MutableStateFlow<Boolean> = MutableStateFlow(false)
129+
val timerVisible = _timerVisible.asStateFlow()
130+
131+
private val _backgroundColor: MutableStateFlow<Int> = MutableStateFlow(application.config.brightDisplayColor)
132+
val backgroundColor = _backgroundColor.asStateFlow()
133+
134+
init {
135+
SleepTimer.timeLeft
136+
.onEach { seconds ->
137+
_timerText.value = seconds.getFormattedDuration()
138+
_timerVisible.value = true
139+
140+
if (seconds == 0) {
141+
exitProcess(0)
142+
}
143+
}
144+
.launchIn(viewModelScope)
145+
}
146+
147+
fun updateBackgroundColor(color: Int) {
148+
_backgroundColor.value = color
149+
}
150+
151+
fun hideTimer() {
152+
_timerVisible.value = false
112153
}
113154
}
114155
}

0 commit comments

Comments
 (0)