@@ -23,22 +23,29 @@ import android.view.KeyEvent
23
23
24
24
import com.buzbuz.smartautoclicker.core.base.AndroidExecutor
25
25
import com.buzbuz.smartautoclicker.core.bitmaps.IBitmapManager
26
+ import com.buzbuz.smartautoclicker.core.common.overlays.manager.OverlayManager
26
27
import com.buzbuz.smartautoclicker.core.display.DisplayMetrics
27
28
import com.buzbuz.smartautoclicker.core.domain.model.scenario.Scenario
28
29
import com.buzbuz.smartautoclicker.core.dumb.domain.model.DumbScenario
29
30
import com.buzbuz.smartautoclicker.core.dumb.engine.DumbEngine
30
31
import com.buzbuz.smartautoclicker.core.processing.domain.DetectionRepository
31
- import com.buzbuz.smartautoclicker.core.common.overlays.manager.OverlayManager
32
+ import com.buzbuz.smartautoclicker.core.processing.domain.DetectionState
32
33
import com.buzbuz.smartautoclicker.feature.smart.config.ui.MainMenu
33
34
import com.buzbuz.smartautoclicker.feature.dumb.config.ui.DumbMainMenu
34
35
import com.buzbuz.smartautoclicker.feature.qstile.domain.QSTileRepository
36
+ import com.buzbuz.smartautoclicker.feature.revenue.IRevenueRepository
37
+ import com.buzbuz.smartautoclicker.feature.revenue.UserBillingState
38
+ import com.buzbuz.smartautoclicker.feature.smart.debugging.domain.DebuggingRepository
35
39
36
40
import kotlinx.coroutines.CoroutineScope
37
41
import kotlinx.coroutines.Dispatchers
38
42
import kotlinx.coroutines.Job
39
43
import kotlinx.coroutines.SupervisorJob
40
44
import kotlinx.coroutines.cancel
41
45
import kotlinx.coroutines.delay
46
+ import kotlinx.coroutines.flow.combine
47
+ import kotlinx.coroutines.flow.launchIn
48
+ import kotlinx.coroutines.flow.onEach
42
49
import kotlinx.coroutines.launch
43
50
44
51
class LocalService (
@@ -48,22 +55,44 @@ class LocalService(
48
55
private val detectionRepository : DetectionRepository ,
49
56
private val bitmapManager : IBitmapManager ,
50
57
private val dumbEngine : DumbEngine ,
51
- val tileRepository : QSTileRepository ,
58
+ private val tileRepository : QSTileRepository ,
59
+ private val revenueRepository : IRevenueRepository ,
60
+ private val debugRepository : DebuggingRepository ,
52
61
private val androidExecutor : AndroidExecutor ,
53
62
private val onStart : (isSmart: Boolean , name: String ) -> Unit ,
54
63
private val onStop : () -> Unit ,
64
+ onStateChanged : (isRunning: Boolean , isMenuHidden: Boolean ) -> Unit ,
55
65
) : SmartAutoClickerService.ILocalService {
56
66
57
67
/* * Scope for this LocalService. */
58
68
private val serviceScope: CoroutineScope = CoroutineScope (Dispatchers .Main + SupervisorJob ())
59
69
/* * Coroutine job for the delayed start of engine & ui. */
60
70
private var startJob: Job ? = null
71
+ /* * Coroutine job for the paywall result upon start from notification. */
72
+ private var paywallResultJob: Job ? = null
73
+
74
+ /* * State of this LocalService. */
75
+ private var state: LocalServiceState = LocalServiceState (isStarted = false , isSmartLoaded = false )
61
76
/* * True if the overlay is started, false if not. */
62
- internal var isStarted: Boolean = false
77
+ internal val isStarted: Boolean
78
+ get() = state.isStarted
79
+
80
+ init {
81
+ combine(dumbEngine.isRunning, detectionRepository.detectionState) { dumbIsRunning, smartState ->
82
+ dumbIsRunning || smartState == DetectionState .DETECTING
83
+ }.onEach { onStateChanged(it, overlayManager.isStackHidden()) }.launchIn(serviceScope)
84
+
85
+ overlayManager.onVisibilityChangedListener = {
86
+ onStateChanged(
87
+ dumbEngine.isRunning.value || detectionRepository.isRunning(),
88
+ overlayManager.isStackHidden()
89
+ )
90
+ }
91
+ }
63
92
64
93
override fun startDumbScenario (dumbScenario : DumbScenario ) {
65
- if (isStarted) return
66
- isStarted = true
94
+ if (state. isStarted) return
95
+ state = LocalServiceState ( isStarted = true , isSmartLoaded = false )
67
96
onStart(false , dumbScenario.name)
68
97
69
98
displayMetrics.startMonitoring(context)
@@ -96,7 +125,7 @@ class LocalService(
96
125
*/
97
126
override fun startSmartScenario (resultCode : Int , data : Intent , scenario : Scenario ) {
98
127
if (isStarted) return
99
- isStarted = true
128
+ state = LocalServiceState ( isStarted = true , isSmartLoaded = true )
100
129
onStart(true , scenario.name)
101
130
102
131
displayMetrics.startMonitoring(context)
@@ -123,9 +152,63 @@ class LocalService(
123
152
}
124
153
}
125
154
155
+ override fun playAndHide () {
156
+ serviceScope.launch {
157
+ overlayManager.hideAll()
158
+
159
+ if (state.isSmartLoaded && ! detectionRepository.isRunning()) {
160
+ if (revenueRepository.userBillingState.value == UserBillingState .AD_REQUESTED ) startPaywall()
161
+ else startSmartScenario()
162
+ } else if (! state.isSmartLoaded && ! dumbEngine.isRunning.value) {
163
+ dumbEngine.startDumbScenario()
164
+ }
165
+ }
166
+ }
167
+
168
+ private fun startPaywall () {
169
+ revenueRepository.startPaywallUiFlow(context)
170
+
171
+ paywallResultJob = combine(revenueRepository.isBillingFlowInProgress, revenueRepository.userBillingState) { inProgress, state ->
172
+ if (inProgress) return @combine
173
+
174
+ if (state != UserBillingState .AD_REQUESTED ) startSmartScenario()
175
+ paywallResultJob?.cancel()
176
+ paywallResultJob = null
177
+ }.launchIn(serviceScope)
178
+ }
179
+
180
+ private fun startSmartScenario () {
181
+ serviceScope.launch {
182
+ detectionRepository.startDetection(
183
+ context,
184
+ debugRepository.getDebugDetectionListenerIfNeeded(context),
185
+ revenueRepository.consumeTrial(),
186
+ )
187
+ }
188
+ }
189
+
190
+ override fun pauseAndShow () {
191
+ serviceScope.launch {
192
+ when {
193
+ dumbEngine.isRunning.value -> dumbEngine.stopDumbScenario()
194
+ detectionRepository.isRunning() -> detectionRepository.stopDetection()
195
+ }
196
+
197
+ overlayManager.restoreVisibility()
198
+ }
199
+ }
200
+
201
+ override fun hide () {
202
+ overlayManager.hideAll()
203
+ }
204
+
205
+ override fun show () {
206
+ overlayManager.restoreVisibility()
207
+ }
208
+
126
209
override fun stop () {
127
210
if (! isStarted) return
128
- isStarted = false
211
+ state = LocalServiceState ( isStarted = false , isSmartLoaded = false )
129
212
130
213
serviceScope.launch {
131
214
startJob?.join()
@@ -149,14 +232,9 @@ class LocalService(
149
232
event ? : return false
150
233
return overlayManager.propagateKeyEvent(event)
151
234
}
235
+ }
152
236
153
- fun toggleOverlaysVisibility () {
154
- overlayManager.apply {
155
- if (isStackHidden()) {
156
- restoreVisibility()
157
- } else {
158
- hideAll()
159
- }
160
- }
161
- }
162
- }
237
+ private data class LocalServiceState (
238
+ val isStarted : Boolean ,
239
+ val isSmartLoaded : Boolean
240
+ )
0 commit comments