diff --git a/core/common/overlays/src/main/java/com/buzbuz/smartautoclicker/core/common/overlays/manager/OverlayManager.kt b/core/common/overlays/src/main/java/com/buzbuz/smartautoclicker/core/common/overlays/manager/OverlayManager.kt index b8eefa5ed..9da3cd549 100644 --- a/core/common/overlays/src/main/java/com/buzbuz/smartautoclicker/core/common/overlays/manager/OverlayManager.kt +++ b/core/common/overlays/src/main/java/com/buzbuz/smartautoclicker/core/common/overlays/manager/OverlayManager.kt @@ -107,9 +107,9 @@ class OverlayManager @Inject internal constructor( } /** Destroys all overlays in the backstack except the root one. */ - fun navigateUpToRoot(context: Context, completionListener: () -> Unit) { + fun navigateUpToRoot(context: Context, completionListener: (() -> Unit)? = null) { if (overlayBackStack.size <= 1) { - completionListener() + completionListener?.invoke() return } diff --git a/core/common/ui/src/main/res/drawable/ic_badge_error.xml b/core/common/ui/src/main/res/drawable/ic_badge_error.xml index 06839b5c3..3583f805a 100644 --- a/core/common/ui/src/main/res/drawable/ic_badge_error.xml +++ b/core/common/ui/src/main/res/drawable/ic_badge_error.xml @@ -1,10 +1,11 @@ + android:shape="oval" + android:tint="?attr/colorError"> + android:color="@color/md_theme_light_error"/> Unit, + onRecordingStopped: (() -> Unit)?, ) { if (_state.value != DetectorState.CREATED) { Log.w(TAG, "startScreenRecord: Screen record is already started") @@ -140,7 +140,7 @@ class DetectorEngine @Inject constructor( startProjection(context, resultCode, data) { Log.i(TAG, "projection lost") this@DetectorEngine.stopScreenRecord() - onRecordingStopped() + onRecordingStopped?.invoke() } startScreenRecord(context, displayConfigManager.displayConfig.sizePx) } diff --git a/core/smart/processing/src/main/java/com/buzbuz/smartautoclicker/core/processing/domain/DetectionRepository.kt b/core/smart/processing/src/main/java/com/buzbuz/smartautoclicker/core/processing/domain/DetectionRepository.kt index b4820fcad..49ae953fa 100644 --- a/core/smart/processing/src/main/java/com/buzbuz/smartautoclicker/core/processing/domain/DetectionRepository.kt +++ b/core/smart/processing/src/main/java/com/buzbuz/smartautoclicker/core/processing/domain/DetectionRepository.kt @@ -73,6 +73,11 @@ class DetectionRepository @Inject constructor( private val coroutineScopeIo: CoroutineScope = CoroutineScope(SupervisorJob() + ioDispatcher) + /** Interacts with the OS to execute the actions */ + private var actionExecutor: SmartActionExecutor? = null + + private var projectionErrorHandler: (() -> Unit)? = null + /** Stop the detection automatically after selected delay */ private var autoStopJob: Job? = null @@ -105,19 +110,23 @@ class DetectionRepository @Inject constructor( _scenarioId.value = identifier } + fun setExecutor(androidExecutor: SmartActionExecutor) { + actionExecutor = androidExecutor + } + + fun setProjectionErrorHandler(handler: () -> Unit) { + projectionErrorHandler = handler + } + fun getScenarioId(): Identifier? = _scenarioId.value fun isRunning(): Boolean = detectorEngine.state.value == DetectorState.DETECTING - fun startScreenRecord( - context: Context, - resultCode: Int, - data: Intent, - androidExecutor: SmartActionExecutor, - onProjectionLost: () -> Unit, - ) { - detectorEngine.startScreenRecord(context, resultCode, data, androidExecutor, onProjectionLost) + fun startScreenRecord(context: Context, resultCode: Int, data: Intent) { + actionExecutor?.let { executor -> + detectorEngine.startScreenRecord(context, resultCode, data, executor, projectionErrorHandler) + } } suspend fun startDetection(context: Context, progressListener: ScenarioProcessingListener?, autoStopDuration: Duration? = null) { @@ -151,11 +160,14 @@ class DetectionRepository @Inject constructor( } fun stopScreenRecord() { + projectionErrorHandler = null + detectorEngine.apply { stopScreenRecord() clear() } + actionExecutor = null _scenarioId.value = null } diff --git a/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/MainMenu.kt b/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/MainMenu.kt index 121ded172..d59449632 100644 --- a/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/MainMenu.kt +++ b/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/MainMenu.kt @@ -36,6 +36,7 @@ import com.buzbuz.smartautoclicker.core.ui.utils.getDynamicColorsContext import com.buzbuz.smartautoclicker.feature.smart.config.R import com.buzbuz.smartautoclicker.feature.smart.config.databinding.OverlayMenuBinding import com.buzbuz.smartautoclicker.feature.smart.config.di.ScenarioConfigViewModelsEntryPoint +import com.buzbuz.smartautoclicker.feature.smart.config.ui.common.starters.newRestartMediaProjectionStarterOverlay import com.buzbuz.smartautoclicker.feature.smart.config.ui.scenario.ScenarioDialog import com.buzbuz.smartautoclicker.feature.smart.debugging.di.DebuggingViewModelsEntryPoint import com.buzbuz.smartautoclicker.feature.smart.debugging.ui.overlay.DebugModel @@ -117,7 +118,8 @@ class MainMenu(private val onStopClicked: () -> Unit) : OverlayMenu() { lifecycleScope.launch { repeatOnLifecycle(Lifecycle.State.STARTED) { - launch { viewModel.canStartScenario.collect(::updatePlayPauseButtonEnabledState) } + launch { viewModel.isStartButtonEnabled.collect(::updatePlayPauseButtonEnabledState) } + launch { viewModel.isMediaProjectionStarted.collect(::updateProjectionErrorBadge) } launch { viewModel.detectionState.collect(::updateDetectionState) } launch { viewModel.nativeLibError.collect(::showNativeLibErrorDialogIfNeeded) } launch { debuggingViewModel.isDebugging.collect(::updateDebugOverlayViewVisibility) } @@ -168,11 +170,7 @@ class MainMenu(private val onStopClicked: () -> Unit) : OverlayMenu() { override fun onMenuItemClicked(viewId: Int) { when (viewId) { R.id.btn_play -> onPlayPauseClicked() - R.id.btn_click_list -> { - viewModel.startScenarioEdition { - showScenarioConfigDialog() - } - } + R.id.btn_click_list -> onConfigureClicked() R.id.btn_stop -> onStopClicked() } } @@ -185,7 +183,28 @@ class MainMenu(private val onStopClicked: () -> Unit) : OverlayMenu() { ) } + fun onMediaProjectionLost() { + overlayManager.navigateUpToRoot(context) + viewModel.cancelScenarioChanges() + } + + private fun onConfigureClicked() { + if (viewModel.shouldRestartMediaProjection()) { + showRestartMediaProjectionScreen() + return + } + + viewModel.startScenarioEdition { + showScenarioConfigDialog() + } + } + private fun onPlayPauseClicked() { + if (viewModel.shouldRestartMediaProjection()) { + showRestartMediaProjectionScreen() + return + } + if (viewModel.shouldShowStopVolumeDownTutorialDialog()) { showStopVolumeDownTutorialDialog() return @@ -261,6 +280,10 @@ class MainMenu(private val onStopClicked: () -> Unit) : OverlayMenu() { } } + private fun updateProjectionErrorBadge(isProjectionStarted: Boolean) { + viewBinding.errorBadge.visibility = if (isProjectionStarted) View.GONE else View.VISIBLE + } + /** * Observe the values for the debug and update the debug views. * @return the coroutine job for the observable. Can be cancelled to stop the observation. @@ -323,4 +346,12 @@ class MainMenu(private val onStopClicked: () -> Unit) : OverlayMenu() { .create() .showAsOverlay() } + + private fun showRestartMediaProjectionScreen() { + overlayManager.navigateTo( + context = context, + newOverlay = newRestartMediaProjectionStarterOverlay(context), + hideCurrent = true, + ) + } } \ No newline at end of file diff --git a/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/MainMenuModel.kt b/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/MainMenuModel.kt index 34ea55b66..dbe82dbe8 100644 --- a/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/MainMenuModel.kt +++ b/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/MainMenuModel.kt @@ -83,11 +83,18 @@ class MainMenuModel @Inject constructor( UiState.Idle, ) + val isMediaProjectionStarted: StateFlow = detectionRepository.detectionState + .map { it == DetectionState.RECORDING || it == DetectionState.DETECTING } + .stateIn(viewModelScope, SharingStarted.Eagerly, true) + /** Tells if the scenario can be started. Edited scenario must be synchronized and engine should allow it. */ - val canStartScenario: Flow = detectionRepository.canStartDetection - .combine(editionRepository.isEditionSynchronized) { canStartDetection, isSynchronized -> - canStartDetection && isSynchronized - } + val isStartButtonEnabled: Flow = combine( + detectionRepository.canStartDetection, + editionRepository.isEditionSynchronized, + isMediaProjectionStarted + ) { canStartDetection, isSynchronized, isProjectionStarted -> + (canStartDetection || !isProjectionStarted) && isSynchronized + } /** Tells if the detector can't work due to a native library load error. */ val nativeLibError: Flow = detectionRepository.detectionState @@ -184,6 +191,9 @@ class MainMenuModel @Inject constructor( } } + fun shouldRestartMediaProjection(): Boolean = + !isMediaProjectionStarted.value + fun shouldShowStopVolumeDownTutorialDialog(): Boolean = detectionState.value == UiState.Idle && tutorialRepository.shouldShowStopWithVolumeDownTutorialDialog() diff --git a/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/common/starters/RestartMediaProjectionActivity.kt b/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/common/starters/RestartMediaProjectionActivity.kt index ea600a5c6..826815758 100644 --- a/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/common/starters/RestartMediaProjectionActivity.kt +++ b/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/common/starters/RestartMediaProjectionActivity.kt @@ -17,7 +17,6 @@ package com.buzbuz.smartautoclicker.feature.smart.config.ui.common.starters import android.content.Context -import android.content.DialogInterface import android.content.Intent import android.os.Bundle import android.util.Log @@ -29,24 +28,28 @@ import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AppCompatActivity import com.buzbuz.smartautoclicker.core.base.extensions.showAsOverlay +import com.buzbuz.smartautoclicker.core.common.overlays.manager.OverlayManager import com.buzbuz.smartautoclicker.core.display.recorder.showMediaProjectionWarning import com.buzbuz.smartautoclicker.feature.smart.config.R import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint +import javax.inject.Inject @AndroidEntryPoint -class RequestMediaProjectionActivity : AppCompatActivity() { +class RestartMediaProjectionActivity : AppCompatActivity() { companion object { fun getStartIntent(context: Context): Intent = - Intent(context, RequestMediaProjectionActivity::class.java) + Intent(context, RestartMediaProjectionActivity::class.java) .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK) } - private val viewModel: MediaProjectionLostViewModel by viewModels() + private val viewModel: RestartMediaProjectionViewModel by viewModels() + + @Inject lateinit var overlayManager: OverlayManager /** The result launcher for the projection permission dialog. */ private lateinit var projectionActivityResult: ActivityResultLauncher @@ -54,41 +57,41 @@ class RequestMediaProjectionActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - setContentView(R.layout.activity_media_projection_lost) + setContentView(R.layout.activity_transparent) + overlayManager.hideAll() projectionActivityResult = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> - if (result.resultCode != RESULT_OK) { - finish() + val data = result.data + if (data == null || result.resultCode != RESULT_OK) { + finishActivity() return@registerForActivityResult } Log.i(TAG, "Media projection us running, start scenario") + viewModel.restartScreenRecord(this, result.resultCode, data) - viewModel.startSmartScenario(result.resultCode, result.data!!) - dialog?.dismiss() - finish() + finishActivity() } dialog = showProjectionLostDialog() } - override fun onStop() { - super.onStop() - dialog?.dismiss() - } - - private fun showProjectionLostDialog(): AlertDialog { - return MaterialAlertDialogBuilder(this) + private fun showProjectionLostDialog() = + MaterialAlertDialogBuilder(this) .setTitle(R.string.dialog_overlay_title_warning) .setMessage(R.string.message_error_media_projection_lost) - .setPositiveButton(R.string.yes) { _: DialogInterface, _: Int -> - projectionActivityResult.showMediaProjectionWarning(this) { finish() } - } - .setNegativeButton(R.string.no) { _: DialogInterface, _: Int -> - viewModel.stopApp() + .setPositiveButton(R.string.yes) { _, _ -> + projectionActivityResult.showMediaProjectionWarning(this) { finishActivity() } } + .setNegativeButton(R.string.no) { _, _ -> finishActivity() } .create().also { it.showAsOverlay() } + + private fun finishActivity() { + dialog?.dismiss() + overlayManager.restoreVisibility() + overlayManager.navigateUp(this) + finish() } } diff --git a/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/common/starters/RestartMediaProjectionViewModel.kt b/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/common/starters/RestartMediaProjectionViewModel.kt index 0b3b1abac..678b0d51e 100644 --- a/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/common/starters/RestartMediaProjectionViewModel.kt +++ b/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/common/starters/RestartMediaProjectionViewModel.kt @@ -1,2 +1,46 @@ -package com.buzbuz.smartautoclicker.feature.smart.config.ui.common.starters +/* + * Copyright (C) 2024 Kevin Buzeau + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.buzbuz.smartautoclicker.feature.smart.config.ui.common.starters +import android.content.Context +import android.content.Intent +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope + +import com.buzbuz.smartautoclicker.core.base.di.Dispatcher +import com.buzbuz.smartautoclicker.core.base.di.HiltCoroutineDispatchers +import com.buzbuz.smartautoclicker.core.processing.domain.DetectionRepository + +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.launch +import javax.inject.Inject + + +@HiltViewModel +class RestartMediaProjectionViewModel @Inject constructor( + @Dispatcher(HiltCoroutineDispatchers.IO) private val ioDispatcher: CoroutineDispatcher, + private val detectionRepository: DetectionRepository, +) : ViewModel() { + + fun restartScreenRecord(context: Context, resultCode: Int, data: Intent) { + viewModelScope.launch(ioDispatcher) { + detectionRepository.startScreenRecord(context, resultCode, data) + } + } + +} \ No newline at end of file diff --git a/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/common/starters/StartersOverlays.kt b/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/common/starters/StartersOverlays.kt index dcd1ebf79..c3bf505e8 100644 --- a/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/common/starters/StartersOverlays.kt +++ b/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/common/starters/StartersOverlays.kt @@ -32,6 +32,10 @@ internal fun newWebBrowserStarterOverlay(uri: Uri) = ActivityStarterOverlayMenu( fallbackIntent = getOpenWebBrowserPickerIntent(uri), ) +internal fun newRestartMediaProjectionStarterOverlay(context: Context) = ActivityStarterOverlayMenu( + intent = RestartMediaProjectionActivity.getStartIntent(context) +) + internal fun newNotificationPermissionStarterOverlay(context: Context) = ActivityStarterOverlayMenu( intent = RequestNotificationPermissionActivity.getStartIntent(context) ) diff --git a/feature/smart-config/src/main/res/layout/overlay_menu.xml b/feature/smart-config/src/main/res/layout/overlay_menu.xml index c2838cbd4..31552eddf 100644 --- a/feature/smart-config/src/main/res/layout/overlay_menu.xml +++ b/feature/smart-config/src/main/res/layout/overlay_menu.xml @@ -34,6 +34,20 @@ android:layout_height="wrap_content" android:animateLayoutChanges="true"> + + Ouvrir les paramètres Le comportement des notifications dépend du système d\'exploitation de votre appareil. Vous pouvez configurer le traitement des notifications dans les paramètres de votre appareil. + + + L\'enregistrement de l\'écran s\'est arrêté. Klick\'r en a besoin + afin de pouvoir détecter sur votre écran. Voulez vous relancer l\'enregistrement? + + La registrazione dello schermo è stata interrotta. Klick\'r lo richiede per poterlo rilevare correttamente. + Si desidera riavviare la registrazione? + + + A gravação da tela foi interrompida. + O Klick\'r precisa disso para detectar corretamente. Deseja reiniciar a gravação? + diff --git a/feature/smart-config/src/main/res/values-zh/strings.xml b/feature/smart-config/src/main/res/values-zh/strings.xml index 4e4b892a3..e5f510bea 100644 --- a/feature/smart-config/src/main/res/values-zh/strings.xml +++ b/feature/smart-config/src/main/res/values-zh/strings.xml @@ -308,6 +308,11 @@ 通知行为取决于设备操作系统。您可以在设备设置中配置如何处理通知。 + + + + 屏幕录制已经停止。Klick\'r 需要它才能正确检测。您想重新开始录制吗? + + + + The screen recording have been stopped. Klick\'r requires it + in order to detect correctly. Would you like to restart the recording? + diff --git a/smartautoclicker/src/main/AndroidManifest.xml b/smartautoclicker/src/main/AndroidManifest.xml index c4056f511..7d7aac695 100644 --- a/smartautoclicker/src/main/AndroidManifest.xml +++ b/smartautoclicker/src/main/AndroidManifest.xml @@ -45,13 +45,6 @@ - - . - */ -package com.buzbuz.smartautoclicker.projection - -import android.content.Context -import android.content.DialogInterface -import android.content.Intent -import android.os.Bundle -import android.util.Log - -import androidx.activity.result.ActivityResultLauncher -import androidx.activity.result.contract.ActivityResultContracts -import androidx.activity.viewModels -import androidx.appcompat.app.AlertDialog -import androidx.appcompat.app.AppCompatActivity - -import com.buzbuz.smartautoclicker.R -import com.buzbuz.smartautoclicker.core.base.extensions.showAsOverlay -import com.buzbuz.smartautoclicker.core.display.recorder.showMediaProjectionWarning - -import com.google.android.material.dialog.MaterialAlertDialogBuilder -import dagger.hilt.android.AndroidEntryPoint - - -@AndroidEntryPoint -class MediaProjectionLostActivity : AppCompatActivity() { - - companion object { - - fun getStartIntent(context: Context): Intent = - Intent(context, MediaProjectionLostActivity::class.java) - .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK) - } - - private val viewModel: MediaProjectionLostViewModel by viewModels() - - /** The result launcher for the projection permission dialog. */ - private lateinit var projectionActivityResult: ActivityResultLauncher - private var dialog: AlertDialog? = null - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContentView(R.layout.activity_media_projection_lost) - - projectionActivityResult = - registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> - if (result.resultCode != RESULT_OK) { - finish() - return@registerForActivityResult - } - - Log.i(TAG, "Media projection us running, start scenario") - - viewModel.startSmartScenario(result.resultCode, result.data!!) - dialog?.dismiss() - finish() - } - - dialog = showProjectionLostDialog() - } - - override fun onStop() { - super.onStop() - dialog?.dismiss() - } - - private fun showProjectionLostDialog(): AlertDialog { - return MaterialAlertDialogBuilder(this) - .setTitle(R.string.dialog_overlay_title_warning) - .setMessage(R.string.message_error_media_projection_lost) - .setPositiveButton(R.string.yes) { _: DialogInterface, _: Int -> - projectionActivityResult.showMediaProjectionWarning(this) { finish() } - } - .setNegativeButton(R.string.no) { _: DialogInterface, _: Int -> - viewModel.stopApp() - } - .create().also { it.showAsOverlay() } - } -} - -private const val TAG = "MediaProjectionLostActivity" \ No newline at end of file diff --git a/smartautoclicker/src/main/java/com/buzbuz/smartautoclicker/projection/MediaProjectionLostViewModel.kt b/smartautoclicker/src/main/java/com/buzbuz/smartautoclicker/projection/MediaProjectionLostViewModel.kt deleted file mode 100644 index 36beccc47..000000000 --- a/smartautoclicker/src/main/java/com/buzbuz/smartautoclicker/projection/MediaProjectionLostViewModel.kt +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2024 Kevin Buzeau - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.buzbuz.smartautoclicker.projection - -import android.content.Intent -import android.util.Log -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope - -import com.buzbuz.smartautoclicker.SmartAutoClickerService -import com.buzbuz.smartautoclicker.core.base.di.Dispatcher -import com.buzbuz.smartautoclicker.core.base.di.HiltCoroutineDispatchers.IO -import com.buzbuz.smartautoclicker.localservice.ILocalService - -import dagger.hilt.android.lifecycle.HiltViewModel - -import kotlinx.coroutines.CoroutineDispatcher -import kotlinx.coroutines.launch -import javax.inject.Inject - -@HiltViewModel -class MediaProjectionLostViewModel @Inject constructor( - @Dispatcher(IO) private val ioDispatcher: CoroutineDispatcher, -) : ViewModel() { - - /** Callback upon the availability of the [SmartAutoClickerService]. */ - private val serviceConnection: (ILocalService?) -> Unit = { localService -> - clickerService = localService - } - - /** - * Reference on the [SmartAutoClickerService]. - * Will be not null only if the Accessibility Service is enabled. - */ - private var clickerService: ILocalService? = null - - init { - SmartAutoClickerService.getLocalService(serviceConnection) - } - - override fun onCleared() { - SmartAutoClickerService.getLocalService(null) - super.onCleared() - } - - fun startSmartScenario(resultCode: Int, data: Intent) { - val service = clickerService ?: let { - Log.e(TAG, "Can't start smart scenario, Service is not started") - return - } - - viewModelScope.launch(ioDispatcher) { - service.retryStartSmartScenario(resultCode, data) - } - } - - fun stopApp() { - val service = clickerService ?: let { - Log.e(TAG, "Can't stop, Service is not started") - return - } - - service.stop() - } -} - -private const val TAG = "MediaProjectionLostViewModel" \ No newline at end of file diff --git a/smartautoclicker/src/main/res/values-fr/strings.xml b/smartautoclicker/src/main/res/values-fr/strings.xml index 7fcf8f756..014419e46 100644 --- a/smartautoclicker/src/main/res/values-fr/strings.xml +++ b/smartautoclicker/src/main/res/values-fr/strings.xml @@ -81,8 +81,7 @@ Le scénario %1$s va être supprimé. Êtes vous sûr ? Votre appareil ne donne pas la possibilité à Klick\'r de pouvoir enregistrer votre écran. L\'application ne pourra pas fonctionner dessus. - L\'enregistrement de l\'écran s\'est arrêté. Klick\'r en a besoin - afin de pouvoir détecter sur votre écran. Voulez vous relancer l\'enregistrement? + 是否删除场景: %1$s ? 您的设备不提供标准的 Android 屏幕捕获权限对话框。 Klick\'r 将无法在其上运行。 - 屏幕录制已经停止。Klick\'r 需要它才能正确检测。您想重新开始录制吗?