diff --git a/.github/workflows/production.yml b/.github/workflows/production.yml index e76da33f27..4201f2683a 100644 --- a/.github/workflows/production.yml +++ b/.github/workflows/production.yml @@ -18,7 +18,7 @@ jobs: - name: Checkout repository uses: actions/checkout@v3 - - uses: actions/cache@v2 + - uses: actions/cache@v3 with: path: | ~/.gradle/caches @@ -27,10 +27,12 @@ jobs: restore-keys: | ${{ runner.os }}-gradle- - - name: set up JDK 1.17 - uses: actions/setup-java@v1 + - name: set up JDK 17 + uses: actions/setup-java@v3 with: - java-version: 1.17 + distribution: 'oracle' + java-version: 17 + cache: 'gradle' - name: Setup Android SDK uses: android-actions/setup-android@v2 diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml new file mode 100644 index 0000000000..e8f747043d --- /dev/null +++ b/.github/workflows/pull-request.yml @@ -0,0 +1,48 @@ +name: Pull request + +on: + pull_request: + +jobs: + apk: + name: Build APK + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - uses: actions/cache@v3 + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper + key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} + restore-keys: | + ${{ runner.os }}-gradle- + + - name: set up JDK 17 + uses: actions/setup-java@v3 + with: + distribution: 'oracle' + java-version: 17 + cache: 'gradle' + + - name: Setup Android SDK + uses: android-actions/setup-android@v2 + + - name: set up Ruby for fastlane + uses: ruby/setup-ruby@v1 + with: + ruby-version: '2.7' + + - name: Create debug keystore + env: + CI_KEYSTORE: ${{ secrets.CI_KEYSTORE }} + run: | + echo "$CI_KEYSTORE" | base64 --decode > /home/runner/.android/debug.keystore + + - name: Install bundle + run: bundle install + + - name: Build apk with fastlane + run: bundle exec fastlane testing \ No newline at end of file diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index 77d04947f5..57760395d2 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -17,7 +17,7 @@ jobs: - name: Checkout repository uses: actions/checkout@v3 - - uses: actions/cache@v2 + - uses: actions/cache@v3 with: path: | ~/.gradle/caches @@ -32,10 +32,12 @@ jobs: property: VERSION_NUM value: ${{ github.run_number }} - - name: set up JDK 1.17 - uses: actions/setup-java@v1 + - name: set up JDK 17 + uses: actions/setup-java@v3 with: - java-version: 1.17 + distribution: 'oracle' + java-version: 17 + cache: 'gradle' - name: Setup Android SDK uses: android-actions/setup-android@v2 @@ -46,9 +48,10 @@ jobs: ruby-version: '2.7' - name: Create debug keystore + env: + CI_KEYSTORE: ${{ secrets.CI_KEYSTORE }} run: | - echo "${{ secrets.CI_KEYSTORE }}" > debug.keystore.asc - gpg -d --passphrase "${{ secrets.CI_KEYSTORE_DECRYPT }}" --batch debug.keystore.asc > /home/runner/.android/debug.keystore + echo "$CI_KEYSTORE" | base64 --decode > /home/runner/.android/debug.keystore - name: Install bundle run: bundle install diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 8e92cb3974..58af6be2d2 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -19,7 +19,7 @@ - + @@ -58,7 +58,7 @@ - + @@ -102,10 +102,10 @@ @@ -115,8 +115,8 @@ @@ -189,8 +189,8 @@ @@ -202,9 +202,9 @@ @@ -213,9 +213,9 @@ @@ -224,8 +224,8 @@ diff --git a/app/src/main/assets/whats-new.txt b/app/src/main/assets/whats-new.txt index 01d96171f8..4705ea1e0b 100644 --- a/app/src/main/assets/whats-new.txt +++ b/app/src/main/assets/whats-new.txt @@ -1 +1 @@ -Action for doing swipe gestures on the screen with 1 or more fingers. Many thanks to Tino (@pixel-shock) for working on this feature. 😊 \ No newline at end of file +Action for doing pinches and swipes on the screen with 2 or more fingers. Many thanks to Tino (@pixel-shock) for working on this feature. 😊 \ No newline at end of file diff --git a/app/src/main/java/io/github/sds100/keymapper/KeyMapperApp.kt b/app/src/main/java/io/github/sds100/keymapper/KeyMapperApp.kt index 91b80439d7..bf86727341 100644 --- a/app/src/main/java/io/github/sds100/keymapper/KeyMapperApp.kt +++ b/app/src/main/java/io/github/sds100/keymapper/KeyMapperApp.kt @@ -78,18 +78,18 @@ class KeyMapperApp : MultiDexApplication() { val packageManagerAdapter by lazy { AndroidPackageManagerAdapter( - this, + this, appCoroutineScope ) } val inputMethodAdapter by lazy { AndroidInputMethodAdapter( - this, - appCoroutineScope, - accessibilityServiceAdapter, - permissionAdapter, - suAdapter + this, + appCoroutineScope, + accessibilityServiceAdapter, + permissionAdapter, + suAdapter ) } val devicesAdapter by lazy { @@ -103,10 +103,10 @@ class KeyMapperApp : MultiDexApplication() { val cameraAdapter by lazy { AndroidCameraAdapter(this) } val permissionAdapter by lazy { AndroidPermissionAdapter( - this, - appCoroutineScope, - suAdapter, - notificationReceiverAdapter + this, + appCoroutineScope, + suAdapter, + notificationReceiverAdapter ) } @@ -144,18 +144,18 @@ class KeyMapperApp : MultiDexApplication() { val autoGrantPermissionController by lazy { AutoGrantPermissionController( - appCoroutineScope, - permissionAdapter, - popupMessageAdapter, - resourceProvider + appCoroutineScope, + permissionAdapter, + popupMessageAdapter, + resourceProvider ) } private val loggingTree by lazy { KeyMapperLoggingTree( - appCoroutineScope, - ServiceLocator.settingsRepository(this), - ServiceLocator.logRepository(this) + appCoroutineScope, + ServiceLocator.settingsRepository(this), + ServiceLocator.logRepository(this) ) } @@ -167,10 +167,10 @@ class KeyMapperApp : MultiDexApplication() { Thread.setDefaultUncaughtExceptionHandler { thread, exception -> //log in a blocking manner and always log regardless of whether the setting is turned on val entry = LogEntryEntity( - id = 0, - time = Calendar.getInstance().timeInMillis, - severity = LogEntryEntity.SEVERITY_ERROR, - message = exception.stackTraceToString() + id = 0, + time = Calendar.getInstance().timeInMillis, + severity = LogEntryEntity.SEVERITY_ERROR, + message = exception.stackTraceToString() ) runBlocking { @@ -195,8 +195,8 @@ class KeyMapperApp : MultiDexApplication() { else -> AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM } } - .onEach { mode -> AppCompatDelegate.setDefaultNightMode(mode) } - .launchIn(appCoroutineScope) + .onEach { mode -> AppCompatDelegate.setDefaultNightMode(mode) } + .launchIn(appCoroutineScope) if (BuildConfig.BUILD_TYPE == "debug" || BuildConfig.BUILD_TYPE == "debug_release") { Timber.plant(Timber.DebugTree()) @@ -222,14 +222,14 @@ class KeyMapperApp : MultiDexApplication() { ) autoSwitchImeController = AutoSwitchImeController( - appCoroutineScope, - ServiceLocator.settingsRepository(this), - ServiceLocator.inputMethodAdapter(this), - UseCases.pauseMappings(this), - devicesAdapter, - popupMessageAdapter, - resourceProvider, - ServiceLocator.accessibilityServiceAdapter(this) + appCoroutineScope, + ServiceLocator.settingsRepository(this), + ServiceLocator.inputMethodAdapter(this), + UseCases.pauseMappings(this), + devicesAdapter, + popupMessageAdapter, + resourceProvider, + ServiceLocator.accessibilityServiceAdapter(this) ) processLifecycleOwner.lifecycle.addObserver(object : LifecycleObserver { diff --git a/app/src/main/java/io/github/sds100/keymapper/MainActivity.kt b/app/src/main/java/io/github/sds100/keymapper/MainActivity.kt index f9c3919f4f..a99cbc6bb5 100644 --- a/app/src/main/java/io/github/sds100/keymapper/MainActivity.kt +++ b/app/src/main/java/io/github/sds100/keymapper/MainActivity.kt @@ -25,7 +25,7 @@ class MainActivity : AppCompatActivity() { companion object { const val ACTION_SHOW_ACCESSIBILITY_SETTINGS_NOT_FOUND_DIALOG = - "$PACKAGE_NAME.ACTION_SHOW_ACCESSIBILITY_SETTINGS_NOT_FOUND_DIALOG" + "$PACKAGE_NAME.ACTION_SHOW_ACCESSIBILITY_SETTINGS_NOT_FOUND_DIALOG" } private val viewModel by viewModels { @@ -51,14 +51,14 @@ class MainActivity : AppCompatActivity() { requestPermissionDelegate = RequestPermissionDelegate(this, showDialogs = true) ServiceLocator.permissionAdapter(this@MainActivity).request - .flowWithLifecycle(lifecycle, Lifecycle.State.STARTED) - .onEach { permission -> - requestPermissionDelegate.requestPermission( - permission, - findNavController(R.id.container) - ) - } - .launchIn(lifecycleScope) + .flowWithLifecycle(lifecycle, Lifecycle.State.STARTED) + .onEach { permission -> + requestPermissionDelegate.requestPermission( + permission, + findNavController(R.id.container) + ) + } + .launchIn(lifecycleScope) if (intent.action == ACTION_SHOW_ACCESSIBILITY_SETTINGS_NOT_FOUND_DIALOG) { viewModel.onCantFindAccessibilitySettings() diff --git a/app/src/main/java/io/github/sds100/keymapper/ServiceLocator.kt b/app/src/main/java/io/github/sds100/keymapper/ServiceLocator.kt index 3c8ff1b2ab..0abbd88cd5 100755 --- a/app/src/main/java/io/github/sds100/keymapper/ServiceLocator.kt +++ b/app/src/main/java/io/github/sds100/keymapper/ServiceLocator.kt @@ -8,7 +8,11 @@ import io.github.sds100.keymapper.actions.sound.SoundsManagerImpl import io.github.sds100.keymapper.backup.BackupManager import io.github.sds100.keymapper.backup.BackupManagerImpl import io.github.sds100.keymapper.data.db.AppDatabase -import io.github.sds100.keymapper.data.repositories.* +import io.github.sds100.keymapper.data.repositories.PreferenceRepository +import io.github.sds100.keymapper.data.repositories.RoomFingerprintMapRepository +import io.github.sds100.keymapper.data.repositories.RoomKeyMapRepository +import io.github.sds100.keymapper.data.repositories.RoomLogRepository +import io.github.sds100.keymapper.data.repositories.SettingsPreferenceRepository import io.github.sds100.keymapper.logging.LogRepository import io.github.sds100.keymapper.mappings.fingerprintmaps.FingerprintMapRepository import io.github.sds100.keymapper.shizuku.ShizukuAdapter diff --git a/app/src/main/java/io/github/sds100/keymapper/UseCases.kt b/app/src/main/java/io/github/sds100/keymapper/UseCases.kt index 3c49c8a0bf..3c6f773263 100644 --- a/app/src/main/java/io/github/sds100/keymapper/UseCases.kt +++ b/app/src/main/java/io/github/sds100/keymapper/UseCases.kt @@ -13,7 +13,11 @@ import io.github.sds100.keymapper.mappings.DisplaySimpleMappingUseCaseImpl import io.github.sds100.keymapper.mappings.PauseMappingsUseCaseImpl import io.github.sds100.keymapper.mappings.fingerprintmaps.AreFingerprintGesturesSupportedUseCaseImpl import io.github.sds100.keymapper.mappings.fingerprintmaps.DetectFingerprintMapsUseCaseImpl -import io.github.sds100.keymapper.mappings.keymaps.* +import io.github.sds100.keymapper.mappings.keymaps.ConfigKeyMapUseCase +import io.github.sds100.keymapper.mappings.keymaps.ConfigKeyMapUseCaseImpl +import io.github.sds100.keymapper.mappings.keymaps.CreateKeyMapShortcutUseCaseImpl +import io.github.sds100.keymapper.mappings.keymaps.DisplayKeyMapUseCase +import io.github.sds100.keymapper.mappings.keymaps.DisplayKeyMapUseCaseImpl import io.github.sds100.keymapper.mappings.keymaps.detection.DetectKeyMapsUseCaseImpl import io.github.sds100.keymapper.onboarding.OnboardingUseCaseImpl import io.github.sds100.keymapper.reroutekeyevents.RerouteKeyEventsUseCaseImpl diff --git a/app/src/main/java/io/github/sds100/keymapper/actions/ActionData.kt b/app/src/main/java/io/github/sds100/keymapper/actions/ActionData.kt index 87ab039469..0c08711dd2 100644 --- a/app/src/main/java/io/github/sds100/keymapper/actions/ActionData.kt +++ b/app/src/main/java/io/github/sds100/keymapper/actions/ActionData.kt @@ -1,5 +1,6 @@ package io.github.sds100.keymapper.actions +import io.github.sds100.keymapper.actions.pinchscreen.PinchScreenType import io.github.sds100.keymapper.system.camera.CameraLens import io.github.sds100.keymapper.system.display.Orientation import io.github.sds100.keymapper.system.intents.IntentTarget @@ -156,17 +157,17 @@ sealed class ActionData { sealed class DoNotDisturb : ActionData() { @Serializable - data class Toggle(val dndMode: DndMode) : ActionData.DoNotDisturb() { + data class Toggle(val dndMode: DndMode) : DoNotDisturb() { override val id: ActionId = ActionId.TOGGLE_DND_MODE } @Serializable - data class Enable(val dndMode: DndMode) : ActionData.DoNotDisturb() { + data class Enable(val dndMode: DndMode) : DoNotDisturb() { override val id: ActionId = ActionId.ENABLE_DND_MODE } @Serializable - object Disable : ActionData.DoNotDisturb() { + object Disable : DoNotDisturb() { override val id = ActionId.DISABLE_DND_MODE } } @@ -254,37 +255,37 @@ sealed class ActionData { @Serializable sealed class ControlMedia : ActionData() { @Serializable - object Pause : ActionData.ControlMedia() { + object Pause : ControlMedia() { override val id = ActionId.PAUSE_MEDIA } @Serializable - object Play : ActionData.ControlMedia() { + object Play : ControlMedia() { override val id = ActionId.PLAY_MEDIA } @Serializable - object PlayPause : ActionData.ControlMedia() { + object PlayPause : ControlMedia() { override val id = ActionId.PLAY_PAUSE_MEDIA } @Serializable - object NextTrack : ActionData.ControlMedia() { + object NextTrack : ControlMedia() { override val id = ActionId.NEXT_TRACK } @Serializable - object PreviousTrack : ActionData.ControlMedia() { + object PreviousTrack : ControlMedia() { override val id = ActionId.PREVIOUS_TRACK } @Serializable - object FastForward : ActionData.ControlMedia() { + object FastForward : ControlMedia() { override val id = ActionId.FAST_FORWARD } @Serializable - object Rewind : ActionData.ControlMedia() { + object Rewind : ControlMedia() { override val id = ActionId.REWIND } } @@ -320,6 +321,19 @@ sealed class ActionData { override val id = ActionId.SWIPE_SCREEN } + @Serializable + data class PinchScreen( + val x: Int, + val y: Int, + val distance: Int, + val pinchType: PinchScreenType, + val fingerCount: Int, + val duration: Int, + val description: String? + ) : ActionData() { + override val id = ActionId.PINCH_SCREEN + } + @Serializable data class PhoneCall( val number: String @@ -434,27 +448,27 @@ sealed class ActionData { @Serializable sealed class Brightness : ActionData() { @Serializable - object EnableAuto : ActionData.Brightness() { + object EnableAuto : Brightness() { override val id = ActionId.ENABLE_AUTO_BRIGHTNESS } @Serializable - object DisableAuto : ActionData.Brightness() { + object DisableAuto : Brightness() { override val id = ActionId.DISABLE_AUTO_BRIGHTNESS } @Serializable - object ToggleAuto : ActionData.Brightness() { + object ToggleAuto : Brightness() { override val id = ActionId.TOGGLE_AUTO_BRIGHTNESS } @Serializable - object Increase : ActionData.Brightness() { + object Increase : Brightness() { override val id = ActionId.INCREASE_BRIGHTNESS } @Serializable - object Decrease : ActionData.Brightness() { + object Decrease : Brightness() { override val id = ActionId.DECREASE_BRIGHTNESS } } @@ -462,27 +476,27 @@ sealed class ActionData { @Serializable sealed class StatusBar : ActionData() { @Serializable - object ExpandNotifications : ActionData.StatusBar() { + object ExpandNotifications : StatusBar() { override val id = ActionId.EXPAND_NOTIFICATION_DRAWER } @Serializable - object ToggleNotifications : ActionData.StatusBar() { + object ToggleNotifications : StatusBar() { override val id = ActionId.TOGGLE_NOTIFICATION_DRAWER } @Serializable - object ExpandQuickSettings : ActionData.StatusBar() { + object ExpandQuickSettings : StatusBar() { override val id = ActionId.EXPAND_QUICK_SETTINGS } @Serializable - object ToggleQuickSettings : ActionData.StatusBar() { + object ToggleQuickSettings : StatusBar() { override val id = ActionId.TOGGLE_QUICK_SETTINGS } @Serializable - object Collapse : ActionData.StatusBar() { + object Collapse : StatusBar() { override val id = ActionId.COLLAPSE_STATUS_BAR } } @@ -622,14 +636,14 @@ sealed class ActionData { object DismissAllNotifications : ActionData() { override val id: ActionId = ActionId.DISMISS_ALL_NOTIFICATIONS } - + @Serializable - object AnswerCall : ActionData(){ + object AnswerCall : ActionData() { override val id: ActionId = ActionId.ANSWER_PHONE_CALL } - + @Serializable - object EndCall : ActionData(){ + object EndCall : ActionData() { override val id: ActionId = ActionId.END_PHONE_CALL } } \ No newline at end of file diff --git a/app/src/main/java/io/github/sds100/keymapper/actions/ActionDataEntityMapper.kt b/app/src/main/java/io/github/sds100/keymapper/actions/ActionDataEntityMapper.kt index 1ef7431b4c..4af7523680 100644 --- a/app/src/main/java/io/github/sds100/keymapper/actions/ActionDataEntityMapper.kt +++ b/app/src/main/java/io/github/sds100/keymapper/actions/ActionDataEntityMapper.kt @@ -1,5 +1,6 @@ package io.github.sds100.keymapper.actions +import io.github.sds100.keymapper.actions.pinchscreen.PinchScreenType import io.github.sds100.keymapper.data.entities.ActionEntity import io.github.sds100.keymapper.data.entities.Extra import io.github.sds100.keymapper.data.entities.getData @@ -30,6 +31,7 @@ object ActionDataEntityMapper { ActionEntity.Type.URL -> ActionId.URL ActionEntity.Type.TAP_COORDINATE -> ActionId.TAP_SCREEN ActionEntity.Type.SWIPE_COORDINATE -> ActionId.SWIPE_SCREEN + ActionEntity.Type.PINCH_COORDINATE -> ActionId.PINCH_SCREEN ActionEntity.Type.INTENT -> ActionId.INTENT ActionEntity.Type.PHONE_CALL -> ActionId.PHONE_CALL ActionEntity.Type.SOUND -> ActionId.SOUND @@ -104,12 +106,12 @@ object ActionDataEntityMapper { ActionId.SWIPE_SCREEN -> { val splitData = entity.data.trim().split(',') - var xStart = 0; - var yStart = 0; - var xEnd = 0; - var yEnd = 0; - var fingerCount = 1; - var duration = 250; + var xStart = 0 + var yStart = 0 + var xEnd = 0 + var yEnd = 0 + var fingerCount = 1 + var duration = 250 if (splitData.isNotEmpty()) { xStart = splitData[0].trim().toInt() @@ -149,6 +151,60 @@ object ActionDataEntityMapper { ) } + ActionId.PINCH_SCREEN -> { + val splitData = entity.data.trim().split(',') + + var x = 0 + var y = 0 + var pinchType = PinchScreenType.PINCH_IN + var distance = 0 + var fingerCount = 2 + var duration = 250 + + if (splitData.isNotEmpty()) { + x = splitData[0].trim().toInt() + } + + if (splitData.size >= 2) { + y = splitData[1].trim().toInt() + } + + if (splitData.size >= 3) { + distance = splitData[2].trim().toInt() + } + + if (splitData.size >= 4) { + val tempType = splitData[3].trim() + + pinchType = if (tempType == PinchScreenType.PINCH_IN.name) { + PinchScreenType.PINCH_IN + } else { + PinchScreenType.PINCH_OUT + } + } + + if (splitData.size >= 5) { + fingerCount = splitData[4].trim().toInt().coerceAtLeast(2) + } + + if (splitData.size >= 6) { + duration = splitData[5].trim().toInt() + } + + val description = entity.extras.getData(ActionEntity.EXTRA_COORDINATE_DESCRIPTION) + .valueOrNull() + + ActionData.PinchScreen( + x = x, + y = y, + distance = distance, + pinchType = pinchType, + fingerCount = fingerCount, + duration = duration, + description = description + ) + } + ActionId.INTENT -> { val target = entity.extras.getData(ActionEntity.EXTRA_INTENT_TARGET).then { INTENT_TARGET_MAP.getKey(it).success() @@ -210,6 +266,7 @@ object ActionDataEntityMapper { ActionId.VOLUME_TOGGLE_MUTE -> ActionData.Volume.ToggleMute( showVolumeUi ) + ActionId.VOLUME_UNMUTE -> ActionData.Volume.UnMute(showVolumeUi) ActionId.VOLUME_MUTE -> ActionData.Volume.Mute(showVolumeUi) @@ -273,16 +330,22 @@ object ActionDataEntityMapper { when (actionId) { ActionId.PAUSE_MEDIA_PACKAGE -> ActionData.ControlMediaForApp.Pause(packageName) + ActionId.PLAY_MEDIA_PACKAGE -> ActionData.ControlMediaForApp.Play(packageName) + ActionId.PLAY_PAUSE_MEDIA_PACKAGE -> ActionData.ControlMediaForApp.PlayPause(packageName) + ActionId.NEXT_TRACK_PACKAGE -> ActionData.ControlMediaForApp.NextTrack(packageName) + ActionId.PREVIOUS_TRACK_PACKAGE -> ActionData.ControlMediaForApp.PreviousTrack(packageName) + ActionId.FAST_FORWARD_PACKAGE -> ActionData.ControlMediaForApp.FastForward(packageName) + ActionId.REWIND_PACKAGE -> ActionData.ControlMediaForApp.Rewind(packageName) @@ -417,6 +480,7 @@ object ActionDataEntityMapper { is ActionData.PhoneCall -> ActionEntity.Type.PHONE_CALL is ActionData.TapScreen -> ActionEntity.Type.TAP_COORDINATE is ActionData.SwipeScreen -> ActionEntity.Type.SWIPE_COORDINATE + is ActionData.PinchScreen -> ActionEntity.Type.PINCH_COORDINATE is ActionData.Text -> ActionEntity.Type.TEXT_BLOCK is ActionData.Url -> ActionEntity.Type.URL is ActionData.Sound -> ActionEntity.Type.SOUND @@ -457,6 +521,7 @@ object ActionDataEntityMapper { is ActionData.PhoneCall -> data.number is ActionData.TapScreen -> "${data.x},${data.y}" is ActionData.SwipeScreen -> "${data.xStart},${data.yStart},${data.xEnd},${data.yEnd},${data.fingerCount},${data.duration}" + is ActionData.PinchScreen -> "${data.x},${data.y},${data.distance},${data.pinchType},${data.fingerCount},${data.duration}" is ActionData.Text -> data.text is ActionData.Url -> data.url is ActionData.Sound -> data.soundUid @@ -542,6 +607,7 @@ object ActionDataEntityMapper { else -> emptyList() } + is ActionData.TapScreen -> sequence { if (!data.description.isNullOrBlank()) { yield(Extra(ActionEntity.EXTRA_COORDINATE_DESCRIPTION, data.description)) @@ -554,6 +620,12 @@ object ActionDataEntityMapper { } }.toList() + is ActionData.PinchScreen -> sequence { + if (!data.description.isNullOrBlank()) { + yield(Extra(ActionEntity.EXTRA_COORDINATE_DESCRIPTION, data.description)) + } + }.toList() + is ActionData.Text -> emptyList() is ActionData.Url -> emptyList() @@ -715,7 +787,7 @@ object ActionDataEntityMapper { ActionId.DISMISS_MOST_RECENT_NOTIFICATION to "dismiss_most_recent_notification", ActionId.DISMISS_ALL_NOTIFICATIONS to "dismiss_all_notifications", - + ActionId.ANSWER_PHONE_CALL to "answer_phone_call", ActionId.END_PHONE_CALL to "end_phone_call" ) diff --git a/app/src/main/java/io/github/sds100/keymapper/actions/ActionId.kt b/app/src/main/java/io/github/sds100/keymapper/actions/ActionId.kt index 7e47c7129f..edaade0613 100644 --- a/app/src/main/java/io/github/sds100/keymapper/actions/ActionId.kt +++ b/app/src/main/java/io/github/sds100/keymapper/actions/ActionId.kt @@ -10,6 +10,7 @@ enum class ActionId { KEY_EVENT, TAP_SCREEN, SWIPE_SCREEN, + PINCH_SCREEN, TEXT, URL, INTENT, @@ -123,7 +124,7 @@ enum class ActionId { DISMISS_MOST_RECENT_NOTIFICATION, DISMISS_ALL_NOTIFICATIONS, - + ANSWER_PHONE_CALL, END_PHONE_CALL } \ No newline at end of file diff --git a/app/src/main/java/io/github/sds100/keymapper/actions/ActionUtils.kt b/app/src/main/java/io/github/sds100/keymapper/actions/ActionUtils.kt index a0ea5ef07b..b2433589e6 100644 --- a/app/src/main/java/io/github/sds100/keymapper/actions/ActionUtils.kt +++ b/app/src/main/java/io/github/sds100/keymapper/actions/ActionUtils.kt @@ -40,6 +40,7 @@ object ActionUtils { ActionId.KEY_EVENT -> ActionCategory.INPUT ActionId.TAP_SCREEN -> ActionCategory.INPUT ActionId.SWIPE_SCREEN -> ActionCategory.INPUT + ActionId.PINCH_SCREEN -> ActionCategory.INPUT ActionId.TEXT -> ActionCategory.INPUT ActionId.OPEN_VOICE_ASSISTANT -> ActionCategory.APPS @@ -257,6 +258,7 @@ object ActionUtils { ActionId.KEY_EVENT -> R.string.action_input_key_event ActionId.TAP_SCREEN -> R.string.action_tap_screen ActionId.SWIPE_SCREEN -> R.string.action_swipe_screen + ActionId.PINCH_SCREEN -> R.string.action_pinch_screen ActionId.TEXT -> R.string.action_input_text ActionId.URL -> R.string.action_open_url ActionId.INTENT -> R.string.action_send_intent @@ -366,7 +368,8 @@ object ActionUtils { ActionId.KEY_CODE -> R.drawable.ic_q_24 ActionId.KEY_EVENT -> R.drawable.ic_q_24 ActionId.TAP_SCREEN -> R.drawable.ic_outline_touch_app_24 - ActionId.SWIPE_SCREEN -> R.drawable.ic_outline_touch_app_24 + ActionId.SWIPE_SCREEN -> R.drawable.ic_outline_swipe_app_24 + ActionId.PINCH_SCREEN -> R.drawable.ic_outline_pinch_app_24 ActionId.TEXT -> R.drawable.ic_outline_short_text_24 ActionId.URL -> R.drawable.ic_outline_link_24 ActionId.INTENT -> null @@ -553,6 +556,7 @@ object ActionUtils { ActionId.ANSWER_PHONE_CALL, ActionId.END_PHONE_CALL -> return listOf(Permission.ANSWER_PHONE_CALL) + else -> Unit } @@ -603,9 +607,11 @@ fun ActionData.isEditable(): Boolean = when (this) { is ActionData.Flashlight.Disable, is ActionData.TapScreen, is ActionData.SwipeScreen, + is ActionData.PinchScreen, is ActionData.Text, is ActionData.Url, is ActionData.PhoneCall, -> true + else -> false } \ No newline at end of file diff --git a/app/src/main/java/io/github/sds100/keymapper/actions/BaseActionUiHelper.kt b/app/src/main/java/io/github/sds100/keymapper/actions/BaseActionUiHelper.kt index 462e905dfa..86b0925c89 100644 --- a/app/src/main/java/io/github/sds100/keymapper/actions/BaseActionUiHelper.kt +++ b/app/src/main/java/io/github/sds100/keymapper/actions/BaseActionUiHelper.kt @@ -2,6 +2,7 @@ package io.github.sds100.keymapper.actions import android.view.KeyEvent import io.github.sds100.keymapper.R +import io.github.sds100.keymapper.actions.pinchscreen.PinchScreenType import io.github.sds100.keymapper.mappings.DisplayActionUseCase import io.github.sds100.keymapper.mappings.Mapping import io.github.sds100.keymapper.system.camera.CameraLensUtils @@ -306,7 +307,54 @@ abstract class BaseActionUiHelper, A : Action>( } else { getString( R.string.description_swipe_coordinate_with_description, - arrayOf(action.fingerCount, action.xStart, action.yStart, action.xEnd, action.yEnd, action.duration, action.description) + arrayOf( + action.fingerCount, + action.xStart, + action.yStart, + action.xEnd, + action.yEnd, + action.duration, + action.description + ) + ) + } + + is ActionData.PinchScreen -> if (action.description.isNullOrBlank()) { + val pinchTypeDisplayName = if (action.pinchType == PinchScreenType.PINCH_IN) { + getString(R.string.hint_coordinate_type_pinch_in) + } else { + getString(R.string.hint_coordinate_type_pinch_out) + } + + getString( + R.string.description_pinch_coordinate_default, + arrayOf( + pinchTypeDisplayName, + action.fingerCount, + action.x, + action.y, + action.distance, + action.duration + ) + ) + } else { + val pinchTypeDisplayName = if (action.pinchType == PinchScreenType.PINCH_IN) { + getString(R.string.hint_coordinate_type_pinch_in) + } else { + getString(R.string.hint_coordinate_type_pinch_out) + } + + getString( + R.string.description_pinch_coordinate_with_description, + arrayOf( + pinchTypeDisplayName, + action.fingerCount, + action.x, + action.y, + action.distance, + action.duration, + action.description + ) ) } @@ -376,6 +424,7 @@ abstract class BaseActionUiHelper, A : Action>( orientationStrings.joinToString() ) } + ActionData.Rotation.DisableAuto -> getString(R.string.action_disable_auto_rotate) ActionData.Rotation.EnableAuto -> getString(R.string.action_enable_auto_rotate) ActionData.Rotation.Landscape -> getString(R.string.action_landscape_mode) @@ -406,7 +455,7 @@ abstract class BaseActionUiHelper, A : Action>( ActionData.Wifi.Toggle -> getString(R.string.action_toggle_wifi) ActionData.DismissAllNotifications -> getString(R.string.action_dismiss_all_notifications) ActionData.DismissLastNotification -> getString(R.string.action_dismiss_most_recent_notification) - + ActionData.AnswerCall -> getString(R.string.action_answer_call) ActionData.EndCall -> getString(R.string.action_end_call) } diff --git a/app/src/main/java/io/github/sds100/keymapper/actions/ChooseActionFragment.kt b/app/src/main/java/io/github/sds100/keymapper/actions/ChooseActionFragment.kt index 6301cd7390..be1dfa6553 100644 --- a/app/src/main/java/io/github/sds100/keymapper/actions/ChooseActionFragment.kt +++ b/app/src/main/java/io/github/sds100/keymapper/actions/ChooseActionFragment.kt @@ -13,7 +13,13 @@ import io.github.sds100.keymapper.simpleGrid import io.github.sds100.keymapper.util.Inject import io.github.sds100.keymapper.util.State import io.github.sds100.keymapper.util.launchRepeatOnLifecycle -import io.github.sds100.keymapper.util.ui.* +import io.github.sds100.keymapper.util.ui.DefaultSimpleListItem +import io.github.sds100.keymapper.util.ui.ListItem +import io.github.sds100.keymapper.util.ui.RecyclerViewUtils +import io.github.sds100.keymapper.util.ui.SectionHeaderListItem +import io.github.sds100.keymapper.util.ui.SimpleRecyclerViewFragment +import io.github.sds100.keymapper.util.ui.setupNavigation +import io.github.sds100.keymapper.util.ui.showPopups import io.github.sds100.keymapper.util.viewLifecycleScope import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.collectLatest diff --git a/app/src/main/java/io/github/sds100/keymapper/actions/ConfigActionsViewModel.kt b/app/src/main/java/io/github/sds100/keymapper/actions/ConfigActionsViewModel.kt index fc0371a947..77e16a0cd9 100644 --- a/app/src/main/java/io/github/sds100/keymapper/actions/ConfigActionsViewModel.kt +++ b/app/src/main/java/io/github/sds100/keymapper/actions/ConfigActionsViewModel.kt @@ -7,11 +7,38 @@ import io.github.sds100.keymapper.mappings.DisplayActionUseCase import io.github.sds100.keymapper.mappings.Mapping import io.github.sds100.keymapper.mappings.isDelayBeforeNextActionAllowed import io.github.sds100.keymapper.onboarding.OnboardingUseCase -import io.github.sds100.keymapper.util.* -import io.github.sds100.keymapper.util.ui.* +import io.github.sds100.keymapper.util.Error +import io.github.sds100.keymapper.util.State +import io.github.sds100.keymapper.util.getFullMessage +import io.github.sds100.keymapper.util.ifIsData +import io.github.sds100.keymapper.util.isFixable +import io.github.sds100.keymapper.util.mapData +import io.github.sds100.keymapper.util.onFailure +import io.github.sds100.keymapper.util.ui.DialogResponse +import io.github.sds100.keymapper.util.ui.IconInfo +import io.github.sds100.keymapper.util.ui.NavDestination +import io.github.sds100.keymapper.util.ui.NavigationViewModel +import io.github.sds100.keymapper.util.ui.NavigationViewModelImpl +import io.github.sds100.keymapper.util.ui.PopupUi +import io.github.sds100.keymapper.util.ui.PopupViewModel +import io.github.sds100.keymapper.util.ui.PopupViewModelImpl +import io.github.sds100.keymapper.util.ui.ResourceProvider +import io.github.sds100.keymapper.util.ui.TintType +import io.github.sds100.keymapper.util.ui.ViewModelHelper +import io.github.sds100.keymapper.util.ui.navigate +import io.github.sds100.keymapper.util.ui.showPopup import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.flow.* +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asSharedFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.collectLatest +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.firstOrNull +import kotlinx.coroutines.flow.flowOn +import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking diff --git a/app/src/main/java/io/github/sds100/keymapper/actions/CreateActionViewModel.kt b/app/src/main/java/io/github/sds100/keymapper/actions/CreateActionViewModel.kt index 462c4fd8b0..a0767eb616 100644 --- a/app/src/main/java/io/github/sds100/keymapper/actions/CreateActionViewModel.kt +++ b/app/src/main/java/io/github/sds100/keymapper/actions/CreateActionViewModel.kt @@ -2,6 +2,7 @@ package io.github.sds100.keymapper.actions import android.text.InputType import io.github.sds100.keymapper.R +import io.github.sds100.keymapper.actions.pinchscreen.PinchPickCoordinateResult import io.github.sds100.keymapper.actions.swipescreen.SwipePickCoordinateResult import io.github.sds100.keymapper.actions.tapscreen.PickCoordinateResult import io.github.sds100.keymapper.system.camera.CameraLens @@ -80,18 +81,25 @@ class CreateActionViewModelImpl( val action = when (actionId) { ActionId.PAUSE_MEDIA_PACKAGE -> ActionData.ControlMediaForApp.Pause(packageName) + ActionId.PLAY_MEDIA_PACKAGE -> ActionData.ControlMediaForApp.Play(packageName) + ActionId.PLAY_PAUSE_MEDIA_PACKAGE -> ActionData.ControlMediaForApp.PlayPause(packageName) + ActionId.NEXT_TRACK_PACKAGE -> ActionData.ControlMediaForApp.NextTrack(packageName) + ActionId.PREVIOUS_TRACK_PACKAGE -> ActionData.ControlMediaForApp.PreviousTrack(packageName) + ActionId.FAST_FORWARD_PACKAGE -> ActionData.ControlMediaForApp.FastForward(packageName) + ActionId.REWIND_PACKAGE -> ActionData.ControlMediaForApp.Rewind(packageName) + else -> throw Exception("don't know how to create action for $actionId") } @@ -137,6 +145,7 @@ class CreateActionViewModelImpl( ActionId.VOLUME_TOGGLE_MUTE -> ActionData.Volume.ToggleMute( showVolumeUi ) + else -> throw Exception("don't know how to create action for $actionId") } @@ -363,6 +372,43 @@ class CreateActionViewModelImpl( ) } + ActionId.PINCH_SCREEN -> { + val oldResult = if (oldData is ActionData.PinchScreen) { + PinchPickCoordinateResult( + oldData.x, + oldData.y, + oldData.distance, + oldData.pinchType, + oldData.fingerCount, + oldData.duration, + oldData.description ?: "" + ) + } else { + null + } + + val result = navigate( + "pick_pinch_coordinate_for_action", + NavDestination.PickPinchCoordinate(oldResult) + ) ?: return null + + val description = if (result.description.isEmpty()) { + null + } else { + result.description + } + + return ActionData.PinchScreen( + result.x, + result.y, + result.distance, + result.pinchType, + result.fingerCount, + result.duration, + description + ) + } + ActionId.TEXT -> { val oldText = if (oldData is ActionData.Text) { oldData.text diff --git a/app/src/main/java/io/github/sds100/keymapper/actions/PerformActionsUseCase.kt b/app/src/main/java/io/github/sds100/keymapper/actions/PerformActionsUseCase.kt index 98059017c2..1626b758ba 100644 --- a/app/src/main/java/io/github/sds100/keymapper/actions/PerformActionsUseCase.kt +++ b/app/src/main/java/io/github/sds100/keymapper/actions/PerformActionsUseCase.kt @@ -43,7 +43,21 @@ import io.github.sds100.keymapper.system.url.OpenUrlAdapter import io.github.sds100.keymapper.system.volume.RingerMode import io.github.sds100.keymapper.system.volume.VolumeAdapter import io.github.sds100.keymapper.system.volume.VolumeStream -import io.github.sds100.keymapper.util.* +import io.github.sds100.keymapper.util.Error +import io.github.sds100.keymapper.util.Event +import io.github.sds100.keymapper.util.InputEventType +import io.github.sds100.keymapper.util.Result +import io.github.sds100.keymapper.util.Success +import io.github.sds100.keymapper.util.dataOrNull +import io.github.sds100.keymapper.util.firstBlocking +import io.github.sds100.keymapper.util.getFullMessage +import io.github.sds100.keymapper.util.getWordBoundaries +import io.github.sds100.keymapper.util.ifIsData +import io.github.sds100.keymapper.util.onFailure +import io.github.sds100.keymapper.util.onSuccess +import io.github.sds100.keymapper.util.otherwise +import io.github.sds100.keymapper.util.success +import io.github.sds100.keymapper.util.then import io.github.sds100.keymapper.util.ui.ResourceProvider import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.delay @@ -113,9 +127,11 @@ class PerformActionsUseCaseImpl( is ActionData.App -> { result = packageManagerAdapter.openApp(action.packageName) } + is ActionData.AppShortcut -> { result = appShortcutAdapter.launchShortcut(action.uri) } + is ActionData.Intent -> { result = intentAdapter.send(action.target, action.uri) } @@ -153,6 +169,7 @@ class PerformActionsUseCaseImpl( is ActionData.DoNotDisturb.Enable -> { result = volumeAdapter.enableDndMode(action.dndMode) } + is ActionData.DoNotDisturb.Toggle -> { result = if (volumeAdapter.isDndEnabled()) { volumeAdapter.disableDndMode() @@ -168,21 +185,27 @@ class PerformActionsUseCaseImpl( is ActionData.ControlMediaForApp.FastForward -> { result = mediaAdapter.fastForward(action.packageName) } + is ActionData.ControlMediaForApp.NextTrack -> { result = mediaAdapter.nextTrack(action.packageName) } + is ActionData.ControlMediaForApp.Pause -> { result = mediaAdapter.pause(action.packageName) } + is ActionData.ControlMediaForApp.Play -> { result = mediaAdapter.play(action.packageName) } + is ActionData.ControlMediaForApp.PlayPause -> { result = mediaAdapter.playPause(action.packageName) } + is ActionData.ControlMediaForApp.PreviousTrack -> { result = mediaAdapter.previousTrack(action.packageName) } + is ActionData.ControlMediaForApp.Rewind -> { result = mediaAdapter.rewind(action.packageName) } @@ -235,6 +258,7 @@ class PerformActionsUseCaseImpl( is ActionData.Volume.Down -> { result = volumeAdapter.lowerVolume(showVolumeUi = action.showVolumeUi) } + is ActionData.Volume.Up -> { result = volumeAdapter.raiseVolume(showVolumeUi = action.showVolumeUi) } @@ -270,7 +294,27 @@ class PerformActionsUseCaseImpl( } is ActionData.SwipeScreen -> { - result = accessibilityService.swipeScreen(action.xStart, action.yStart, action.xEnd, action.yEnd, action.fingerCount, action.duration, inputEventType) + result = accessibilityService.swipeScreen( + action.xStart, + action.yStart, + action.xEnd, + action.yEnd, + action.fingerCount, + action.duration, + inputEventType + ) + } + + is ActionData.PinchScreen -> { + result = accessibilityService.pinchScreen( + action.x, + action.y, + action.distance, + action.pinchType, + action.fingerCount, + action.duration, + inputEventType + ) } is ActionData.Text -> { @@ -351,9 +395,11 @@ class PerformActionsUseCaseImpl( is ActionData.Brightness.EnableAuto -> { result = displayAdapter.enableAutoBrightness() } + is ActionData.Brightness.Increase -> { result = displayAdapter.increaseBrightness() } + is ActionData.Brightness.Decrease -> { result = displayAdapter.decreaseBrightness() } @@ -425,7 +471,7 @@ class PerformActionsUseCaseImpl( is ActionData.StatusBar.ToggleNotifications -> { result = if (accessibilityService.rootNode?.packageName == "com.android.systemui") { - closeStatusBarShade() + closeStatusBarShade() } else { val globalAction = AccessibilityService.GLOBAL_ACTION_NOTIFICATIONS @@ -464,21 +510,27 @@ class PerformActionsUseCaseImpl( is ActionData.ControlMedia.Pause -> { result = mediaAdapter.pause() } + is ActionData.ControlMedia.Play -> { result = mediaAdapter.play() } + is ActionData.ControlMedia.PlayPause -> { result = mediaAdapter.playPause() } + is ActionData.ControlMedia.NextTrack -> { result = mediaAdapter.nextTrack() } + is ActionData.ControlMedia.PreviousTrack -> { result = mediaAdapter.previousTrack() } + is ActionData.ControlMedia.FastForward -> { result = mediaAdapter.fastForward() } + is ActionData.ControlMedia.Rewind -> { result = mediaAdapter.rewind() } @@ -487,6 +539,7 @@ class PerformActionsUseCaseImpl( result = accessibilityService.doGlobalAction(AccessibilityService.GLOBAL_ACTION_BACK) } + is ActionData.GoHome -> { result = accessibilityService.doGlobalAction(AccessibilityService.GLOBAL_ACTION_HOME) @@ -523,9 +576,11 @@ class PerformActionsUseCaseImpl( is ActionData.Nfc.Enable -> { result = nfcAdapter.enable() } + is ActionData.Nfc.Disable -> { result = nfcAdapter.disable() } + is ActionData.Nfc.Toggle -> { result = if (nfcAdapter.isEnabled()) { nfcAdapter.disable() @@ -586,6 +641,7 @@ class PerformActionsUseCaseImpl( AccessibilityNodeAction(AccessibilityNodeInfo.ACTION_COPY) } } + is ActionData.PasteText -> { result = accessibilityService.performActionOnNode({ it.isFocused }) { AccessibilityNodeAction(AccessibilityNodeInfo.ACTION_PASTE) @@ -627,9 +683,11 @@ class PerformActionsUseCaseImpl( airplaneModeAdapter.enable() } } + is ActionData.AirplaneMode.Enable -> { result = airplaneModeAdapter.enable() } + is ActionData.AirplaneMode.Disable -> { result = airplaneModeAdapter.disable() } @@ -661,9 +719,11 @@ class PerformActionsUseCaseImpl( is ActionData.VoiceAssistant -> { result = packageManagerAdapter.launchVoiceAssistant() } + is ActionData.DeviceAssistant -> { result = packageManagerAdapter.launchDeviceAssistant() } + is ActionData.OpenCamera -> { result = packageManagerAdapter.launchCameraApp() } @@ -716,13 +776,13 @@ class PerformActionsUseCaseImpl( result = null } - - ActionData.AnswerCall ->{ + + ActionData.AnswerCall -> { phoneAdapter.answerCall() result = success() } - - ActionData.EndCall ->{ + + ActionData.EndCall -> { phoneAdapter.endCall() result = success() } diff --git a/app/src/main/java/io/github/sds100/keymapper/actions/pinchscreen/PichPickDisplayCoordinateFragment.kt b/app/src/main/java/io/github/sds100/keymapper/actions/pinchscreen/PichPickDisplayCoordinateFragment.kt new file mode 100644 index 0000000000..81c1d2f501 --- /dev/null +++ b/app/src/main/java/io/github/sds100/keymapper/actions/pinchscreen/PichPickDisplayCoordinateFragment.kt @@ -0,0 +1,158 @@ +package io.github.sds100.keymapper.actions.pinchscreen + +import android.annotation.SuppressLint +import android.graphics.ImageDecoder +import android.graphics.Point +import android.os.Build +import android.os.Bundle +import android.provider.MediaStore +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.ArrayAdapter +import androidx.activity.addCallback +import androidx.activity.result.contract.ActivityResultContracts +import androidx.core.content.getSystemService +import androidx.core.graphics.decodeBitmap +import androidx.core.os.bundleOf +import androidx.fragment.app.Fragment +import androidx.fragment.app.setFragmentResult +import androidx.fragment.app.viewModels +import androidx.lifecycle.* +import androidx.navigation.fragment.findNavController +import androidx.navigation.fragment.navArgs +import io.github.sds100.keymapper.R +import io.github.sds100.keymapper.databinding.FragmentPinchPickCoordinatesBinding +import io.github.sds100.keymapper.system.files.FileUtils +import io.github.sds100.keymapper.util.* +import io.github.sds100.keymapper.util.ui.showPopups +import kotlinx.coroutines.flow.collectLatest +import kotlinx.serialization.decodeFromString +import kotlinx.serialization.encodeToString +import kotlinx.serialization.json.Json + +class PinchPickDisplayCoordinateFragment : Fragment() { + companion object { + const val EXTRA_RESULT = "extra_result" + } + + private val args: PinchPickDisplayCoordinateFragmentArgs by navArgs() + private val requestKey: String by lazy { args.requestKey } + private var pinchTypesDisplayValues = mutableListOf() + + private val viewModel: PinchPickDisplayCoordinateViewModel by viewModels { + Inject.pinchCoordinateActionTypeViewModel(requireContext()) + } + + private val screenshotLauncher = + registerForActivityResult(ActivityResultContracts.GetContent()) { + it ?: return@registerForActivityResult + + val bitmap = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + ImageDecoder.createSource(requireContext().contentResolver, it) + .decodeBitmap { _, _ -> } + } else { + MediaStore.Images.Media.getBitmap(requireContext().contentResolver, it) + } + + val displaySize = Point().apply { + val windowManager: WindowManager = requireContext().getSystemService()!! + windowManager.defaultDisplay.getRealSize(this) + } + + viewModel.selectedScreenshot(bitmap, displaySize) + } + + /** + * Scoped to the lifecycle of the fragment's view (between onCreateView and onDestroyView) + */ + private var _binding: FragmentPinchPickCoordinatesBinding? = null + val binding: FragmentPinchPickCoordinatesBinding + get() = _binding!! + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + pinchTypesDisplayValues = arrayOf( + str(R.string.hint_coordinate_type_pinch_in), + str(R.string.hint_coordinate_type_pinch_out) + ).toMutableList() + + args.result?.let { + viewModel.loadResult(Json.decodeFromString(it)) + } + } + + @SuppressLint("ClickableViewAccessibility") + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + FragmentPinchPickCoordinatesBinding.inflate(inflater, container, false).apply { + lifecycleOwner = viewLifecycleOwner + _binding = this + + return this.root + } + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + binding.viewModel = viewModel + binding.pinchTypeSpinnerAdapter = + ArrayAdapter(this.requireActivity(), android.R.layout.simple_spinner_dropdown_item, pinchTypesDisplayValues) + viewModel.showPopups(this, binding) + + requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) { + findNavController().navigateUp() + } + + binding.appBar.setNavigationOnClickListener { + findNavController().navigateUp() + } + + viewLifecycleOwner.launchRepeatOnLifecycle(Lifecycle.State.RESUMED) { + viewModel.bitmap.collectLatest { bitmap -> + if (bitmap == null) { + binding.imageViewScreenshot.setImageDrawable(null) + } else { + binding.imageViewScreenshot.setImageBitmap(bitmap) + } + } + } + + viewLifecycleOwner.launchRepeatOnLifecycle(Lifecycle.State.RESUMED) { + binding.imageViewScreenshot.pointCoordinates.collectLatest { point -> + if (point != null) { + viewModel.onScreenshotTouch( + point.x.toFloat() / binding.imageViewScreenshot.width, + point.y.toFloat() / binding.imageViewScreenshot.height + ) + } + } + } + + viewLifecycleOwner.launchRepeatOnLifecycle(Lifecycle.State.RESUMED) { + viewModel.returnResult.collectLatest { result -> + setFragmentResult( + requestKey, + bundleOf(EXTRA_RESULT to Json.encodeToString(result)) + ) + + findNavController().navigateUp() + } + } + + binding.setOnSelectScreenshotClick { + screenshotLauncher.launch(FileUtils.MIME_TYPE_IMAGES) + } + } + + override fun onDestroyView() { + _binding = null + super.onDestroyView() + } +} \ No newline at end of file diff --git a/app/src/main/java/io/github/sds100/keymapper/actions/pinchscreen/PinchPickCoordinateResult.kt b/app/src/main/java/io/github/sds100/keymapper/actions/pinchscreen/PinchPickCoordinateResult.kt new file mode 100644 index 0000000000..39f115f49b --- /dev/null +++ b/app/src/main/java/io/github/sds100/keymapper/actions/pinchscreen/PinchPickCoordinateResult.kt @@ -0,0 +1,19 @@ +package io.github.sds100.keymapper.actions.pinchscreen + +import kotlinx.serialization.Serializable + +enum class PinchScreenType { + PINCH_IN, + PINCH_OUT +} + +@Serializable +data class PinchPickCoordinateResult( + val x: Int, + val y: Int, + val distance: Int, + val pinchType: PinchScreenType, + val fingerCount: Int, + val duration: Int, + val description: String +) diff --git a/app/src/main/java/io/github/sds100/keymapper/actions/pinchscreen/PinchPickDisplayCoordinateViewModel.kt b/app/src/main/java/io/github/sds100/keymapper/actions/pinchscreen/PinchPickDisplayCoordinateViewModel.kt new file mode 100644 index 0000000000..44023e35d4 --- /dev/null +++ b/app/src/main/java/io/github/sds100/keymapper/actions/pinchscreen/PinchPickDisplayCoordinateViewModel.kt @@ -0,0 +1,273 @@ +package io.github.sds100.keymapper.actions.pinchscreen + +import android.accessibilityservice.GestureDescription +import android.graphics.Bitmap +import android.graphics.Point +import android.os.Build +import android.view.View +import android.widget.AdapterView +import androidx.lifecycle.ViewModel +import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.viewModelScope +import io.github.sds100.keymapper.R +import io.github.sds100.keymapper.util.ui.* +import kotlinx.coroutines.flow.* +import kotlinx.coroutines.launch +import kotlin.math.roundToInt + +class PinchPickDisplayCoordinateViewModel( + resourceProvider: ResourceProvider +) : ViewModel(), ResourceProvider by resourceProvider, PopupViewModel by PopupViewModelImpl() { + + private val pinchTypes = arrayOf(PinchScreenType.PINCH_IN.name, PinchScreenType.PINCH_OUT.name) + + private val x = MutableStateFlow(null) + private val y = MutableStateFlow(null) + private val distance = MutableStateFlow(null) + private val pinchType = MutableStateFlow(PinchScreenType.PINCH_IN) + private val fingerCount = MutableStateFlow(2) + private val duration = MutableStateFlow(200) + + private val _bitmap = MutableStateFlow(null) + private val _returnResult = MutableSharedFlow() + + private val description: MutableStateFlow = MutableStateFlow(null) + + val xString = x.map { + it ?: return@map "" + + it.toString() + }.stateIn(viewModelScope, SharingStarted.Lazily, null) + + val yString = y.map { + it ?: return@map "" + + it.toString() + }.stateIn(viewModelScope, SharingStarted.Lazily, null) + + val distanceString = distance.map { + it ?: return@map "" + + it.toString() + }.stateIn(viewModelScope, SharingStarted.Lazily, null) + + val distanceError: StateFlow = distance.map { distance -> + if (distance == null) { + return@map resourceProvider.getString(R.string.error_cant_be_empty) + } + + if (distance <= 0) { + return@map resourceProvider.getString(R.string.error_pinch_screen_distance_too_low) + } + + null + }.stateIn(viewModelScope, SharingStarted.Eagerly, null) + + val pinchTypeSpinnerSelection = pinchType.map { + it ?: return@map 0 + + this.pinchTypes.indexOf(it.name) + }.stateIn(viewModelScope, SharingStarted.Lazily, 0) + + val fingerCountString = fingerCount.map { + it ?: return@map "" + + it.toString() + }.stateIn(viewModelScope, SharingStarted.Lazily, null) + + val fingerCountError: StateFlow = fingerCount.map { count -> + if (count == null) { + return@map resourceProvider.getString(R.string.error_cant_be_empty) + } + + if (count < 2) { + return@map resourceProvider.getString(R.string.error_pinch_screen_must_be_two_or_more_fingers) + } + + var maxFingerCount = 10 + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + maxFingerCount = GestureDescription.getMaxStrokeCount() + } + + if (count > maxFingerCount) { + return@map resourceProvider.getString( + R.string.error_pinch_screen_must_be_ten_or_less_fingers, + arrayOf(maxFingerCount) + ) + } + + null + }.stateIn(viewModelScope, SharingStarted.Lazily, null) + + val durationString = duration.map { + it ?: return@map "" + + it.toString() + }.stateIn(viewModelScope, SharingStarted.Lazily, null) + + val durationError: StateFlow = duration.map { d -> + if (d == null) { + return@map resourceProvider.getString(R.string.error_cant_be_empty) + } + + if (d <= 0) { + return@map resourceProvider.getString(R.string.error_pinch_screen_duration_must_be_more_than_zero) + } + + null + }.stateIn(viewModelScope, SharingStarted.Lazily, null) + + val bitmap = _bitmap.asStateFlow() + val returnResult = _returnResult.asSharedFlow() + + private val isCoordinatesValid: StateFlow = + combine(x, y, distance, pinchType) { x, y, distance, pinchType -> + x ?: return@combine false + y ?: return@combine false + distance ?: return@combine false + pinchType ?: return@combine false + + x >= 0 && y >= 0 && distance > 0 && (pinchType == PinchScreenType.PINCH_IN || pinchType == PinchScreenType.PINCH_OUT) + }.stateIn(viewModelScope, SharingStarted.Lazily, false) + + val isDoneButtonEnabled: StateFlow = + combine( + isCoordinatesValid, + fingerCountError, + durationError + ) { isCoordinatesValid, fingerCountError, durationError -> + isCoordinatesValid && fingerCountError == null && durationError == null + }.stateIn(viewModelScope, SharingStarted.Lazily, false) + + fun selectedScreenshot(newBitmap: Bitmap, displaySize: Point) { + //check whether the height and width of the bitmap match the display size, even when it is rotated. + if ( + (displaySize.x != newBitmap.width + && displaySize.y != newBitmap.height) && + + (displaySize.y != newBitmap.width + && displaySize.x != newBitmap.height) + ) { + viewModelScope.launch { + val snackBar = PopupUi.SnackBar( + message = getString(R.string.toast_incorrect_screenshot_resolution) + ) + + showPopup("incorrect_resolution", snackBar) + } + + return + } + + _bitmap.value = newBitmap + } + + fun setX(x: String) { + this.x.value = x.toIntOrNull() + } + + fun setY(y: String) { + this.y.value = y.toIntOrNull() + } + + fun setDistance(distance: String) { + this.distance.value = distance.toIntOrNull() + } + + private fun setPinchType(type: String) { + if (type == PinchScreenType.PINCH_IN.name) { + this.pinchType.value = PinchScreenType.PINCH_IN + } else { + this.pinchType.value = PinchScreenType.PINCH_OUT + } + } + + fun setFingerCount(fingerCount: String) { + this.fingerCount.value = fingerCount.toIntOrNull() + } + + fun setDuration(duration: String) { + this.duration.value = duration.toIntOrNull() + } + + /** + * [screenshotXRatio] The ratio between the point where the user pressed to the width of the image. + * [screenshotYRatio] The ratio between the point where the user pressed to the height of the image. + */ + fun onScreenshotTouch(screenshotXRatio: Float, screenshotYRatio: Float) { + bitmap.value?.let { + + val displayX = it.width * screenshotXRatio + val displayY = it.height * screenshotYRatio + + x.value = displayX.roundToInt() + y.value = displayY.roundToInt() + } + } + + fun onDoneClick() { + viewModelScope.launch { + val x = x.value ?: return@launch + val y = y.value ?: return@launch + val distance = distance.value ?: return@launch + val pinchType = pinchType.value ?: return@launch + val fingerCount = fingerCount.value ?: return@launch + val duration = duration.value ?: return@launch + + val description = showPopup( + "coordinate_description", + PopupUi.Text( + getString(R.string.hint_tap_coordinate_title), + allowEmpty = true, + text = description.value ?: "" + ) + ) ?: return@launch + + _returnResult.emit( + PinchPickCoordinateResult( + x, + y, + distance, + pinchType, + fingerCount, + duration, + description + ) + ) + } + } + + fun onPinchTypeSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) { + this.setPinchType(pinchTypes[position]) + } + + fun loadResult(result: PinchPickCoordinateResult) { + viewModelScope.launch { + x.value = result.x + y.value = result.y + distance.value = result.distance + pinchType.value = result.pinchType + fingerCount.value = result.fingerCount + duration.value = result.duration + description.value = result.description + } + } + + override fun onCleared() { + bitmap.value?.recycle() + _bitmap.value = null + + super.onCleared() + } + + @Suppress("UNCHECKED_CAST") + class Factory( + private val resourceProvider: ResourceProvider + ) : ViewModelProvider.NewInstanceFactory() { + + override fun create(modelClass: Class): T { + return PinchPickDisplayCoordinateViewModel(resourceProvider) as T + } + } +} diff --git a/app/src/main/java/io/github/sds100/keymapper/actions/sound/SoundsManager.kt b/app/src/main/java/io/github/sds100/keymapper/actions/sound/SoundsManager.kt index 46fb069f05..feb9bdbc62 100644 --- a/app/src/main/java/io/github/sds100/keymapper/actions/sound/SoundsManager.kt +++ b/app/src/main/java/io/github/sds100/keymapper/actions/sound/SoundsManager.kt @@ -2,13 +2,18 @@ package io.github.sds100.keymapper.actions.sound import io.github.sds100.keymapper.system.files.FileAdapter import io.github.sds100.keymapper.system.files.IFile -import io.github.sds100.keymapper.util.* +import io.github.sds100.keymapper.util.Error +import io.github.sds100.keymapper.util.Result +import io.github.sds100.keymapper.util.Success +import io.github.sds100.keymapper.util.onFailure +import io.github.sds100.keymapper.util.onSuccess +import io.github.sds100.keymapper.util.then import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.launch import timber.log.Timber -import java.util.* +import java.util.UUID /** * Created by sds100 on 24/06/2021. diff --git a/app/src/main/java/io/github/sds100/keymapper/actions/swipescreen/SwipePickDisplayCoordinateFragment.kt b/app/src/main/java/io/github/sds100/keymapper/actions/swipescreen/SwipePickDisplayCoordinateFragment.kt index 84d278079e..a7eb2006b8 100644 --- a/app/src/main/java/io/github/sds100/keymapper/actions/swipescreen/SwipePickDisplayCoordinateFragment.kt +++ b/app/src/main/java/io/github/sds100/keymapper/actions/swipescreen/SwipePickDisplayCoordinateFragment.kt @@ -29,7 +29,6 @@ import kotlinx.coroutines.flow.collectLatest import kotlinx.serialization.decodeFromString import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json -import timber.log.Timber class SwipePickDisplayCoordinateFragment : Fragment() { companion object { diff --git a/app/src/main/java/io/github/sds100/keymapper/actions/swipescreen/SwipePickDisplayCoordinateViewModel.kt b/app/src/main/java/io/github/sds100/keymapper/actions/swipescreen/SwipePickDisplayCoordinateViewModel.kt index 57a9bb2d6e..24dca4d491 100644 --- a/app/src/main/java/io/github/sds100/keymapper/actions/swipescreen/SwipePickDisplayCoordinateViewModel.kt +++ b/app/src/main/java/io/github/sds100/keymapper/actions/swipescreen/SwipePickDisplayCoordinateViewModel.kt @@ -1,7 +1,9 @@ package io.github.sds100.keymapper.actions.swipescreen +import android.accessibilityservice.GestureDescription import android.graphics.Bitmap import android.graphics.Point +import android.os.Build import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.viewModelScope @@ -9,25 +11,25 @@ import io.github.sds100.keymapper.R import io.github.sds100.keymapper.util.ui.* import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch -import timber.log.Timber import kotlin.math.roundToInt enum class ScreenshotTouchType { START, END } + class SwipePickDisplayCoordinateViewModel( resourceProvider: ResourceProvider ) : ViewModel(), ResourceProvider by resourceProvider, PopupViewModel by PopupViewModelImpl() { - public val screenshotTouchTypeStart = ScreenshotTouchType.START; - public val screenshotTouchTypeEnd = ScreenshotTouchType.END; + val screenshotTouchTypeStart = ScreenshotTouchType.START + val screenshotTouchTypeEnd = ScreenshotTouchType.END private val xStart = MutableStateFlow(null) private val yStart = MutableStateFlow(null) private val xEnd = MutableStateFlow(null) private val yEnd = MutableStateFlow(null) private val fingerCount = MutableStateFlow(1) - private val duration = MutableStateFlow(null) + private val duration = MutableStateFlow(200) private val _bitmap = MutableStateFlow(null) private val _returnResult = MutableSharedFlow() @@ -65,50 +67,89 @@ class SwipePickDisplayCoordinateViewModel( it.toString() }.stateIn(viewModelScope, SharingStarted.Lazily, null) + val fingerCountError: StateFlow = fingerCount.map { count -> + if (count == null) { + return@map resourceProvider.getString(R.string.error_cant_be_empty) + } + + if (count <= 0) { + return@map resourceProvider.getString(R.string.error_swipe_screen_fingercount_must_be_more_than_zero) + } + + var maxFingerCount = 10 + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + maxFingerCount = GestureDescription.getMaxStrokeCount() + } + + if (count > maxFingerCount) { + return@map resourceProvider.getString( + R.string.error_swipe_screen_must_be_ten_or_less_fingers, + arrayOf(maxFingerCount) + ) + } + + null + }.stateIn(viewModelScope, SharingStarted.Lazily, null) + val durationString = duration.map { it ?: return@map "" it.toString() }.stateIn(viewModelScope, SharingStarted.Lazily, null) + val durationError: StateFlow = duration.map { d -> + if (d == null) { + return@map resourceProvider.getString(R.string.error_cant_be_empty) + } + + if (d <= 0) { + return@map resourceProvider.getString(R.string.error_swipe_screen_duration_must_be_more_than_zero) + } + + null + }.stateIn(viewModelScope, SharingStarted.Lazily, null) + val bitmap = _bitmap.asStateFlow() val returnResult = _returnResult.asSharedFlow() - val isSelectStartEndSwitchEnabled:StateFlow = combine(bitmap) { - bitmap?.value != null + val isSelectStartEndSwitchEnabled: StateFlow = combine(bitmap) { + bitmap.value != null }.stateIn(viewModelScope, SharingStarted.Lazily, false) - private val isCoordinatesValid: StateFlow = combine(xStart, yStart, xEnd, yEnd) { xStart, yStart, xEnd, yEnd -> - xStart ?: return@combine false - yStart ?: return@combine false - xEnd ?: return@combine false - yEnd ?: return@combine false + private val isCoordinatesValid: StateFlow = + combine(xStart, yStart, xEnd, yEnd) { xStart, yStart, xEnd, yEnd -> + xStart ?: return@combine false + yStart ?: return@combine false + xEnd ?: return@combine false + yEnd ?: return@combine false - xStart >= 0 && yStart >= 0 && xEnd >= 0 && yEnd >= 0 - }.stateIn(viewModelScope, SharingStarted.Lazily, false) + xStart >= 0 && yStart >= 0 && xEnd >= 0 && yEnd >= 0 + }.stateIn(viewModelScope, SharingStarted.Lazily, false) - private val isOptionsValid: StateFlow = combine(fingerCount, duration) { fingerCount, duration -> - fingerCount ?: return@combine false - duration ?: return@combine false + private val isOptionsValid: StateFlow = + combine(fingerCount, duration) { fingerCount, duration -> + fingerCount ?: return@combine false + duration ?: return@combine false - fingerCount >= 1 && duration > 0 - }.stateIn(viewModelScope, SharingStarted.Lazily, false) + fingerCount > 0 && duration > 0 + }.stateIn(viewModelScope, SharingStarted.Lazily, false) - val isDoneButtonEnabled: StateFlow = combine(isCoordinatesValid, isOptionsValid) { isCoordinatesValid, isOptionsValid -> - isCoordinatesValid && isOptionsValid - }.stateIn(viewModelScope, SharingStarted.Lazily, false) + val isDoneButtonEnabled: StateFlow = + combine(isCoordinatesValid, isOptionsValid) { isCoordinatesValid, isOptionsValid -> + isCoordinatesValid && isOptionsValid + }.stateIn(viewModelScope, SharingStarted.Lazily, false) fun selectedScreenshot(newBitmap: Bitmap, displaySize: Point) { - - _screenshotTouchType.value = ScreenshotTouchType.START; + _screenshotTouchType.value = ScreenshotTouchType.START //check whether the height and width of the bitmap match the display size, even when it is rotated. if ( (displaySize.x != newBitmap.width - && displaySize.y != newBitmap.height) && + && displaySize.y != newBitmap.height) && (displaySize.y != newBitmap.width - && displaySize.x != newBitmap.height) + && displaySize.x != newBitmap.height) ) { viewModelScope.launch { val snackBar = PopupUi.SnackBar( @@ -148,7 +189,7 @@ class SwipePickDisplayCoordinateViewModel( this.duration.value = duration.toIntOrNull() } - fun setStartOrEndCoordinates(isChecked:Boolean, type: ScreenshotTouchType) { + fun setStartOrEndCoordinates(isChecked: Boolean, type: ScreenshotTouchType) { if (isChecked) this._screenshotTouchType.value = type } @@ -190,7 +231,17 @@ class SwipePickDisplayCoordinateViewModel( ) ) ?: return@launch - _returnResult.emit(SwipePickCoordinateResult(xStart, yStart, xEnd, yEnd, fingerCount, duration, description)) + _returnResult.emit( + SwipePickCoordinateResult( + xStart, + yStart, + xEnd, + yEnd, + fingerCount, + duration, + description + ) + ) } } diff --git a/app/src/main/java/io/github/sds100/keymapper/backup/BackupManager.kt b/app/src/main/java/io/github/sds100/keymapper/backup/BackupManager.kt index e3a3ea2463..d678de8c29 100644 --- a/app/src/main/java/io/github/sds100/keymapper/backup/BackupManager.kt +++ b/app/src/main/java/io/github/sds100/keymapper/backup/BackupManager.kt @@ -13,13 +13,13 @@ import io.github.sds100.keymapper.data.db.AppDatabase import io.github.sds100.keymapper.data.entities.ActionEntity import io.github.sds100.keymapper.data.entities.ConstraintEntity import io.github.sds100.keymapper.data.entities.Extra +import io.github.sds100.keymapper.data.entities.FingerprintMapEntity +import io.github.sds100.keymapper.data.entities.KeyMapEntity import io.github.sds100.keymapper.data.migration.* import io.github.sds100.keymapper.data.migration.fingerprintmaps.FingerprintMapMigration_0_1 import io.github.sds100.keymapper.data.migration.fingerprintmaps.FingerprintMapMigration_1_2 import io.github.sds100.keymapper.data.repositories.PreferenceRepository -import io.github.sds100.keymapper.data.entities.FingerprintMapEntity import io.github.sds100.keymapper.mappings.fingerprintmaps.FingerprintMapRepository -import io.github.sds100.keymapper.data.entities.KeyMapEntity import io.github.sds100.keymapper.mappings.keymaps.KeyMapRepository import io.github.sds100.keymapper.system.files.FileAdapter import io.github.sds100.keymapper.system.files.IFile diff --git a/app/src/main/java/io/github/sds100/keymapper/constraints/ChooseConstraintFragment.kt b/app/src/main/java/io/github/sds100/keymapper/constraints/ChooseConstraintFragment.kt index 14ebfa8286..acf511c1c0 100644 --- a/app/src/main/java/io/github/sds100/keymapper/constraints/ChooseConstraintFragment.kt +++ b/app/src/main/java/io/github/sds100/keymapper/constraints/ChooseConstraintFragment.kt @@ -12,7 +12,11 @@ import io.github.sds100.keymapper.simpleGrid import io.github.sds100.keymapper.util.Inject import io.github.sds100.keymapper.util.State import io.github.sds100.keymapper.util.launchRepeatOnLifecycle -import io.github.sds100.keymapper.util.ui.* +import io.github.sds100.keymapper.util.ui.RecyclerViewUtils +import io.github.sds100.keymapper.util.ui.SimpleListItem +import io.github.sds100.keymapper.util.ui.SimpleRecyclerViewFragment +import io.github.sds100.keymapper.util.ui.setupNavigation +import io.github.sds100.keymapper.util.ui.showPopups import io.github.sds100.keymapper.util.viewLifecycleScope import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.collectLatest diff --git a/app/src/main/java/io/github/sds100/keymapper/constraints/ChooseConstraintViewModel.kt b/app/src/main/java/io/github/sds100/keymapper/constraints/ChooseConstraintViewModel.kt index c7650ac438..a2a3818f6e 100644 --- a/app/src/main/java/io/github/sds100/keymapper/constraints/ChooseConstraintViewModel.kt +++ b/app/src/main/java/io/github/sds100/keymapper/constraints/ChooseConstraintViewModel.kt @@ -288,6 +288,7 @@ class ChooseConstraintViewModel( ChooseConstraintType.WIFI_DISCONNECTED -> _returnResult.emit(Constraint.WifiDisconnected(chosenSSID)) + else -> Unit } } @@ -307,6 +308,7 @@ class ChooseConstraintViewModel( ChooseConstraintType.IME_NOT_CHOSEN -> _returnResult.emit(Constraint.ImeNotChosen(imeInfo.id, imeInfo.label)) + else -> Unit } } @@ -351,10 +353,12 @@ class ChooseConstraintViewModel( device.address, device.name ) + ChooseConstraintType.BT_DEVICE_DISCONNECTED -> Constraint.BtDeviceDisconnected( device.address, device.name ) + else -> throw IllegalArgumentException("Don't know how to create $type constraint after choosing app") } @@ -370,12 +374,15 @@ class ChooseConstraintViewModel( ChooseConstraintType.APP_IN_FOREGROUND -> Constraint.AppInForeground( packageName ) + ChooseConstraintType.APP_NOT_IN_FOREGROUND -> Constraint.AppNotInForeground( packageName ) + ChooseConstraintType.APP_PLAYING_MEDIA -> Constraint.AppPlayingMedia( packageName ) + ChooseConstraintType.APP_NOT_PLAYING_MEDIA -> Constraint.AppNotPlayingMedia( packageName ) diff --git a/app/src/main/java/io/github/sds100/keymapper/constraints/ConfigConstraintsViewModel.kt b/app/src/main/java/io/github/sds100/keymapper/constraints/ConfigConstraintsViewModel.kt index 4dc07fdb97..0d04f97368 100644 --- a/app/src/main/java/io/github/sds100/keymapper/constraints/ConfigConstraintsViewModel.kt +++ b/app/src/main/java/io/github/sds100/keymapper/constraints/ConfigConstraintsViewModel.kt @@ -4,11 +4,30 @@ import io.github.sds100.keymapper.R import io.github.sds100.keymapper.mappings.ConfigMappingUseCase import io.github.sds100.keymapper.mappings.DisplayConstraintUseCase import io.github.sds100.keymapper.mappings.Mapping -import io.github.sds100.keymapper.util.* -import io.github.sds100.keymapper.util.ui.* +import io.github.sds100.keymapper.util.Error +import io.github.sds100.keymapper.util.State +import io.github.sds100.keymapper.util.getFullMessage +import io.github.sds100.keymapper.util.ifIsData +import io.github.sds100.keymapper.util.isFixable +import io.github.sds100.keymapper.util.mapData +import io.github.sds100.keymapper.util.ui.IconInfo +import io.github.sds100.keymapper.util.ui.NavDestination +import io.github.sds100.keymapper.util.ui.NavigationViewModel +import io.github.sds100.keymapper.util.ui.NavigationViewModelImpl +import io.github.sds100.keymapper.util.ui.PopupUi +import io.github.sds100.keymapper.util.ui.PopupViewModel +import io.github.sds100.keymapper.util.ui.PopupViewModelImpl +import io.github.sds100.keymapper.util.ui.ResourceProvider +import io.github.sds100.keymapper.util.ui.TintType +import io.github.sds100.keymapper.util.ui.navigate +import io.github.sds100.keymapper.util.ui.showPopup import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.flow.* +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.collectLatest +import kotlinx.coroutines.flow.firstOrNull import kotlinx.coroutines.launch /** diff --git a/app/src/main/java/io/github/sds100/keymapper/constraints/Constraint.kt b/app/src/main/java/io/github/sds100/keymapper/constraints/Constraint.kt index 00e362619a..72f19a55db 100644 --- a/app/src/main/java/io/github/sds100/keymapper/constraints/Constraint.kt +++ b/app/src/main/java/io/github/sds100/keymapper/constraints/Constraint.kt @@ -8,7 +8,7 @@ import io.github.sds100.keymapper.system.display.Orientation import io.github.sds100.keymapper.util.getKey import io.github.sds100.keymapper.util.valueOrNull import kotlinx.serialization.Serializable -import java.util.* +import java.util.UUID /** * Created by sds100 on 03/03/2021. @@ -284,6 +284,7 @@ object ConstraintEntityMapper { ConstraintEntity.FLASHLIGHT_OFF, Extra(ConstraintEntity.EXTRA_FLASHLIGHT_CAMERA_LENS, LENS_MAP[constraint.lens]!!) ) + is Constraint.FlashlightOn -> ConstraintEntity( ConstraintEntity.FLASHLIGHT_ON, Extra(ConstraintEntity.EXTRA_FLASHLIGHT_CAMERA_LENS, LENS_MAP[constraint.lens]!!) diff --git a/app/src/main/java/io/github/sds100/keymapper/constraints/ConstraintSnapshot.kt b/app/src/main/java/io/github/sds100/keymapper/constraints/ConstraintSnapshot.kt index 2f899c3d8d..53a66497be 100644 --- a/app/src/main/java/io/github/sds100/keymapper/constraints/ConstraintSnapshot.kt +++ b/app/src/main/java/io/github/sds100/keymapper/constraints/ConstraintSnapshot.kt @@ -60,6 +60,7 @@ class ConstraintSnapshotImpl( ConstraintMode.AND -> { constraintState.constraints.all { isSatisfied(it) } } + ConstraintMode.OR -> { constraintState.constraints.any { isSatisfied(it) } } @@ -73,21 +74,27 @@ class ConstraintSnapshotImpl( is Constraint.AppNotInForeground -> appInForeground != constraint.packageName is Constraint.AppPlayingMedia -> appsPlayingMedia.contains(constraint.packageName) + is Constraint.AppNotPlayingMedia -> appsPlayingMedia.none { it == constraint.packageName } + Constraint.MediaPlaying -> appsPlayingMedia.isNotEmpty() Constraint.NoMediaPlaying -> appsPlayingMedia.isEmpty() is Constraint.BtDeviceConnected -> { connectedBluetoothDevices.any { it.address == constraint.bluetoothAddress } } + is Constraint.BtDeviceDisconnected -> { connectedBluetoothDevices.none { it.address == constraint.bluetoothAddress } } + is Constraint.OrientationCustom -> orientation == constraint.orientation Constraint.OrientationLandscape -> orientation == Orientation.ORIENTATION_90 || orientation == Orientation.ORIENTATION_270 + Constraint.OrientationPortrait -> orientation == Orientation.ORIENTATION_0 || orientation == Orientation.ORIENTATION_180 + Constraint.ScreenOff -> !isScreenOn Constraint.ScreenOn -> isScreenOn is Constraint.FlashlightOff -> !cameraAdapter.isFlashlightOn(constraint.lens) @@ -101,6 +108,7 @@ class ConstraintSnapshotImpl( connectedWifiSSID == constraint.ssid } } + is Constraint.WifiDisconnected -> if (constraint.ssid == null) { //connected to no network diff --git a/app/src/main/java/io/github/sds100/keymapper/constraints/ConstraintUiHelper.kt b/app/src/main/java/io/github/sds100/keymapper/constraints/ConstraintUiHelper.kt index 56c2874a2a..67584a0c85 100644 --- a/app/src/main/java/io/github/sds100/keymapper/constraints/ConstraintUiHelper.kt +++ b/app/src/main/java/io/github/sds100/keymapper/constraints/ConstraintUiHelper.kt @@ -104,6 +104,7 @@ class ConstraintUiHelper( getString(R.string.constraint_wifi_connected_description, constraint.ssid) } } + is Constraint.WifiDisconnected -> { if (constraint.ssid == null) { getString(R.string.constraint_wifi_disconnected_any_description) @@ -111,6 +112,7 @@ class ConstraintUiHelper( getString(R.string.constraint_wifi_disconnected_description, constraint.ssid) } } + Constraint.WifiOff -> getString(R.string.constraint_wifi_off) Constraint.WifiOn -> getString(R.string.constraint_wifi_on) @@ -129,6 +131,7 @@ class ConstraintUiHelper( getString(R.string.constraint_ime_not_chosen_description, label) } + Constraint.DeviceIsLocked -> getString(R.string.constraint_device_is_locked) Constraint.DeviceIsUnlocked -> getString(R.string.constraint_device_is_unlocked) Constraint.InPhoneCall -> getString(R.string.constraint_in_phone_call) @@ -211,14 +214,17 @@ class ConstraintUiHelper( drawable = getDrawable(R.drawable.ic_outline_wifi_24), tintType = TintType.OnSurface ) + is Constraint.WifiDisconnected -> IconInfo( drawable = getDrawable(R.drawable.ic_outline_signal_wifi_statusbar_null_24), tintType = TintType.OnSurface ) + Constraint.WifiOff -> IconInfo( drawable = getDrawable(R.drawable.ic_outline_wifi_off_24), tintType = TintType.OnSurface ) + Constraint.WifiOn -> IconInfo( drawable = getDrawable(R.drawable.ic_outline_wifi_24), tintType = TintType.OnSurface @@ -243,22 +249,27 @@ class ConstraintUiHelper( drawable = getDrawable(R.drawable.ic_outline_lock_open_24), tintType = TintType.OnSurface ) + Constraint.InPhoneCall -> IconInfo( drawable = getDrawable(R.drawable.ic_outline_call_24), tintType = TintType.OnSurface ) + Constraint.NotInPhoneCall -> IconInfo( drawable = getDrawable(R.drawable.ic_baseline_call_end_24), tintType = TintType.OnSurface ) + Constraint.PhoneRinging -> IconInfo( drawable = getDrawable(R.drawable.ic_baseline_ring_volume_24), tintType = TintType.OnSurface ) + Constraint.Charging -> IconInfo( drawable = getDrawable(R.drawable.ic_baseline_battery_charging_full_24), tintType = TintType.OnSurface ) + Constraint.Discharging -> IconInfo( drawable = getDrawable(R.drawable.ic_battery_70), tintType = TintType.OnSurface diff --git a/app/src/main/java/io/github/sds100/keymapper/constraints/CreateConstraintUseCase.kt b/app/src/main/java/io/github/sds100/keymapper/constraints/CreateConstraintUseCase.kt index 3791482b19..586594f006 100644 --- a/app/src/main/java/io/github/sds100/keymapper/constraints/CreateConstraintUseCase.kt +++ b/app/src/main/java/io/github/sds100/keymapper/constraints/CreateConstraintUseCase.kt @@ -32,6 +32,7 @@ class CreateConstraintUseCaseImpl( if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP_MR1) { return Error.SdkVersionTooLow(minSdk = Build.VERSION_CODES.LOLLIPOP_MR1) } + else -> Unit } diff --git a/app/src/main/java/io/github/sds100/keymapper/constraints/GetConstraintErrorUseCase.kt b/app/src/main/java/io/github/sds100/keymapper/constraints/GetConstraintErrorUseCase.kt index 511aee07a3..256e9a85b6 100644 --- a/app/src/main/java/io/github/sds100/keymapper/constraints/GetConstraintErrorUseCase.kt +++ b/app/src/main/java/io/github/sds100/keymapper/constraints/GetConstraintErrorUseCase.kt @@ -100,6 +100,7 @@ class GetConstraintErrorUseCaseImpl( return Error.PermissionDenied(Permission.READ_PHONE_STATE) } } + else -> Unit } diff --git a/app/src/main/java/io/github/sds100/keymapper/data/Keys.kt b/app/src/main/java/io/github/sds100/keymapper/data/Keys.kt index 48d1b9de5c..33c080e9bf 100644 --- a/app/src/main/java/io/github/sds100/keymapper/data/Keys.kt +++ b/app/src/main/java/io/github/sds100/keymapper/data/Keys.kt @@ -15,14 +15,14 @@ object Keys { val showImePickerNotification = booleanPreferencesKey("pref_show_ime_notification") val showToggleKeymapsNotification = booleanPreferencesKey("pref_show_remappings_notification") val showToggleKeyboardNotification = - booleanPreferencesKey("pref_toggle_key_mapper_keyboard_notification") + booleanPreferencesKey("pref_toggle_key_mapper_keyboard_notification") val devicesThatChangeIme = stringSetPreferencesKey("pref_devices_that_change_ime") val changeImeOnDeviceConnect = - booleanPreferencesKey("pref_auto_change_ime_on_connect_disconnect") + booleanPreferencesKey("pref_auto_change_ime_on_connect_disconnect") val changeImeOnInputFocus = booleanPreferencesKey("pref_change_ime_on_input_focus") val showToastWhenAutoChangingIme = - booleanPreferencesKey("pref_show_toast_when_auto_changing_ime") + booleanPreferencesKey("pref_show_toast_when_auto_changing_ime") val devicesThatShowImePicker = stringSetPreferencesKey("pref_devices_show_ime_picker") val showImePickerOnDeviceConnect = booleanPreferencesKey("pref_auto_show_ime_picker") @@ -36,27 +36,27 @@ object Keys { val defaultSequenceTriggerTimeout = intPreferencesKey("pref_sequence_trigger_timeout") val defaultHoldDownDuration = intPreferencesKey("pref_hold_down_duration") val toggleKeyboardOnToggleKeymaps = - booleanPreferencesKey("key_toggle_keyboard_on_pause_resume_keymaps") + booleanPreferencesKey("key_toggle_keyboard_on_pause_resume_keymaps") val automaticBackupLocation = stringPreferencesKey("pref_automatic_backup_location") val mappingsPaused = booleanPreferencesKey("pref_keymaps_paused") val hideHomeScreenAlerts = booleanPreferencesKey("pref_hide_home_screen_alerts") val acknowledgedGuiKeyboard = booleanPreferencesKey("pref_acknowledged_gui_keyboard") val showDeviceDescriptors = booleanPreferencesKey("pref_show_device_descriptors") val approvedFingerprintFeaturePrompt = - booleanPreferencesKey("pref_approved_fingerprint_feature_prompt") + booleanPreferencesKey("pref_approved_fingerprint_feature_prompt") val shownParallelTriggerOrderExplanation = - booleanPreferencesKey("key_shown_parallel_trigger_order_warning") + booleanPreferencesKey("key_shown_parallel_trigger_order_warning") val shownSequenceTriggerExplanation = - booleanPreferencesKey("key_shown_sequence_trigger_explanation_dialog") + booleanPreferencesKey("key_shown_sequence_trigger_explanation_dialog") val lastInstalledVersionCodeHomeScreen = - intPreferencesKey("last_installed_version_home_screen") + intPreferencesKey("last_installed_version_home_screen") val lastInstalledVersionCodeBackground = - intPreferencesKey("last_installed_version_accessibility_service") + intPreferencesKey("last_installed_version_accessibility_service") val shownQuickStartGuideHint = booleanPreferencesKey("tap_target_quick_start_guide") val fingerprintGesturesAvailable = - booleanPreferencesKey("fingerprint_gestures_available") + booleanPreferencesKey("fingerprint_gestures_available") val approvedSetupChosenDevicesAgain = booleanPreferencesKey("pref_approved_new_choose_devices_settings") diff --git a/app/src/main/java/io/github/sds100/keymapper/data/PreferenceDefaults.kt b/app/src/main/java/io/github/sds100/keymapper/data/PreferenceDefaults.kt index 1ce0c63483..fbaaacd311 100644 --- a/app/src/main/java/io/github/sds100/keymapper/data/PreferenceDefaults.kt +++ b/app/src/main/java/io/github/sds100/keymapper/data/PreferenceDefaults.kt @@ -4,17 +4,17 @@ package io.github.sds100.keymapper.data * Created by sds100 on 30/01/21. */ - object PreferenceDefaults { - const val DARK_THEME = "2" +object PreferenceDefaults { + const val DARK_THEME = "2" - const val SHOW_TOAST_WHEN_AUTO_CHANGE_IME = true + const val SHOW_TOAST_WHEN_AUTO_CHANGE_IME = true - const val FORCE_VIBRATE = false - const val LONG_PRESS_DELAY = 500 - const val DOUBLE_PRESS_DELAY = 300 - const val VIBRATION_DURATION = 200 - const val REPEAT_DELAY = 400 - const val REPEAT_RATE = 50 - const val SEQUENCE_TRIGGER_TIMEOUT = 1000 - const val HOLD_DOWN_DURATION = 1000 + const val FORCE_VIBRATE = false + const val LONG_PRESS_DELAY = 500 + const val DOUBLE_PRESS_DELAY = 300 + const val VIBRATION_DURATION = 200 + const val REPEAT_DELAY = 400 + const val REPEAT_RATE = 50 + const val SEQUENCE_TRIGGER_TIMEOUT = 1000 + const val HOLD_DOWN_DURATION = 1000 } \ No newline at end of file diff --git a/app/src/main/java/io/github/sds100/keymapper/data/db/AppDatabase.kt b/app/src/main/java/io/github/sds100/keymapper/data/db/AppDatabase.kt index 3ef2e64468..c1e4be2f05 100644 --- a/app/src/main/java/io/github/sds100/keymapper/data/db/AppDatabase.kt +++ b/app/src/main/java/io/github/sds100/keymapper/data/db/AppDatabase.kt @@ -15,10 +15,19 @@ import io.github.sds100.keymapper.data.db.typeconverter.ActionListTypeConverter import io.github.sds100.keymapper.data.db.typeconverter.ConstraintListTypeConverter import io.github.sds100.keymapper.data.db.typeconverter.ExtraListTypeConverter import io.github.sds100.keymapper.data.db.typeconverter.TriggerTypeConverter -import io.github.sds100.keymapper.data.entities.LogEntryEntity -import io.github.sds100.keymapper.data.migration.* import io.github.sds100.keymapper.data.entities.FingerprintMapEntity import io.github.sds100.keymapper.data.entities.KeyMapEntity +import io.github.sds100.keymapper.data.entities.LogEntryEntity +import io.github.sds100.keymapper.data.migration.Migration_10_11 +import io.github.sds100.keymapper.data.migration.Migration_11_12 +import io.github.sds100.keymapper.data.migration.Migration_1_2 +import io.github.sds100.keymapper.data.migration.Migration_2_3 +import io.github.sds100.keymapper.data.migration.Migration_3_4 +import io.github.sds100.keymapper.data.migration.Migration_4_5 +import io.github.sds100.keymapper.data.migration.Migration_5_6 +import io.github.sds100.keymapper.data.migration.Migration_6_7 +import io.github.sds100.keymapper.data.migration.Migration_8_9 +import io.github.sds100.keymapper.data.migration.Migration_9_10 /** * Created by sds100 on 24/01/2020. diff --git a/app/src/main/java/io/github/sds100/keymapper/data/db/SeedDatabaseWorker.kt b/app/src/main/java/io/github/sds100/keymapper/data/db/SeedDatabaseWorker.kt index f6589642fd..cf220e69e2 100644 --- a/app/src/main/java/io/github/sds100/keymapper/data/db/SeedDatabaseWorker.kt +++ b/app/src/main/java/io/github/sds100/keymapper/data/db/SeedDatabaseWorker.kt @@ -24,11 +24,11 @@ class SeedDatabaseWorker( for (i in 1..100) { yield( KeyMapEntity( - id = 0, - trigger = createRandomTrigger(), - actionList = createRandomActionList(), - flags = 0 - ) + id = 0, + trigger = createRandomTrigger(), + actionList = createRandomActionList(), + flags = 0 + ) ) } }.toList().toTypedArray() @@ -45,25 +45,28 @@ class SeedDatabaseWorker( val keys = sequence { yield( TriggerEntity.KeyEntity( - KeyEvent.KEYCODE_CTRL_LEFT, - TriggerEntity.KeyEntity.DEVICE_ID_THIS_DEVICE, + KeyEvent.KEYCODE_CTRL_LEFT, + TriggerEntity.KeyEntity.DEVICE_ID_THIS_DEVICE, null, - TriggerEntity.SHORT_PRESS - )) + TriggerEntity.SHORT_PRESS + ) + ) yield( TriggerEntity.KeyEntity( - KeyEvent.KEYCODE_ALT_LEFT, - TriggerEntity.KeyEntity.DEVICE_ID_ANY_DEVICE, + KeyEvent.KEYCODE_ALT_LEFT, + TriggerEntity.KeyEntity.DEVICE_ID_ANY_DEVICE, null, - TriggerEntity.LONG_PRESS - )) + TriggerEntity.LONG_PRESS + ) + ) yield( TriggerEntity.KeyEntity( - KeyEvent.KEYCODE_DEL, - TriggerEntity.KeyEntity.DEVICE_ID_THIS_DEVICE, + KeyEvent.KEYCODE_DEL, + TriggerEntity.KeyEntity.DEVICE_ID_THIS_DEVICE, null, - TriggerEntity.SHORT_PRESS - )) + TriggerEntity.SHORT_PRESS + ) + ) }.toList() return TriggerEntity(keys, mode = TriggerEntity.SEQUENCE, flags = TriggerEntity.TRIGGER_FLAG_VIBRATE) @@ -73,15 +76,15 @@ class SeedDatabaseWorker( return sequence { yield( ActionEntity( - type = ActionEntity.Type.APP, - data = Constants.PACKAGE_NAME - ) + type = ActionEntity.Type.APP, + data = Constants.PACKAGE_NAME + ) ) yield( ActionEntity( - type = ActionEntity.Type.APP, - data = "this.app.doesnt.exist" - ) + type = ActionEntity.Type.APP, + data = "this.app.doesnt.exist" + ) ) }.toList() } diff --git a/app/src/main/java/io/github/sds100/keymapper/data/entities/ActionEntity.kt b/app/src/main/java/io/github/sds100/keymapper/data/entities/ActionEntity.kt index 4f47173504..f039ba9c4b 100644 --- a/app/src/main/java/io/github/sds100/keymapper/data/entities/ActionEntity.kt +++ b/app/src/main/java/io/github/sds100/keymapper/data/entities/ActionEntity.kt @@ -119,14 +119,14 @@ data class ActionEntity( ActionEntity( type, data, extraList.toMutableList(), flags, uid - ?: UUID.randomUUID().toString() + ?: UUID.randomUUID().toString() ) } } enum class Type { //DONT CHANGE THESE - APP, APP_SHORTCUT, KEY_EVENT, TEXT_BLOCK, URL, SYSTEM_ACTION, TAP_COORDINATE, SWIPE_COORDINATE, INTENT, PHONE_CALL, SOUND + APP, APP_SHORTCUT, KEY_EVENT, TEXT_BLOCK, URL, SYSTEM_ACTION, TAP_COORDINATE, SWIPE_COORDINATE, PINCH_COORDINATE, INTENT, PHONE_CALL, SOUND } constructor( diff --git a/app/src/main/java/io/github/sds100/keymapper/data/entities/KeyMapEntity.kt b/app/src/main/java/io/github/sds100/keymapper/data/entities/KeyMapEntity.kt index 2e2857e666..146d0a11a3 100644 --- a/app/src/main/java/io/github/sds100/keymapper/data/entities/KeyMapEntity.kt +++ b/app/src/main/java/io/github/sds100/keymapper/data/entities/KeyMapEntity.kt @@ -52,7 +52,7 @@ data class KeyMapEntity( @SerializedName(NAME_UID) @ColumnInfo(name = KeyMapDao.KEY_UID) val uid: String = UUID.randomUUID().toString() -) { +) { companion object { //DON'T CHANGE THESE. Used for JSON serialization and parsing. diff --git a/app/src/main/java/io/github/sds100/keymapper/data/entities/LogEntryEntity.kt b/app/src/main/java/io/github/sds100/keymapper/data/entities/LogEntryEntity.kt index 49ad0c7229..905f7b66ca 100644 --- a/app/src/main/java/io/github/sds100/keymapper/data/entities/LogEntryEntity.kt +++ b/app/src/main/java/io/github/sds100/keymapper/data/entities/LogEntryEntity.kt @@ -3,7 +3,6 @@ package io.github.sds100.keymapper.data.entities import androidx.room.ColumnInfo import androidx.room.Entity import androidx.room.PrimaryKey -import com.google.gson.annotations.SerializedName import io.github.sds100.keymapper.data.db.dao.LogEntryDao /** @@ -19,8 +18,8 @@ data class LogEntryEntity( val severity: Int, @ColumnInfo(name = LogEntryDao.KEY_MESSAGE) val message: String -){ - companion object{ +) { + companion object { const val SEVERITY_ERROR = 0 const val SEVERITY_DEBUG = 1 const val SEVERITY_INFO = 2 diff --git a/app/src/main/java/io/github/sds100/keymapper/data/entities/TriggerEntity.kt b/app/src/main/java/io/github/sds100/keymapper/data/entities/TriggerEntity.kt index 3cb56bdfbd..87d3a8975a 100644 --- a/app/src/main/java/io/github/sds100/keymapper/data/entities/TriggerEntity.kt +++ b/app/src/main/java/io/github/sds100/keymapper/data/entities/TriggerEntity.kt @@ -121,7 +121,7 @@ data class TriggerEntity( val flags by it.json.byNullableInt(NAME_FLAGS) val uid by it.json.byNullableString(NAME_UID) - KeyEntity(keycode, deviceId, deviceName, clickType,flags ?: 0, uid ?: UUID.randomUUID().toString()) + KeyEntity(keycode, deviceId, deviceName, clickType, flags ?: 0, uid ?: UUID.randomUUID().toString()) } } } diff --git a/app/src/main/java/io/github/sds100/keymapper/data/migration/MigrationUtils.kt b/app/src/main/java/io/github/sds100/keymapper/data/migration/MigrationUtils.kt index 2d26cc62f9..f883679564 100644 --- a/app/src/main/java/io/github/sds100/keymapper/data/migration/MigrationUtils.kt +++ b/app/src/main/java/io/github/sds100/keymapper/data/migration/MigrationUtils.kt @@ -1,6 +1,5 @@ package io.github.sds100.keymapper.data.migration -import com.google.gson.Gson import com.google.gson.JsonObject /** @@ -20,7 +19,7 @@ object MigrationUtils { migrations .find { it.versionBefore == version } ?.let { - outputJson = it.migrate( outputJson) + outputJson = it.migrate(outputJson) version = it.versionAfter } ?: throw Exception("No migration for version $version to $outputVersion") diff --git a/app/src/main/java/io/github/sds100/keymapper/data/migration/Migration_1_2.kt b/app/src/main/java/io/github/sds100/keymapper/data/migration/Migration_1_2.kt index f1d52c381b..815ba4718d 100644 --- a/app/src/main/java/io/github/sds100/keymapper/data/migration/Migration_1_2.kt +++ b/app/src/main/java/io/github/sds100/keymapper/data/migration/Migration_1_2.kt @@ -35,7 +35,8 @@ object Migration_1_2 { private const val MODE_SEQUENCE = 1 fun migrate(database: SupportSQLiteDatabase) = database.apply { - execSQL(""" + execSQL( + """ CREATE TABLE IF NOT EXISTS `new_keymaps` ( `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `trigger` TEXT NOT NULL, @@ -45,11 +46,22 @@ object Migration_1_2 { `flags` INTEGER NOT NULL, `folder_name` TEXT, `is_enabled` INTEGER NOT NULL) - """.trimIndent()) + """.trimIndent() + ) val query = SupportSQLiteQueryBuilder .builder("keymaps") - .columns(arrayOf("id", "trigger_list", "flags", "is_enabled", "action_type", "action_data", "action_extras")) + .columns( + arrayOf( + "id", + "trigger_list", + "flags", + "is_enabled", + "action_type", + "action_data", + "action_extras" + ) + ) .create() query(query).apply { @@ -126,12 +138,12 @@ object Migration_1_2 { actionListNew.add( createAction2( - actionTypeNew, - actionDataOld, - actionExtrasOld - ?: JsonArray(), - actionFlags - ) + actionTypeNew, + actionDataOld, + actionExtrasOld + ?: JsonArray(), + actionFlags + ) ) } @@ -143,7 +155,8 @@ object Migration_1_2 { """ INSERT INTO 'new_keymaps' ('id', 'trigger', 'action_list', 'constraint_list', 'constraint_mode', 'flags', 'folder_name', 'is_enabled') VALUES ($id, '${gson.toJson(it)}', '${gson.toJson(actionListNew)}', '[]', 1, '$flagsNew', 'NULL', ${isEnabledOld}) - """.trimIndent()) + """.trimIndent() + ) id++ } } diff --git a/app/src/main/java/io/github/sds100/keymapper/data/migration/Migration_3_4.kt b/app/src/main/java/io/github/sds100/keymapper/data/migration/Migration_3_4.kt index a2f360a1ec..8e3e2388ef 100644 --- a/app/src/main/java/io/github/sds100/keymapper/data/migration/Migration_3_4.kt +++ b/app/src/main/java/io/github/sds100/keymapper/data/migration/Migration_3_4.kt @@ -7,8 +7,6 @@ import androidx.sqlite.db.SupportSQLiteQueryBuilder import com.github.salomonbrys.kotson.set import com.google.gson.Gson import com.google.gson.JsonParser -import kotlin.collections.forEach -import kotlin.collections.mutableMapOf import kotlin.collections.set /** diff --git a/app/src/main/java/io/github/sds100/keymapper/data/migration/Migration_9_10.kt b/app/src/main/java/io/github/sds100/keymapper/data/migration/Migration_9_10.kt index 90cfed74ae..124fc8fd80 100644 --- a/app/src/main/java/io/github/sds100/keymapper/data/migration/Migration_9_10.kt +++ b/app/src/main/java/io/github/sds100/keymapper/data/migration/Migration_9_10.kt @@ -67,8 +67,10 @@ object Migration_9_10 { return keyMap } - private fun migrate(trigger: JsonElement, - actionList: JsonArray): MigrateModel { + private fun migrate( + trigger: JsonElement, + actionList: JsonArray + ): MigrateModel { var showToast = false actionList.forEach { diff --git a/app/src/main/java/io/github/sds100/keymapper/data/repositories/RoomFingerprintMapRepository.kt b/app/src/main/java/io/github/sds100/keymapper/data/repositories/RoomFingerprintMapRepository.kt index cf3178e439..41ff7ff992 100644 --- a/app/src/main/java/io/github/sds100/keymapper/data/repositories/RoomFingerprintMapRepository.kt +++ b/app/src/main/java/io/github/sds100/keymapper/data/repositories/RoomFingerprintMapRepository.kt @@ -6,9 +6,18 @@ import io.github.sds100.keymapper.data.entities.Extra import io.github.sds100.keymapper.data.entities.FingerprintMapEntity import io.github.sds100.keymapper.mappings.fingerprintmaps.FingerprintMapRepository import io.github.sds100.keymapper.system.devices.DevicesAdapter -import io.github.sds100.keymapper.util.* +import io.github.sds100.keymapper.util.DefaultDispatcherProvider +import io.github.sds100.keymapper.util.DispatcherProvider +import io.github.sds100.keymapper.util.State +import io.github.sds100.keymapper.util.ifIsData import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.flow.* +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.flowOn +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch import kotlinx.coroutines.withContext diff --git a/app/src/main/java/io/github/sds100/keymapper/data/repositories/RoomKeyMapRepository.kt b/app/src/main/java/io/github/sds100/keymapper/data/repositories/RoomKeyMapRepository.kt index 9fbdcbc989..4ef5bc6c7b 100644 --- a/app/src/main/java/io/github/sds100/keymapper/data/repositories/RoomKeyMapRepository.kt +++ b/app/src/main/java/io/github/sds100/keymapper/data/repositories/RoomKeyMapRepository.kt @@ -3,16 +3,26 @@ package io.github.sds100.keymapper.data.repositories import io.github.sds100.keymapper.data.db.dao.KeyMapDao import io.github.sds100.keymapper.data.entities.ActionEntity import io.github.sds100.keymapper.data.entities.Extra -import io.github.sds100.keymapper.data.entities.TriggerEntity -import io.github.sds100.keymapper.data.migration.* import io.github.sds100.keymapper.data.entities.KeyMapEntity +import io.github.sds100.keymapper.data.entities.TriggerEntity import io.github.sds100.keymapper.mappings.keymaps.KeyMapRepository import io.github.sds100.keymapper.system.devices.DevicesAdapter -import io.github.sds100.keymapper.util.* +import io.github.sds100.keymapper.util.DefaultDispatcherProvider +import io.github.sds100.keymapper.util.DispatcherProvider +import io.github.sds100.keymapper.util.State +import io.github.sds100.keymapper.util.ifIsData +import io.github.sds100.keymapper.util.splitIntoBatches import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.flow.* +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.flowOn +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch -import java.util.* +import java.util.UUID /** * Created by sds100 on 18/03/2021. diff --git a/app/src/main/java/io/github/sds100/keymapper/data/repositories/RoomLogRepository.kt b/app/src/main/java/io/github/sds100/keymapper/data/repositories/RoomLogRepository.kt index a16460db5c..eaecd2a195 100644 --- a/app/src/main/java/io/github/sds100/keymapper/data/repositories/RoomLogRepository.kt +++ b/app/src/main/java/io/github/sds100/keymapper/data/repositories/RoomLogRepository.kt @@ -6,7 +6,14 @@ import io.github.sds100.keymapper.logging.LogRepository import io.github.sds100.keymapper.util.State import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.flow.* +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.filter +import kotlinx.coroutines.flow.flowOn +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch /** diff --git a/app/src/main/java/io/github/sds100/keymapper/data/repositories/SettingsPreferenceRepository.kt b/app/src/main/java/io/github/sds100/keymapper/data/repositories/SettingsPreferenceRepository.kt index 0e500af554..430cdcefbe 100644 --- a/app/src/main/java/io/github/sds100/keymapper/data/repositories/SettingsPreferenceRepository.kt +++ b/app/src/main/java/io/github/sds100/keymapper/data/repositories/SettingsPreferenceRepository.kt @@ -13,8 +13,8 @@ import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch class SettingsPreferenceRepository( - context: Context, - private val coroutineScope: CoroutineScope + context: Context, + private val coroutineScope: CoroutineScope ) : PreferenceRepository { companion object { @@ -24,13 +24,13 @@ class SettingsPreferenceRepository( private val ctx = context.applicationContext private val sharedPreferencesMigration = SharedPreferencesMigration( - ctx, - DEFAULT_SHARED_PREFS_NAME + ctx, + DEFAULT_SHARED_PREFS_NAME ) private val Context.dataStore by preferencesDataStore( - name = "preferences", - produceMigrations = { listOf(sharedPreferencesMigration) } + name = "preferences", + produceMigrations = { listOf(sharedPreferencesMigration) } ) private val dataStore = ctx.dataStore diff --git a/app/src/main/java/io/github/sds100/keymapper/home/FixAppKillingActivity.kt b/app/src/main/java/io/github/sds100/keymapper/home/FixAppKillingActivity.kt index b808400d19..7e2b24dba4 100644 --- a/app/src/main/java/io/github/sds100/keymapper/home/FixAppKillingActivity.kt +++ b/app/src/main/java/io/github/sds100/keymapper/home/FixAppKillingActivity.kt @@ -26,7 +26,7 @@ class FixAppKillingActivity : AppIntro2() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - + viewModel.showPopups(this, findViewById(R.id.background)) isSkipButtonEnabled = false diff --git a/app/src/main/java/io/github/sds100/keymapper/home/HomeFragment.kt b/app/src/main/java/io/github/sds100/keymapper/home/HomeFragment.kt index 3f4975745e..d9675617f6 100644 --- a/app/src/main/java/io/github/sds100/keymapper/home/HomeFragment.kt +++ b/app/src/main/java/io/github/sds100/keymapper/home/HomeFragment.kt @@ -9,6 +9,7 @@ import android.view.View import android.view.ViewGroup import androidx.activity.addCallback import androidx.activity.result.contract.ActivityResultContracts +import androidx.activity.result.contract.ActivityResultContracts.CreateDocument import androidx.core.view.isVisible import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels @@ -28,7 +29,11 @@ import io.github.sds100.keymapper.fixError import io.github.sds100.keymapper.success import io.github.sds100.keymapper.system.files.FileUtils import io.github.sds100.keymapper.system.url.UrlUtils -import io.github.sds100.keymapper.util.* +import io.github.sds100.keymapper.util.Inject +import io.github.sds100.keymapper.util.QuickStartGuideTapTarget +import io.github.sds100.keymapper.util.launchRepeatOnLifecycle +import io.github.sds100.keymapper.util.str +import io.github.sds100.keymapper.util.strArray import io.github.sds100.keymapper.util.ui.TextListItem import io.github.sds100.keymapper.util.ui.setupNavigation import io.github.sds100.keymapper.util.ui.showPopups @@ -49,21 +54,21 @@ class HomeFragment : Fragment() { get() = _binding!! private val backupMappingsLauncher = - registerForActivityResult(ActivityResultContracts.CreateDocument()) { + registerForActivityResult(CreateDocument("todo/todo")) { it ?: return@registerForActivityResult homeViewModel.onChoseBackupFile(it.toString()) } private val backupFingerprintMapsLauncher = - registerForActivityResult(ActivityResultContracts.CreateDocument()) { + registerForActivityResult(CreateDocument("todo/todo")) { it ?: return@registerForActivityResult homeViewModel.backupFingerprintMaps(it.toString()) } private val backupKeyMapsLauncher = - registerForActivityResult(ActivityResultContracts.CreateDocument()) { + registerForActivityResult(CreateDocument("todo/todo")) { it ?: return@registerForActivityResult homeViewModel.backupSelectedKeyMaps(it.toString()) diff --git a/app/src/main/java/io/github/sds100/keymapper/home/HomeMenuViewModel.kt b/app/src/main/java/io/github/sds100/keymapper/home/HomeMenuViewModel.kt index 33e9b51460..20076c6275 100644 --- a/app/src/main/java/io/github/sds100/keymapper/home/HomeMenuViewModel.kt +++ b/app/src/main/java/io/github/sds100/keymapper/home/HomeMenuViewModel.kt @@ -4,9 +4,24 @@ import io.github.sds100.keymapper.R import io.github.sds100.keymapper.mappings.PauseMappingsUseCase import io.github.sds100.keymapper.system.accessibility.ServiceState import io.github.sds100.keymapper.system.inputmethod.ShowInputMethodPickerUseCase -import io.github.sds100.keymapper.util.ui.* +import io.github.sds100.keymapper.util.ui.NavDestination +import io.github.sds100.keymapper.util.ui.NavigationViewModel +import io.github.sds100.keymapper.util.ui.NavigationViewModelImpl +import io.github.sds100.keymapper.util.ui.PopupUi +import io.github.sds100.keymapper.util.ui.PopupViewModel +import io.github.sds100.keymapper.util.ui.PopupViewModelImpl +import io.github.sds100.keymapper.util.ui.ResourceProvider +import io.github.sds100.keymapper.util.ui.ViewModelHelper +import io.github.sds100.keymapper.util.ui.navigate +import io.github.sds100.keymapper.util.ui.showPopup import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.flow.* +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asSharedFlow +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking @@ -35,6 +50,7 @@ class HomeMenuViewModel( } else { ToggleMappingsButtonState.RESUMED } + ServiceState.CRASHED -> ToggleMappingsButtonState.SERVICE_CRASHED ServiceState.DISABLED -> ToggleMappingsButtonState.SERVICE_DISABLED @@ -128,7 +144,7 @@ class HomeMenuViewModel( message = getString(R.string.dialog_message_no_app_found_to_create_file), positiveButtonText = getString(R.string.pos_ok) ) - + coroutineScope.launch { showPopup("create_document_activity_not_found", dialog) } diff --git a/app/src/main/java/io/github/sds100/keymapper/home/HomePagerAdapter.kt b/app/src/main/java/io/github/sds100/keymapper/home/HomePagerAdapter.kt index 974049e098..3bd5ae52d1 100644 --- a/app/src/main/java/io/github/sds100/keymapper/home/HomePagerAdapter.kt +++ b/app/src/main/java/io/github/sds100/keymapper/home/HomePagerAdapter.kt @@ -24,6 +24,7 @@ class HomePagerAdapter( } } } + HomeTab.FINGERPRINT_MAPS -> { { FingerprintMapListFragment().apply { diff --git a/app/src/main/java/io/github/sds100/keymapper/home/HomeViewModel.kt b/app/src/main/java/io/github/sds100/keymapper/home/HomeViewModel.kt index 135909657e..d773c761c9 100644 --- a/app/src/main/java/io/github/sds100/keymapper/home/HomeViewModel.kt +++ b/app/src/main/java/io/github/sds100/keymapper/home/HomeViewModel.kt @@ -89,6 +89,7 @@ class HomeViewModel( isVisible = false, text = "" ) + is SelectionState.Selecting<*> -> SelectionCountViewState( isVisible = true, text = getString(R.string.selection_count, it.selectedIds.size) @@ -173,6 +174,7 @@ class HomeViewModel( getString(R.string.home_error_accessibility_service_is_crashed) ) ) + ServiceState.DISABLED -> yield( TextListItem.Error( @@ -180,6 +182,7 @@ class HomeViewModel( getString(R.string.home_error_accessibility_service_is_disabled) ) ) + ServiceState.ENABLED -> yield( TextListItem.Success( diff --git a/app/src/main/java/io/github/sds100/keymapper/home/MenuFragment.kt b/app/src/main/java/io/github/sds100/keymapper/home/MenuFragment.kt index 6cf7bd67e8..a214ada377 100644 --- a/app/src/main/java/io/github/sds100/keymapper/home/MenuFragment.kt +++ b/app/src/main/java/io/github/sds100/keymapper/home/MenuFragment.kt @@ -75,18 +75,22 @@ class MenuFragment : BottomSheetDialogFragment() { text = str(R.string.action_tap_to_resume_keymaps) color = color(R.color.green, harmonize = true) } + ToggleMappingsButtonState.RESUMED -> { text = str(R.string.action_tap_to_pause_keymaps) color = color(R.color.red, harmonize = true) } + ToggleMappingsButtonState.SERVICE_DISABLED -> { text = str(R.string.button_enable_accessibility_service) color = color(R.color.red, harmonize = true) } + ToggleMappingsButtonState.SERVICE_CRASHED -> { text = str(R.string.button_restart_accessibility_service) color = color(R.color.red, harmonize = true) } + else -> return@collectLatest } diff --git a/app/src/main/java/io/github/sds100/keymapper/logging/KeyMapperLoggingTree.kt b/app/src/main/java/io/github/sds100/keymapper/logging/KeyMapperLoggingTree.kt index 891281762d..789e2abf8d 100644 --- a/app/src/main/java/io/github/sds100/keymapper/logging/KeyMapperLoggingTree.kt +++ b/app/src/main/java/io/github/sds100/keymapper/logging/KeyMapperLoggingTree.kt @@ -7,9 +7,16 @@ import io.github.sds100.keymapper.data.repositories.PreferenceRepository import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.channels.BufferOverflow -import kotlinx.coroutines.flow.* +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.flowOn +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.flow.stateIn import timber.log.Timber -import java.util.* +import java.util.Calendar /** * Created by sds100 on 13/05/2021. diff --git a/app/src/main/java/io/github/sds100/keymapper/logging/LogFragment.kt b/app/src/main/java/io/github/sds100/keymapper/logging/LogFragment.kt index b744ae1209..8c61ab8fa2 100644 --- a/app/src/main/java/io/github/sds100/keymapper/logging/LogFragment.kt +++ b/app/src/main/java/io/github/sds100/keymapper/logging/LogFragment.kt @@ -4,7 +4,7 @@ import android.content.Intent import android.os.Bundle import android.view.View import android.view.ViewTreeObserver -import androidx.activity.result.contract.ActivityResultContracts +import androidx.activity.result.contract.ActivityResultContracts.CreateDocument import androidx.fragment.app.viewModels import androidx.lifecycle.Lifecycle import androidx.navigation.fragment.findNavController @@ -43,16 +43,16 @@ class LogFragment : SimpleRecyclerViewFragment() { private val recyclerViewController by lazy { RecyclerViewController() } private val saveLogToFileLauncher = - registerForActivityResult(ActivityResultContracts.CreateDocument()) { - it ?: return@registerForActivityResult + registerForActivityResult(CreateDocument("todo/todo")) { + it ?: return@registerForActivityResult - viewModel.onPickFileToSaveTo(it.toString()) + viewModel.onPickFileToSaveTo(it.toString()) - val takeFlags: Int = Intent.FLAG_GRANT_READ_URI_PERMISSION or - Intent.FLAG_GRANT_WRITE_URI_PERMISSION + val takeFlags: Int = Intent.FLAG_GRANT_READ_URI_PERMISSION or + Intent.FLAG_GRANT_WRITE_URI_PERMISSION - requireContext().contentResolver.takePersistableUriPermission(it, takeFlags) - } + requireContext().contentResolver.takePersistableUriPermission(it, takeFlags) + } private lateinit var dragSelectTouchListener: DragSelectTouchListener @@ -97,10 +97,10 @@ class LogFragment : SimpleRecyclerViewFragment() { } val dragSelectionProcessor = DragSelectionProcessor(viewModel.dragSelectionHandler) - .withMode(DragSelectionProcessor.Mode.Simple) + .withMode(DragSelectionProcessor.Mode.Simple) dragSelectTouchListener = DragSelectTouchListener() - .withSelectListener(dragSelectionProcessor) + .withSelectListener(dragSelectionProcessor) binding.epoxyRecyclerView.addOnItemTouchListener(dragSelectTouchListener) @@ -125,7 +125,7 @@ class LogFragment : SimpleRecyclerViewFragment() { currentData?.also { currentData -> if (!scrolledToBottomInitially) { recyclerView?.viewTreeObserver?.addOnGlobalLayoutListener(object : - ViewTreeObserver.OnGlobalLayoutListener { + ViewTreeObserver.OnGlobalLayoutListener { override fun onGlobalLayout() { recyclerView?.scrollToPosition(currentData.size - 1) recyclerView?.viewTreeObserver?.removeOnGlobalLayoutListener(this) diff --git a/app/src/main/java/io/github/sds100/keymapper/logging/LogUtils.kt b/app/src/main/java/io/github/sds100/keymapper/logging/LogUtils.kt index e27017c501..6182f6ef9c 100644 --- a/app/src/main/java/io/github/sds100/keymapper/logging/LogUtils.kt +++ b/app/src/main/java/io/github/sds100/keymapper/logging/LogUtils.kt @@ -3,7 +3,8 @@ package io.github.sds100.keymapper.logging import io.github.sds100.keymapper.data.entities.LogEntryEntity import io.github.sds100.keymapper.system.files.FileUtils import java.text.SimpleDateFormat -import java.util.* +import java.util.Date +import java.util.Locale /** * Created by sds100 on 14/05/2021. diff --git a/app/src/main/java/io/github/sds100/keymapper/logging/LogViewModel.kt b/app/src/main/java/io/github/sds100/keymapper/logging/LogViewModel.kt index e5787159ea..7506ba360a 100644 --- a/app/src/main/java/io/github/sds100/keymapper/logging/LogViewModel.kt +++ b/app/src/main/java/io/github/sds100/keymapper/logging/LogViewModel.kt @@ -108,9 +108,11 @@ class LogViewModel( useCase.copyToClipboard(getSelectedLogEntries()) showPopup("copied", PopupUi.Toast(getString(R.string.toast_copied_log))) } + R.id.action_short_messages -> { showShortMessages.value = !showShortMessages.value } + R.id.action_save -> _pickFileToSaveTo.emit(Unit) } diff --git a/app/src/main/java/io/github/sds100/keymapper/mappings/ConfigMappingFragment.kt b/app/src/main/java/io/github/sds100/keymapper/mappings/ConfigMappingFragment.kt index 261e196b4f..f0127caaee 100644 --- a/app/src/main/java/io/github/sds100/keymapper/mappings/ConfigMappingFragment.kt +++ b/app/src/main/java/io/github/sds100/keymapper/mappings/ConfigMappingFragment.kt @@ -15,9 +15,13 @@ import com.google.android.material.tabs.TabLayoutMediator import io.github.sds100.keymapper.R import io.github.sds100.keymapper.databinding.FragmentConfigMappingBinding import io.github.sds100.keymapper.system.url.UrlUtils -import io.github.sds100.keymapper.util.* +import io.github.sds100.keymapper.util.FragmentInfo +import io.github.sds100.keymapper.util.GenericFragmentPagerAdapter +import io.github.sds100.keymapper.util.launchRepeatOnLifecycle +import io.github.sds100.keymapper.util.str import io.github.sds100.keymapper.util.ui.setupNavigation import io.github.sds100.keymapper.util.ui.showPopups +import io.github.sds100.keymapper.util.viewLifecycleScope import splitties.alertdialog.appcompat.messageResource import splitties.alertdialog.appcompat.negativeButton import splitties.alertdialog.appcompat.positiveButton @@ -127,6 +131,7 @@ abstract class ConfigMappingFragment : Fragment() { true } + else -> false } } diff --git a/app/src/main/java/io/github/sds100/keymapper/mappings/DisplayMappingUseCase.kt b/app/src/main/java/io/github/sds100/keymapper/mappings/DisplayMappingUseCase.kt index 33b93835f5..b0aee8c01b 100644 --- a/app/src/main/java/io/github/sds100/keymapper/mappings/DisplayMappingUseCase.kt +++ b/app/src/main/java/io/github/sds100/keymapper/mappings/DisplayMappingUseCase.kt @@ -11,7 +11,11 @@ import io.github.sds100.keymapper.system.apps.PackageManagerAdapter import io.github.sds100.keymapper.system.inputmethod.InputMethodAdapter import io.github.sds100.keymapper.system.inputmethod.KeyMapperImeHelper import io.github.sds100.keymapper.system.permissions.PermissionAdapter -import io.github.sds100.keymapper.util.* +import io.github.sds100.keymapper.util.Error +import io.github.sds100.keymapper.util.Result +import io.github.sds100.keymapper.util.Success +import io.github.sds100.keymapper.util.otherwise +import io.github.sds100.keymapper.util.then import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.map @@ -71,6 +75,7 @@ class DisplaySimpleMappingUseCaseImpl( inputMethodAdapter.showImePicker(fromForeground = true) } } + else -> Unit } } diff --git a/app/src/main/java/io/github/sds100/keymapper/mappings/EditActionViewModel.kt b/app/src/main/java/io/github/sds100/keymapper/mappings/EditActionViewModel.kt index 97a39a90bb..aec2a72264 100644 --- a/app/src/main/java/io/github/sds100/keymapper/mappings/EditActionViewModel.kt +++ b/app/src/main/java/io/github/sds100/keymapper/mappings/EditActionViewModel.kt @@ -1,11 +1,24 @@ package io.github.sds100.keymapper.mappings -import io.github.sds100.keymapper.actions.* +import io.github.sds100.keymapper.actions.Action +import io.github.sds100.keymapper.actions.CreateActionUseCase +import io.github.sds100.keymapper.actions.CreateActionViewModel +import io.github.sds100.keymapper.actions.CreateActionViewModelImpl +import io.github.sds100.keymapper.actions.isEditable import io.github.sds100.keymapper.util.State -import io.github.sds100.keymapper.util.ui.* +import io.github.sds100.keymapper.util.ui.ListItem +import io.github.sds100.keymapper.util.ui.NavDestination +import io.github.sds100.keymapper.util.ui.ResourceProvider +import io.github.sds100.keymapper.util.ui.navigate import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.flow.* +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.flowOn +import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch /** diff --git a/app/src/main/java/io/github/sds100/keymapper/mappings/Mapping.kt b/app/src/main/java/io/github/sds100/keymapper/mappings/Mapping.kt index 54363e6762..5f3c144540 100644 --- a/app/src/main/java/io/github/sds100/keymapper/mappings/Mapping.kt +++ b/app/src/main/java/io/github/sds100/keymapper/mappings/Mapping.kt @@ -1,7 +1,7 @@ package io.github.sds100.keymapper.mappings -import io.github.sds100.keymapper.constraints.ConstraintState import io.github.sds100.keymapper.actions.Action +import io.github.sds100.keymapper.constraints.ConstraintState /** * Created by sds100 on 04/04/2021. diff --git a/app/src/main/java/io/github/sds100/keymapper/mappings/OptionsFragment.kt b/app/src/main/java/io/github/sds100/keymapper/mappings/OptionsFragment.kt index c1ad90d762..f29695e96a 100644 --- a/app/src/main/java/io/github/sds100/keymapper/mappings/OptionsFragment.kt +++ b/app/src/main/java/io/github/sds100/keymapper/mappings/OptionsFragment.kt @@ -18,7 +18,12 @@ import io.github.sds100.keymapper.ui.utils.configuredRadioButtonPair import io.github.sds100.keymapper.ui.utils.configuredRadioButtonTriple import io.github.sds100.keymapper.ui.utils.configuredSlider import io.github.sds100.keymapper.util.launchRepeatOnLifecycle -import io.github.sds100.keymapper.util.ui.* +import io.github.sds100.keymapper.util.ui.CheckBoxListItem +import io.github.sds100.keymapper.util.ui.DividerListItem +import io.github.sds100.keymapper.util.ui.ListItem +import io.github.sds100.keymapper.util.ui.RadioButtonPairListItem +import io.github.sds100.keymapper.util.ui.RadioButtonTripleListItem +import io.github.sds100.keymapper.util.ui.SliderListItem import kotlinx.coroutines.flow.collectLatest /** diff --git a/app/src/main/java/io/github/sds100/keymapper/mappings/SimpleMappingController.kt b/app/src/main/java/io/github/sds100/keymapper/mappings/SimpleMappingController.kt index 826d9339ce..750fc5b70c 100644 --- a/app/src/main/java/io/github/sds100/keymapper/mappings/SimpleMappingController.kt +++ b/app/src/main/java/io/github/sds100/keymapper/mappings/SimpleMappingController.kt @@ -5,11 +5,15 @@ import io.github.sds100.keymapper.actions.PerformActionsUseCase import io.github.sds100.keymapper.actions.RepeatMode import io.github.sds100.keymapper.constraints.DetectConstraintsUseCase import io.github.sds100.keymapper.data.PreferenceDefaults -import io.github.sds100.keymapper.util.* -import kotlinx.coroutines.* +import io.github.sds100.keymapper.util.InputEventType +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.CoroutineStart +import kotlinx.coroutines.Job +import kotlinx.coroutines.delay import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.launch /** * Created by sds100 on 10/01/21. @@ -160,7 +164,8 @@ abstract class SimpleMappingController( repeatCount++ if (action.repeatLimit != null) { - continueRepeating = repeatCount < action.repeatLimit!! + 1 //this value is how many times it should REPEAT. The first repeat happens after the first time it is performed + continueRepeating = + repeatCount < action.repeatLimit!! + 1 //this value is how many times it should REPEAT. The first repeat happens after the first time it is performed } delay(repeatRate) diff --git a/app/src/main/java/io/github/sds100/keymapper/mappings/fingerprintmaps/AreFingerprintGesturesSupportedUseCase.kt b/app/src/main/java/io/github/sds100/keymapper/mappings/fingerprintmaps/AreFingerprintGesturesSupportedUseCase.kt index e307244d13..e7a7ae9e15 100644 --- a/app/src/main/java/io/github/sds100/keymapper/mappings/fingerprintmaps/AreFingerprintGesturesSupportedUseCase.kt +++ b/app/src/main/java/io/github/sds100/keymapper/mappings/fingerprintmaps/AreFingerprintGesturesSupportedUseCase.kt @@ -10,7 +10,7 @@ import kotlinx.coroutines.flow.map * Created by sds100 on 02/04/2021. */ class AreFingerprintGesturesSupportedUseCaseImpl( - private val preferenceRepository: PreferenceRepository + private val preferenceRepository: PreferenceRepository ) : AreFingerprintGesturesSupportedUseCase { override val isSupported: Flow = preferenceRepository.get(Keys.fingerprintGesturesAvailable).map { diff --git a/app/src/main/java/io/github/sds100/keymapper/mappings/fingerprintmaps/ConfigFingerprintMapFragment.kt b/app/src/main/java/io/github/sds100/keymapper/mappings/fingerprintmaps/ConfigFingerprintMapFragment.kt index 9505314ecd..3dacc2cdf4 100644 --- a/app/src/main/java/io/github/sds100/keymapper/mappings/fingerprintmaps/ConfigFingerprintMapFragment.kt +++ b/app/src/main/java/io/github/sds100/keymapper/mappings/fingerprintmaps/ConfigFingerprintMapFragment.kt @@ -13,7 +13,11 @@ import io.github.sds100.keymapper.constraints.ConfigConstraintsFragment import io.github.sds100.keymapper.constraints.Constraint import io.github.sds100.keymapper.mappings.ConfigMappingFragment import io.github.sds100.keymapper.ui.utils.getJsonSerializable -import io.github.sds100.keymapper.util.* +import io.github.sds100.keymapper.util.FragmentInfo +import io.github.sds100.keymapper.util.Inject +import io.github.sds100.keymapper.util.int +import io.github.sds100.keymapper.util.intArray +import io.github.sds100.keymapper.util.launchRepeatOnLifecycle import io.github.sds100.keymapper.util.ui.TwoFragments import kotlinx.coroutines.flow.collectLatest diff --git a/app/src/main/java/io/github/sds100/keymapper/mappings/fingerprintmaps/ConfigFingerprintMapOptionsViewModel.kt b/app/src/main/java/io/github/sds100/keymapper/mappings/fingerprintmaps/ConfigFingerprintMapOptionsViewModel.kt index a8f61e66b9..11f05514c0 100644 --- a/app/src/main/java/io/github/sds100/keymapper/mappings/fingerprintmaps/ConfigFingerprintMapOptionsViewModel.kt +++ b/app/src/main/java/io/github/sds100/keymapper/mappings/fingerprintmaps/ConfigFingerprintMapOptionsViewModel.kt @@ -5,7 +5,15 @@ import io.github.sds100.keymapper.mappings.OptionMinimums import io.github.sds100.keymapper.util.Defaultable import io.github.sds100.keymapper.util.State import io.github.sds100.keymapper.util.mapData -import io.github.sds100.keymapper.util.ui.* +import io.github.sds100.keymapper.util.ui.CheckBoxListItem +import io.github.sds100.keymapper.util.ui.ListItem +import io.github.sds100.keymapper.util.ui.PopupViewModel +import io.github.sds100.keymapper.util.ui.PopupViewModelImpl +import io.github.sds100.keymapper.util.ui.ResourceProvider +import io.github.sds100.keymapper.util.ui.SliderListItem +import io.github.sds100.keymapper.util.ui.SliderMaximums +import io.github.sds100.keymapper.util.ui.SliderModel +import io.github.sds100.keymapper.util.ui.SliderStepSizes import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableStateFlow diff --git a/app/src/main/java/io/github/sds100/keymapper/mappings/fingerprintmaps/EditFingerprintMapActionViewModel.kt b/app/src/main/java/io/github/sds100/keymapper/mappings/fingerprintmaps/EditFingerprintMapActionViewModel.kt index c0da07ce28..eee1268ae0 100644 --- a/app/src/main/java/io/github/sds100/keymapper/mappings/fingerprintmaps/EditFingerprintMapActionViewModel.kt +++ b/app/src/main/java/io/github/sds100/keymapper/mappings/fingerprintmaps/EditFingerprintMapActionViewModel.kt @@ -7,7 +7,15 @@ import io.github.sds100.keymapper.mappings.EditActionViewModel import io.github.sds100.keymapper.mappings.OptionMinimums import io.github.sds100.keymapper.mappings.isDelayBeforeNextActionAllowed import io.github.sds100.keymapper.util.Defaultable -import io.github.sds100.keymapper.util.ui.* +import io.github.sds100.keymapper.util.ui.CheckBoxListItem +import io.github.sds100.keymapper.util.ui.DividerListItem +import io.github.sds100.keymapper.util.ui.ListItem +import io.github.sds100.keymapper.util.ui.RadioButtonPairListItem +import io.github.sds100.keymapper.util.ui.ResourceProvider +import io.github.sds100.keymapper.util.ui.SliderListItem +import io.github.sds100.keymapper.util.ui.SliderMaximums +import io.github.sds100.keymapper.util.ui.SliderModel +import io.github.sds100.keymapper.util.ui.SliderStepSizes import kotlinx.coroutines.CoroutineScope /** @@ -64,11 +72,13 @@ class EditFingerprintMapActionViewModel( actionUid, value.nullIfDefault() ) + ID_MULTIPLIER -> config.setActionMultiplier(actionUid, value.nullIfDefault()) ID_DELAY_BEFORE_NEXT_ACTION -> config.setDelayBeforeNextAction( actionUid, value.nullIfDefault() ) + ID_REPEAT_LIMIT -> config.setActionRepeatLimit(actionUid, value.nullIfDefault()) } } diff --git a/app/src/main/java/io/github/sds100/keymapper/mappings/fingerprintmaps/FingerprintConfigActionsFragment.kt b/app/src/main/java/io/github/sds100/keymapper/mappings/fingerprintmaps/FingerprintConfigActionsFragment.kt index f36a5d6b3b..5d22f2c0e0 100644 --- a/app/src/main/java/io/github/sds100/keymapper/mappings/fingerprintmaps/FingerprintConfigActionsFragment.kt +++ b/app/src/main/java/io/github/sds100/keymapper/mappings/fingerprintmaps/FingerprintConfigActionsFragment.kt @@ -2,8 +2,8 @@ package io.github.sds100.keymapper.mappings.fingerprintmaps import androidx.navigation.navGraphViewModels import io.github.sds100.keymapper.R -import io.github.sds100.keymapper.actions.ConfigActionsViewModel import io.github.sds100.keymapper.actions.ConfigActionsFragment +import io.github.sds100.keymapper.actions.ConfigActionsViewModel import io.github.sds100.keymapper.util.FragmentInfo import io.github.sds100.keymapper.util.Inject diff --git a/app/src/main/java/io/github/sds100/keymapper/mappings/fingerprintmaps/FingerprintConfigConstraintsFragment.kt b/app/src/main/java/io/github/sds100/keymapper/mappings/fingerprintmaps/FingerprintConfigConstraintsFragment.kt index bf2614779b..e623cef8b3 100644 --- a/app/src/main/java/io/github/sds100/keymapper/mappings/fingerprintmaps/FingerprintConfigConstraintsFragment.kt +++ b/app/src/main/java/io/github/sds100/keymapper/mappings/fingerprintmaps/FingerprintConfigConstraintsFragment.kt @@ -2,8 +2,8 @@ package io.github.sds100.keymapper.mappings.fingerprintmaps import androidx.navigation.navGraphViewModels import io.github.sds100.keymapper.R -import io.github.sds100.keymapper.constraints.ConfigConstraintsViewModel import io.github.sds100.keymapper.constraints.ConfigConstraintsFragment +import io.github.sds100.keymapper.constraints.ConfigConstraintsViewModel import io.github.sds100.keymapper.util.FragmentInfo import io.github.sds100.keymapper.util.Inject diff --git a/app/src/main/java/io/github/sds100/keymapper/mappings/fingerprintmaps/FingerprintMapAction.kt b/app/src/main/java/io/github/sds100/keymapper/mappings/fingerprintmaps/FingerprintMapAction.kt index 715858d812..42ed41577d 100644 --- a/app/src/main/java/io/github/sds100/keymapper/mappings/fingerprintmaps/FingerprintMapAction.kt +++ b/app/src/main/java/io/github/sds100/keymapper/mappings/fingerprintmaps/FingerprintMapAction.kt @@ -12,7 +12,7 @@ import io.github.sds100.keymapper.util.valueOrNull import kotlinx.serialization.Serializable import splitties.bitflags.hasFlag import splitties.bitflags.withFlag -import java.util.* +import java.util.UUID /** * Created by sds100 on 09/03/2021. @@ -97,7 +97,7 @@ object FingerprintMapActionEntityMapper { fun toEntity(fingerprintMap: FingerprintMap): List = fingerprintMap.actionList.mapNotNull { action -> - val base = ActionDataEntityMapper.toEntity(action.data) ?: return@mapNotNull null + val base = ActionDataEntityMapper.toEntity(action.data) val extras = mutableListOf().apply { if (fingerprintMap.isDelayBeforeNextActionAllowed() && action.delayBeforeNextAction != null) { diff --git a/app/src/main/java/io/github/sds100/keymapper/mappings/fingerprintmaps/FingerprintMapActionUiHelper.kt b/app/src/main/java/io/github/sds100/keymapper/mappings/fingerprintmaps/FingerprintMapActionUiHelper.kt index a99216460d..b7be00acb2 100644 --- a/app/src/main/java/io/github/sds100/keymapper/mappings/fingerprintmaps/FingerprintMapActionUiHelper.kt +++ b/app/src/main/java/io/github/sds100/keymapper/mappings/fingerprintmaps/FingerprintMapActionUiHelper.kt @@ -46,6 +46,7 @@ class FingerprintMapActionUiHelper( RepeatMode.TRIGGER_PRESSED_AGAIN -> { append(getString(R.string.flag_repeat_build_description_until_swiped_again)) } + else -> Unit } } diff --git a/app/src/main/java/io/github/sds100/keymapper/mappings/fingerprintmaps/FingerprintMapJsonGroup.kt b/app/src/main/java/io/github/sds100/keymapper/mappings/fingerprintmaps/FingerprintMapJsonGroup.kt index 8e7915605d..fdee898f3c 100644 --- a/app/src/main/java/io/github/sds100/keymapper/mappings/fingerprintmaps/FingerprintMapJsonGroup.kt +++ b/app/src/main/java/io/github/sds100/keymapper/mappings/fingerprintmaps/FingerprintMapJsonGroup.kt @@ -3,7 +3,9 @@ package io.github.sds100.keymapper.mappings.fingerprintmaps /** * Created by sds100 on 04/04/2021. */ -data class FingerprintMapJsonGroup(val swipeDown: String, - val swipeUp: String, - val swipeLeft: String, - val swipeRight: String) \ No newline at end of file +data class FingerprintMapJsonGroup( + val swipeDown: String, + val swipeUp: String, + val swipeLeft: String, + val swipeRight: String +) \ No newline at end of file diff --git a/app/src/main/java/io/github/sds100/keymapper/mappings/fingerprintmaps/FingerprintMapListItemCreator.kt b/app/src/main/java/io/github/sds100/keymapper/mappings/fingerprintmaps/FingerprintMapListItemCreator.kt index e2543bd945..96d0e9213d 100644 --- a/app/src/main/java/io/github/sds100/keymapper/mappings/fingerprintmaps/FingerprintMapListItemCreator.kt +++ b/app/src/main/java/io/github/sds100/keymapper/mappings/fingerprintmaps/FingerprintMapListItemCreator.kt @@ -1,9 +1,9 @@ package io.github.sds100.keymapper.mappings.fingerprintmaps import io.github.sds100.keymapper.R -import io.github.sds100.keymapper.util.ui.ResourceProvider -import io.github.sds100.keymapper.mappings.DisplaySimpleMappingUseCase import io.github.sds100.keymapper.mappings.BaseMappingListItemCreator +import io.github.sds100.keymapper.mappings.DisplaySimpleMappingUseCase +import io.github.sds100.keymapper.util.ui.ResourceProvider /** * Created by sds100 on 19/03/2021. diff --git a/app/src/main/java/io/github/sds100/keymapper/mappings/fingerprintmaps/FingerprintMapListViewModel.kt b/app/src/main/java/io/github/sds100/keymapper/mappings/fingerprintmaps/FingerprintMapListViewModel.kt index 0d168b76a4..a30a180502 100755 --- a/app/src/main/java/io/github/sds100/keymapper/mappings/fingerprintmaps/FingerprintMapListViewModel.kt +++ b/app/src/main/java/io/github/sds100/keymapper/mappings/fingerprintmaps/FingerprintMapListViewModel.kt @@ -1,12 +1,34 @@ package io.github.sds100.keymapper.mappings.fingerprintmaps -import androidx.lifecycle.* import io.github.sds100.keymapper.R -import io.github.sds100.keymapper.ui.* -import io.github.sds100.keymapper.util.* -import io.github.sds100.keymapper.util.ui.* -import kotlinx.coroutines.* -import kotlinx.coroutines.flow.* +import io.github.sds100.keymapper.util.Error +import io.github.sds100.keymapper.util.State +import io.github.sds100.keymapper.util.getFullMessage +import io.github.sds100.keymapper.util.isFixable +import io.github.sds100.keymapper.util.ui.ChipUi +import io.github.sds100.keymapper.util.ui.DialogResponse +import io.github.sds100.keymapper.util.ui.NavDestination +import io.github.sds100.keymapper.util.ui.NavigationViewModel +import io.github.sds100.keymapper.util.ui.NavigationViewModelImpl +import io.github.sds100.keymapper.util.ui.PopupUi +import io.github.sds100.keymapper.util.ui.PopupViewModel +import io.github.sds100.keymapper.util.ui.PopupViewModelImpl +import io.github.sds100.keymapper.util.ui.ResourceProvider +import io.github.sds100.keymapper.util.ui.navigate +import io.github.sds100.keymapper.util.ui.showPopup +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asSharedFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.collectLatest +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.firstOrNull +import kotlinx.coroutines.flow.flowOn +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.launch +import kotlinx.coroutines.runBlocking class FingerprintMapListViewModel( private val coroutineScope: CoroutineScope, diff --git a/app/src/main/java/io/github/sds100/keymapper/mappings/fingerprintmaps/FingerprintMapOptionsFragment.kt b/app/src/main/java/io/github/sds100/keymapper/mappings/fingerprintmaps/FingerprintMapOptionsFragment.kt index 716e50a621..e606182255 100644 --- a/app/src/main/java/io/github/sds100/keymapper/mappings/fingerprintmaps/FingerprintMapOptionsFragment.kt +++ b/app/src/main/java/io/github/sds100/keymapper/mappings/fingerprintmaps/FingerprintMapOptionsFragment.kt @@ -3,13 +3,15 @@ package io.github.sds100.keymapper.mappings.fingerprintmaps import androidx.navigation.navGraphViewModels import com.airbnb.epoxy.EpoxyRecyclerView import io.github.sds100.keymapper.R -import io.github.sds100.keymapper.ui.* import io.github.sds100.keymapper.ui.utils.configuredCheckBox import io.github.sds100.keymapper.ui.utils.configuredSlider import io.github.sds100.keymapper.util.FragmentInfo import io.github.sds100.keymapper.util.Inject import io.github.sds100.keymapper.util.State -import io.github.sds100.keymapper.util.ui.* +import io.github.sds100.keymapper.util.ui.CheckBoxListItem +import io.github.sds100.keymapper.util.ui.ListItem +import io.github.sds100.keymapper.util.ui.SimpleRecyclerViewFragment +import io.github.sds100.keymapper.util.ui.SliderListItem import kotlinx.coroutines.flow.Flow /** diff --git a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/ConfigKeyMapConstraintsFragment.kt b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/ConfigKeyMapConstraintsFragment.kt index 465dd53735..bce46f8a66 100644 --- a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/ConfigKeyMapConstraintsFragment.kt +++ b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/ConfigKeyMapConstraintsFragment.kt @@ -2,8 +2,8 @@ package io.github.sds100.keymapper.mappings.keymaps import androidx.navigation.navGraphViewModels import io.github.sds100.keymapper.R -import io.github.sds100.keymapper.constraints.ConfigConstraintsViewModel import io.github.sds100.keymapper.constraints.ConfigConstraintsFragment +import io.github.sds100.keymapper.constraints.ConfigConstraintsViewModel import io.github.sds100.keymapper.util.FragmentInfo import io.github.sds100.keymapper.util.Inject diff --git a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/ConfigKeyMapFragment.kt b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/ConfigKeyMapFragment.kt index adcca39087..ca7d4b8db3 100644 --- a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/ConfigKeyMapFragment.kt +++ b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/ConfigKeyMapFragment.kt @@ -16,7 +16,11 @@ import io.github.sds100.keymapper.mappings.ConfigMappingFragment import io.github.sds100.keymapper.mappings.keymaps.trigger.ConfigTriggerOptionsFragment import io.github.sds100.keymapper.mappings.keymaps.trigger.TriggerFragment import io.github.sds100.keymapper.ui.utils.getJsonSerializable -import io.github.sds100.keymapper.util.* +import io.github.sds100.keymapper.util.FragmentInfo +import io.github.sds100.keymapper.util.Inject +import io.github.sds100.keymapper.util.int +import io.github.sds100.keymapper.util.intArray +import io.github.sds100.keymapper.util.launchRepeatOnLifecycle import io.github.sds100.keymapper.util.ui.FourFragments import io.github.sds100.keymapper.util.ui.TwoFragments import io.github.sds100.keymapper.util.ui.setupNavigation diff --git a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/ConfigKeyMapTriggerOptionsViewModel.kt b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/ConfigKeyMapTriggerOptionsViewModel.kt index 69d05e6ead..164e78e233 100644 --- a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/ConfigKeyMapTriggerOptionsViewModel.kt +++ b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/ConfigKeyMapTriggerOptionsViewModel.kt @@ -3,8 +3,23 @@ package io.github.sds100.keymapper.mappings.keymaps import io.github.sds100.keymapper.R import io.github.sds100.keymapper.mappings.OptionMinimums import io.github.sds100.keymapper.mappings.keymaps.trigger.TriggerFromOtherAppsListItem -import io.github.sds100.keymapper.util.* -import io.github.sds100.keymapper.util.ui.* +import io.github.sds100.keymapper.util.Defaultable +import io.github.sds100.keymapper.util.State +import io.github.sds100.keymapper.util.dataOrNull +import io.github.sds100.keymapper.util.getFullMessage +import io.github.sds100.keymapper.util.mapData +import io.github.sds100.keymapper.util.onFailure +import io.github.sds100.keymapper.util.ui.CheckBoxListItem +import io.github.sds100.keymapper.util.ui.ListItem +import io.github.sds100.keymapper.util.ui.PopupUi +import io.github.sds100.keymapper.util.ui.PopupViewModel +import io.github.sds100.keymapper.util.ui.PopupViewModelImpl +import io.github.sds100.keymapper.util.ui.ResourceProvider +import io.github.sds100.keymapper.util.ui.SliderListItem +import io.github.sds100.keymapper.util.ui.SliderMaximums +import io.github.sds100.keymapper.util.ui.SliderModel +import io.github.sds100.keymapper.util.ui.SliderStepSizes +import io.github.sds100.keymapper.util.ui.showPopup import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableStateFlow diff --git a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/ConfigKeyMapTriggerViewModel.kt b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/ConfigKeyMapTriggerViewModel.kt index 95636a0876..cdfd7fb785 100644 --- a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/ConfigKeyMapTriggerViewModel.kt +++ b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/ConfigKeyMapTriggerViewModel.kt @@ -4,7 +4,14 @@ import android.os.Build import android.view.KeyEvent import io.github.sds100.keymapper.R import io.github.sds100.keymapper.mappings.ClickType -import io.github.sds100.keymapper.mappings.keymaps.trigger.* +import io.github.sds100.keymapper.mappings.keymaps.trigger.KeyMapTrigger +import io.github.sds100.keymapper.mappings.keymaps.trigger.KeyMapTriggerError +import io.github.sds100.keymapper.mappings.keymaps.trigger.RecordTriggerState +import io.github.sds100.keymapper.mappings.keymaps.trigger.RecordTriggerUseCase +import io.github.sds100.keymapper.mappings.keymaps.trigger.TriggerKeyDevice +import io.github.sds100.keymapper.mappings.keymaps.trigger.TriggerKeyLinkType +import io.github.sds100.keymapper.mappings.keymaps.trigger.TriggerKeyListItem +import io.github.sds100.keymapper.mappings.keymaps.trigger.TriggerMode import io.github.sds100.keymapper.onboarding.OnboardingUseCase import io.github.sds100.keymapper.system.devices.InputDeviceUtils import io.github.sds100.keymapper.system.keyevents.KeyEventUtils @@ -13,10 +20,35 @@ import io.github.sds100.keymapper.util.Error import io.github.sds100.keymapper.util.State import io.github.sds100.keymapper.util.dataOrNull import io.github.sds100.keymapper.util.mapData -import io.github.sds100.keymapper.util.ui.* +import io.github.sds100.keymapper.util.ui.NavigationViewModel +import io.github.sds100.keymapper.util.ui.NavigationViewModelImpl +import io.github.sds100.keymapper.util.ui.PopupUi +import io.github.sds100.keymapper.util.ui.PopupViewModel +import io.github.sds100.keymapper.util.ui.PopupViewModelImpl +import io.github.sds100.keymapper.util.ui.ResourceProvider +import io.github.sds100.keymapper.util.ui.TextListItem +import io.github.sds100.keymapper.util.ui.ViewModelHelper +import io.github.sds100.keymapper.util.ui.showPopup import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.flow.* +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asSharedFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.collectLatest +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.drop +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.firstOrNull +import kotlinx.coroutines.flow.flowOn +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.mapNotNull +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking @@ -25,22 +57,22 @@ import kotlinx.coroutines.runBlocking */ class ConfigKeyMapTriggerViewModel( - private val coroutineScope: CoroutineScope, - private val onboarding: OnboardingUseCase, - private val config: ConfigKeyMapUseCase, - private val recordTrigger: RecordTriggerUseCase, - private val createKeyMapShortcut: CreateKeyMapShortcutUseCase, - private val displayKeyMap: DisplayKeyMapUseCase, - resourceProvider: ResourceProvider + private val coroutineScope: CoroutineScope, + private val onboarding: OnboardingUseCase, + private val config: ConfigKeyMapUseCase, + private val recordTrigger: RecordTriggerUseCase, + private val createKeyMapShortcut: CreateKeyMapShortcutUseCase, + private val displayKeyMap: DisplayKeyMapUseCase, + resourceProvider: ResourceProvider ) : ResourceProvider by resourceProvider, - PopupViewModel by PopupViewModelImpl(), - NavigationViewModel by NavigationViewModelImpl() { + PopupViewModel by PopupViewModelImpl(), + NavigationViewModel by NavigationViewModelImpl() { val optionsViewModel = ConfigKeyMapTriggerOptionsViewModel( - coroutineScope, - config, - createKeyMapShortcut, - resourceProvider + coroutineScope, + config, + createKeyMapShortcut, + resourceProvider ) private val _openEditOptions = MutableSharedFlow() @@ -53,9 +85,10 @@ class ConfigKeyMapTriggerViewModel( val recordTriggerButtonText: StateFlow = recordTrigger.state.map { recordTriggerState -> when (recordTriggerState) { is RecordTriggerState.CountingDown -> getString( - R.string.button_recording_trigger_countdown, - recordTriggerState.timeLeft + R.string.button_recording_trigger_countdown, + recordTriggerState.timeLeft ) + RecordTriggerState.Stopped -> getString(R.string.button_record_trigger) } }.flowOn(Dispatchers.Default).stateIn(coroutineScope, SharingStarted.Lazily, "") @@ -78,19 +111,19 @@ class ConfigKeyMapTriggerViewModel( State.Loading -> R.id.radioButtonUndefined } }.flowOn(Dispatchers.Default) - .stateIn(coroutineScope, SharingStarted.Eagerly, R.id.radioButtonUndefined) + .stateIn(coroutineScope, SharingStarted.Eagerly, R.id.radioButtonUndefined) val triggerKeyListItems: StateFlow>> = - combine( - config.mapping, - displayKeyMap.showDeviceDescriptors - ) { mappingState, showDeviceDescriptors -> + combine( + config.mapping, + displayKeyMap.showDeviceDescriptors + ) { mappingState, showDeviceDescriptors -> - mappingState.mapData { keyMap -> - createListItems(keyMap.trigger, showDeviceDescriptors) - } + mappingState.mapData { keyMap -> + createListItems(keyMap.trigger, showDeviceDescriptors) + } - }.flowOn(Dispatchers.Default).stateIn(coroutineScope, SharingStarted.Eagerly, State.Loading) + }.flowOn(Dispatchers.Default).stateIn(coroutineScope, SharingStarted.Eagerly, State.Loading) val clickTypeRadioButtonsVisible: StateFlow = config.mapping.map { state -> when (state) { @@ -99,6 +132,7 @@ class ConfigKeyMapTriggerViewModel( trigger.mode is TriggerMode.Parallel || trigger.keys.size == 1 } + State.Loading -> false } }.flowOn(Dispatchers.Default).stateIn(coroutineScope, SharingStarted.Eagerly, false) @@ -128,10 +162,11 @@ class ConfigKeyMapTriggerViewModel( null -> R.id.radioButtonShortPress } } + State.Loading -> R.id.radioButtonShortPress } }.flowOn(Dispatchers.Default) - .stateIn(coroutineScope, SharingStarted.Eagerly, R.id.radioButtonShortPress) + .stateIn(coroutineScope, SharingStarted.Eagerly, R.id.radioButtonShortPress) private val _errorListItems = MutableStateFlow>(emptyList()) val errorListItems = _errorListItems.asStateFlow() @@ -174,7 +209,7 @@ class ConfigKeyMapTriggerViewModel( recordTrigger.onRecordKey.onEach { if (it.keyCode == KeyEvent.KEYCODE_CAPS_LOCK) { val dialog = PopupUi.Ok( - message = getString(R.string.dialog_message_enable_physical_keyboard_caps_lock_a_keyboard_layout) + message = getString(R.string.dialog_message_enable_physical_keyboard_caps_lock_a_keyboard_layout) ) showPopup("caps_lock_message", dialog) @@ -182,7 +217,7 @@ class ConfigKeyMapTriggerViewModel( if (it.keyCode == KeyEvent.KEYCODE_BACK) { val dialog = PopupUi.Ok( - message = getString(R.string.dialog_message_screen_pinning_warning) + message = getString(R.string.dialog_message_screen_pinning_warning) ) showPopup("screen_pinning_message", dialog) @@ -193,57 +228,57 @@ class ConfigKeyMapTriggerViewModel( coroutineScope.launch { config.mapping - .mapNotNull { it.dataOrNull()?.trigger?.mode } - .distinctUntilChanged() - .drop(1) - .collectLatest { mode -> - if (mode is TriggerMode.Parallel) { - if (onboarding.shownParallelTriggerOrderExplanation) return@collectLatest - - val dialog = PopupUi.Ok( - message = getString(R.string.dialog_message_parallel_trigger_order) - ) + .mapNotNull { it.dataOrNull()?.trigger?.mode } + .distinctUntilChanged() + .drop(1) + .collectLatest { mode -> + if (mode is TriggerMode.Parallel) { + if (onboarding.shownParallelTriggerOrderExplanation) return@collectLatest - showPopup("parallel_trigger_order", dialog) ?: return@collectLatest + val dialog = PopupUi.Ok( + message = getString(R.string.dialog_message_parallel_trigger_order) + ) - onboarding.shownParallelTriggerOrderExplanation = true - } + showPopup("parallel_trigger_order", dialog) ?: return@collectLatest - if (mode is TriggerMode.Sequence) { - if (onboarding.shownSequenceTriggerExplanation) return@collectLatest + onboarding.shownParallelTriggerOrderExplanation = true + } - val dialog = PopupUi.Ok( - message = getString(R.string.dialog_message_sequence_trigger_explanation) - ) + if (mode is TriggerMode.Sequence) { + if (onboarding.shownSequenceTriggerExplanation) return@collectLatest - showPopup("sequence_trigger_explanation", dialog) - ?: return@collectLatest + val dialog = PopupUi.Ok( + message = getString(R.string.dialog_message_sequence_trigger_explanation) + ) - onboarding.shownSequenceTriggerExplanation = true - } + showPopup("sequence_trigger_explanation", dialog) + ?: return@collectLatest + + onboarding.shownSequenceTriggerExplanation = true } + } } } private fun buildTriggerErrorListItems(triggerErrors: List) = - triggerErrors.map { error -> - when (error) { - KeyMapTriggerError.DND_ACCESS_DENIED -> TextListItem.Error( - id = error.toString(), - text = getString(R.string.trigger_error_dnd_access_denied), - ) + triggerErrors.map { error -> + when (error) { + KeyMapTriggerError.DND_ACCESS_DENIED -> TextListItem.Error( + id = error.toString(), + text = getString(R.string.trigger_error_dnd_access_denied), + ) - KeyMapTriggerError.SCREEN_OFF_ROOT_DENIED -> TextListItem.Error( - id = error.toString(), - text = getString(R.string.trigger_error_screen_off_root_permission_denied) - ) + KeyMapTriggerError.SCREEN_OFF_ROOT_DENIED -> TextListItem.Error( + id = error.toString(), + text = getString(R.string.trigger_error_screen_off_root_permission_denied) + ) - KeyMapTriggerError.CANT_DETECT_IN_PHONE_CALL -> TextListItem.Error( - id = error.toString(), - text = getString(R.string.trigger_error_cant_detect_in_phone_call) - ) - } + KeyMapTriggerError.CANT_DETECT_IN_PHONE_CALL -> TextListItem.Error( + id = error.toString(), + text = getString(R.string.trigger_error_cant_detect_in_phone_call) + ) } + } fun onParallelRadioButtonCheckedChange(isChecked: Boolean) { if (isChecked) { @@ -286,8 +321,8 @@ class ConfigKeyMapTriggerViewModel( is TriggerKeyDevice.External -> { if (showDeviceDescriptors) { val name = InputDeviceUtils.appendDeviceDescriptorToName( - device.descriptor, - device.name + device.descriptor, + device.name ) device.descriptor to name } else { @@ -298,8 +333,8 @@ class ConfigKeyMapTriggerViewModel( } val triggerKeyDeviceId = showPopup( - "pick_trigger_key_device", - PopupUi.SingleChoice(listItems) + "pick_trigger_key_device", + PopupUi.SingleChoice(listItems) ) ?: return@launch val selectedTriggerKeyDevice = when (triggerKeyDeviceId) { @@ -406,7 +441,7 @@ class ConfigKeyMapTriggerViewModel( linkType = linkDrawable, isDragDropEnabled = trigger.keys.size > 1 ) - } + } private fun getTriggerKeyDeviceName( device: TriggerKeyDevice, diff --git a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/ConfigKeyMapUseCase.kt b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/ConfigKeyMapUseCase.kt index a73a8d9dc8..c06dd3fd4e 100644 --- a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/ConfigKeyMapUseCase.kt +++ b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/ConfigKeyMapUseCase.kt @@ -16,7 +16,12 @@ import io.github.sds100.keymapper.mappings.keymaps.trigger.TriggerMode import io.github.sds100.keymapper.system.devices.DevicesAdapter import io.github.sds100.keymapper.system.devices.InputDeviceUtils import io.github.sds100.keymapper.system.keyevents.KeyEventUtils -import io.github.sds100.keymapper.util.* +import io.github.sds100.keymapper.util.Defaultable +import io.github.sds100.keymapper.util.State +import io.github.sds100.keymapper.util.dataOrNull +import io.github.sds100.keymapper.util.firstBlocking +import io.github.sds100.keymapper.util.ifIsData +import io.github.sds100.keymapper.util.moveElement import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map @@ -362,7 +367,7 @@ class ConfigKeyMapUseCaseImpl( repeat = true } } - + if (data is ActionData.AnswerCall) { addConstraint(Constraint.PhoneRinging) } diff --git a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/CreateKeyMapShortcutActivity.kt b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/CreateKeyMapShortcutActivity.kt index 2d97170e24..e174475eaf 100644 --- a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/CreateKeyMapShortcutActivity.kt +++ b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/CreateKeyMapShortcutActivity.kt @@ -4,12 +4,12 @@ import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import androidx.databinding.DataBindingUtil import androidx.lifecycle.Lifecycle -import io.github.sds100.keymapper.util.launchRepeatOnLifecycle import androidx.navigation.findNavController import io.github.sds100.keymapper.R import io.github.sds100.keymapper.ServiceLocator import io.github.sds100.keymapper.databinding.ActivityCreateKeymapShortcutBinding import io.github.sds100.keymapper.system.permissions.RequestPermissionDelegate +import io.github.sds100.keymapper.util.launchRepeatOnLifecycle import kotlinx.coroutines.flow.collectLatest /** diff --git a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/CreateKeyMapShortcutFragment.kt b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/CreateKeyMapShortcutFragment.kt index bd9d2669e5..7551e0dd3c 100644 --- a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/CreateKeyMapShortcutFragment.kt +++ b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/CreateKeyMapShortcutFragment.kt @@ -3,21 +3,25 @@ package io.github.sds100.keymapper.mappings.keymaps import android.app.Activity import androidx.fragment.app.activityViewModels import androidx.lifecycle.Lifecycle -import io.github.sds100.keymapper.util.launchRepeatOnLifecycle import com.airbnb.epoxy.EpoxyRecyclerView import io.github.sds100.keymapper.R import io.github.sds100.keymapper.databinding.FragmentSimpleRecyclerviewBinding import io.github.sds100.keymapper.keymap -import io.github.sds100.keymapper.util.ui.ChipUi +import io.github.sds100.keymapper.util.Inject import io.github.sds100.keymapper.util.State -import io.github.sds100.keymapper.util.ui.SimpleRecyclerViewFragment +import io.github.sds100.keymapper.util.launchRepeatOnLifecycle +import io.github.sds100.keymapper.util.str +import io.github.sds100.keymapper.util.ui.ChipUi import io.github.sds100.keymapper.util.ui.OnChipClickCallback +import io.github.sds100.keymapper.util.ui.SimpleRecyclerViewFragment import io.github.sds100.keymapper.util.ui.showPopups -import io.github.sds100.keymapper.util.Inject -import io.github.sds100.keymapper.util.str import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.collectLatest -import splitties.alertdialog.appcompat.* +import splitties.alertdialog.appcompat.alertDialog +import splitties.alertdialog.appcompat.messageResource +import splitties.alertdialog.appcompat.negativeButton +import splitties.alertdialog.appcompat.positiveButton +import splitties.alertdialog.appcompat.titleResource /** * Created by sds100 on 08/09/20. diff --git a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/CreateKeyMapShortcutUseCase.kt b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/CreateKeyMapShortcutUseCase.kt index a5b231bdd0..1e44df7338 100644 --- a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/CreateKeyMapShortcutUseCase.kt +++ b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/CreateKeyMapShortcutUseCase.kt @@ -6,9 +6,8 @@ import androidx.core.os.bundleOf import io.github.sds100.keymapper.R import io.github.sds100.keymapper.api.Api import io.github.sds100.keymapper.system.apps.AppShortcutAdapter -import io.github.sds100.keymapper.util.ui.ResourceProvider -import io.github.sds100.keymapper.system.accessibility.MyAccessibilityService import io.github.sds100.keymapper.util.Result +import io.github.sds100.keymapper.util.ui.ResourceProvider /** * Created by sds100 on 23/03/2021. diff --git a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/CreateKeyMapShortcutViewModel.kt b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/CreateKeyMapShortcutViewModel.kt index 46d4af883a..a1909e0f2f 100644 --- a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/CreateKeyMapShortcutViewModel.kt +++ b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/CreateKeyMapShortcutViewModel.kt @@ -16,12 +16,12 @@ import kotlinx.coroutines.launch * Created by sds100 on 08/09/20. */ class CreateKeyMapShortcutViewModel( - private val configKeyMapUseCase: ConfigKeyMapUseCase, - private val listUseCase: ListKeyMapsUseCase, - private val createShortcutUseCase: CreateKeyMapShortcutUseCase, - resourceProvider: ResourceProvider + private val configKeyMapUseCase: ConfigKeyMapUseCase, + private val listUseCase: ListKeyMapsUseCase, + private val createShortcutUseCase: CreateKeyMapShortcutUseCase, + resourceProvider: ResourceProvider ) : ViewModel(), PopupViewModel by PopupViewModelImpl(), - ResourceProvider by resourceProvider { + ResourceProvider by resourceProvider { private val listItemCreator = KeyMapListItemCreator(listUseCase, resourceProvider) @@ -35,11 +35,11 @@ class CreateKeyMapShortcutViewModel( val rebuildUiState = MutableSharedFlow>>(replay = 1) combine( - rebuildUiState, - listUseCase.showDeviceDescriptors + rebuildUiState, + listUseCase.showDeviceDescriptors ) { keyMapListState, showDeviceDescriptors -> val selectionUiState = - KeyMapListItem.SelectionUiState(isSelected = false, isSelectable = false) + KeyMapListItem.SelectionUiState(isSelected = false, isSelectable = false) _state.value = keyMapListState.mapData { keyMapList -> keyMapList.map { keyMap -> @@ -90,16 +90,16 @@ class CreateKeyMapShortcutViewModel( val key = "create_launcher_shortcut" val shortcutName = showPopup( - key, - PopupUi.Text( - getString(R.string.hint_shortcut_name), - allowEmpty = false - ) + key, + PopupUi.Text( + getString(R.string.hint_shortcut_name), + allowEmpty = false + ) ) ?: return@launch createShortcutUseCase.createIntentForMultipleActions( - keyMapUid = keyMap.uid, - shortcutLabel = shortcutName + keyMapUid = keyMap.uid, + shortcutLabel = shortcutName ) } @@ -130,9 +130,9 @@ class CreateKeyMapShortcutViewModel( private fun showDialogAndFixError(error: Error) { viewModelScope.launch { ViewModelHelper.showFixErrorDialog( - resourceProvider = this@CreateKeyMapShortcutViewModel, - popupViewModel = this@CreateKeyMapShortcutViewModel, - error + resourceProvider = this@CreateKeyMapShortcutViewModel, + popupViewModel = this@CreateKeyMapShortcutViewModel, + error ) { listUseCase.fixError(error) } @@ -140,10 +140,10 @@ class CreateKeyMapShortcutViewModel( } class Factory( - private val configKeyMapUseCase: ConfigKeyMapUseCase, - private val listUseCase: ListKeyMapsUseCase, - private val createShortcutUseCase: CreateKeyMapShortcutUseCase, - private val resourceProvider: ResourceProvider + private val configKeyMapUseCase: ConfigKeyMapUseCase, + private val listUseCase: ListKeyMapsUseCase, + private val createShortcutUseCase: CreateKeyMapShortcutUseCase, + private val resourceProvider: ResourceProvider ) : ViewModelProvider.Factory { @Suppress("UNCHECKED_CAST") diff --git a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/DisplayKeyMapUseCase.kt b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/DisplayKeyMapUseCase.kt index 7bbc0babdc..e172566068 100644 --- a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/DisplayKeyMapUseCase.kt +++ b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/DisplayKeyMapUseCase.kt @@ -10,7 +10,11 @@ import io.github.sds100.keymapper.system.inputmethod.InputMethodAdapter import io.github.sds100.keymapper.system.inputmethod.KeyMapperImeHelper import io.github.sds100.keymapper.system.permissions.Permission import io.github.sds100.keymapper.system.permissions.PermissionAdapter -import kotlinx.coroutines.flow.* +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.drop +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.merge /** * Created by sds100 on 04/04/2021. @@ -24,8 +28,8 @@ class DisplayKeyMapUseCaseImpl( ) : DisplayKeyMapUseCase, DisplaySimpleMappingUseCase by displaySimpleMappingUseCase { private companion object { val keysThatRequireDndAccess = arrayOf( - KeyEvent.KEYCODE_VOLUME_DOWN, - KeyEvent.KEYCODE_VOLUME_UP + KeyEvent.KEYCODE_VOLUME_DOWN, + KeyEvent.KEYCODE_VOLUME_UP ) } diff --git a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/EditKeyMapActionViewModel.kt b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/EditKeyMapActionViewModel.kt index 37dbd87cd9..61396acfb9 100644 --- a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/EditKeyMapActionViewModel.kt +++ b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/EditKeyMapActionViewModel.kt @@ -7,7 +7,16 @@ import io.github.sds100.keymapper.mappings.EditActionViewModel import io.github.sds100.keymapper.mappings.OptionMinimums import io.github.sds100.keymapper.mappings.isDelayBeforeNextActionAllowed import io.github.sds100.keymapper.util.Defaultable -import io.github.sds100.keymapper.util.ui.* +import io.github.sds100.keymapper.util.ui.CheckBoxListItem +import io.github.sds100.keymapper.util.ui.DividerListItem +import io.github.sds100.keymapper.util.ui.ListItem +import io.github.sds100.keymapper.util.ui.RadioButtonPairListItem +import io.github.sds100.keymapper.util.ui.RadioButtonTripleListItem +import io.github.sds100.keymapper.util.ui.ResourceProvider +import io.github.sds100.keymapper.util.ui.SliderListItem +import io.github.sds100.keymapper.util.ui.SliderMaximums +import io.github.sds100.keymapper.util.ui.SliderModel +import io.github.sds100.keymapper.util.ui.SliderStepSizes import kotlinx.coroutines.CoroutineScope /** @@ -84,6 +93,7 @@ class EditKeyMapActionViewModel( actionUid, value.nullIfDefault() ) + ID_MULTIPLIER -> config.setActionMultiplier(actionUid, value.nullIfDefault()) ID_DELAY_BEFORE_NEXT_ACTION -> config.setDelayBeforeNextAction( actionUid, diff --git a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/KeyMap.kt b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/KeyMap.kt index 8108865cdd..55c26363d0 100644 --- a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/KeyMap.kt +++ b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/KeyMap.kt @@ -12,7 +12,7 @@ import io.github.sds100.keymapper.mappings.keymaps.detection.KeyMapController import io.github.sds100.keymapper.mappings.keymaps.trigger.KeyMapTrigger import io.github.sds100.keymapper.mappings.keymaps.trigger.KeymapTriggerEntityMapper import kotlinx.serialization.Serializable -import java.util.* +import java.util.UUID /** * Created by sds100 on 03/03/2021. @@ -20,12 +20,12 @@ import java.util.* @Serializable data class KeyMap( - val dbId: Long? = null, - val uid: String = UUID.randomUUID().toString(), - val trigger: KeyMapTrigger = KeyMapTrigger(), - override val actionList: List = emptyList(), - override val constraintState: ConstraintState = ConstraintState(), - override val isEnabled: Boolean = true + val dbId: Long? = null, + val uid: String = UUID.randomUUID().toString(), + val trigger: KeyMapTrigger = KeyMapTrigger(), + override val actionList: List = emptyList(), + override val constraintState: ConstraintState = ConstraintState(), + override val isEnabled: Boolean = true ) : Mapping { override val showToast: Boolean @@ -76,7 +76,7 @@ data class KeyMap( */ fun KeyMap.requiresImeKeyEventForwarding(): Boolean { return trigger.keys.any { it.keyCode == KeyEvent.KEYCODE_VOLUME_DOWN || it.keyCode == KeyEvent.KEYCODE_VOLUME_UP } - && actionList.any { it.data is ActionData.AnswerCall || it.data is ActionData.EndCall } + && actionList.any { it.data is ActionData.AnswerCall || it.data is ActionData.EndCall } } object KeyMapEntityMapper { @@ -84,17 +84,17 @@ object KeyMapEntityMapper { val actionList = entity.actionList.mapNotNull { KeymapActionEntityMapper.fromEntity(it) } val constraintList = - entity.constraintList.map { ConstraintEntityMapper.fromEntity(it) }.toSet() + entity.constraintList.map { ConstraintEntityMapper.fromEntity(it) }.toSet() val constraintMode = ConstraintModeEntityMapper.fromEntity(entity.constraintMode) return KeyMap( - dbId = entity.id, - uid = entity.uid, - trigger = KeymapTriggerEntityMapper.fromEntity(entity.trigger), - actionList = actionList, - constraintState = ConstraintState(constraintList, constraintMode), - isEnabled = entity.isEnabled + dbId = entity.id, + uid = entity.uid, + trigger = KeymapTriggerEntityMapper.fromEntity(entity.trigger), + actionList = actionList, + constraintState = ConstraintState(constraintList, constraintMode), + isEnabled = entity.isEnabled ) } @@ -103,17 +103,17 @@ object KeyMapEntityMapper { val actionEntityList = KeymapActionEntityMapper.toEntity(keyMap) return KeyMapEntity( - id = dbId, - trigger = KeymapTriggerEntityMapper.toEntity(keyMap.trigger), - actionList = actionEntityList, - constraintList = keyMap.constraintState.constraints.map { - ConstraintEntityMapper.toEntity( - it - ) - }, - constraintMode = ConstraintModeEntityMapper.toEntity(keyMap.constraintState.mode), - isEnabled = keyMap.isEnabled, - uid = keyMap.uid + id = dbId, + trigger = KeymapTriggerEntityMapper.toEntity(keyMap.trigger), + actionList = actionEntityList, + constraintList = keyMap.constraintState.constraints.map { + ConstraintEntityMapper.toEntity( + it + ) + }, + constraintMode = ConstraintModeEntityMapper.toEntity(keyMap.constraintState.mode), + isEnabled = keyMap.isEnabled, + uid = keyMap.uid ) } } \ No newline at end of file diff --git a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/KeyMapAction.kt b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/KeyMapAction.kt index 3d7da8ccb2..36ff232474 100644 --- a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/KeyMapAction.kt +++ b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/KeyMapAction.kt @@ -14,7 +14,7 @@ import io.github.sds100.keymapper.util.valueOrNull import kotlinx.serialization.Serializable import splitties.bitflags.hasFlag import splitties.bitflags.withFlag -import java.util.* +import java.util.UUID /** * Created by sds100 on 09/03/2021. @@ -113,7 +113,7 @@ object KeymapActionEntityMapper { } fun toEntity(keyMap: KeyMap): List = keyMap.actionList.mapNotNull { action -> - val base = ActionDataEntityMapper.toEntity(action.data) ?: return@mapNotNull null + val base = ActionDataEntityMapper.toEntity(action.data) val extras = mutableListOf().apply { if (keyMap.isDelayBeforeNextActionAllowed() && action.delayBeforeNextAction != null) { diff --git a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/KeyMapActionUiHelper.kt b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/KeyMapActionUiHelper.kt index 72f1c02f08..4318a780ca 100644 --- a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/KeyMapActionUiHelper.kt +++ b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/KeyMapActionUiHelper.kt @@ -51,6 +51,7 @@ class KeyMapActionUiHelper( RepeatMode.TRIGGER_PRESSED_AGAIN -> { append(getString(R.string.flag_repeat_build_description_until_pressed_again)) } + else -> Unit } } diff --git a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/KeyMapConfigActionsFragment.kt b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/KeyMapConfigActionsFragment.kt index a11464cbe3..6a10110a6e 100644 --- a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/KeyMapConfigActionsFragment.kt +++ b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/KeyMapConfigActionsFragment.kt @@ -2,8 +2,8 @@ package io.github.sds100.keymapper.mappings.keymaps import androidx.navigation.navGraphViewModels import io.github.sds100.keymapper.R -import io.github.sds100.keymapper.actions.ConfigActionsViewModel import io.github.sds100.keymapper.actions.ConfigActionsFragment +import io.github.sds100.keymapper.actions.ConfigActionsViewModel import io.github.sds100.keymapper.util.FragmentInfo import io.github.sds100.keymapper.util.Inject diff --git a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/KeyMapListItemCreator.kt b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/KeyMapListItemCreator.kt index c715468fd6..511e28b808 100644 --- a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/KeyMapListItemCreator.kt +++ b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/KeyMapListItemCreator.kt @@ -18,25 +18,25 @@ import io.github.sds100.keymapper.util.ui.ResourceProvider * Created by sds100 on 19/03/2021. */ class KeyMapListItemCreator( - private val displayMapping: DisplayKeyMapUseCase, - resourceProvider: ResourceProvider + private val displayMapping: DisplayKeyMapUseCase, + resourceProvider: ResourceProvider ) : BaseMappingListItemCreator( - displayMapping, - KeyMapActionUiHelper(displayMapping, resourceProvider), - resourceProvider + displayMapping, + KeyMapActionUiHelper(displayMapping, resourceProvider), + resourceProvider ) { - suspend fun create(keyMap: KeyMap, showDeviceDescriptors: Boolean): KeyMapListItem.KeyMapUiState { - val midDot = getString(R.string.middot) + suspend fun create(keyMap: KeyMap, showDeviceDescriptors: Boolean): KeyMapListItem.KeyMapUiState { + val midDot = getString(R.string.middot) - val triggerDescription = buildString { - val separator = when (keyMap.trigger.mode) { - is TriggerMode.Parallel -> getString(R.string.plus) - is TriggerMode.Sequence -> getString(R.string.arrow) - is TriggerMode.Undefined -> null - } + val triggerDescription = buildString { + val separator = when (keyMap.trigger.mode) { + is TriggerMode.Parallel -> getString(R.string.plus) + is TriggerMode.Sequence -> getString(R.string.arrow) + is TriggerMode.Undefined -> null + } - val longPressString = getString(R.string.clicktype_long_press) + val longPressString = getString(R.string.clicktype_long_press) val doublePressString = getString(R.string.clicktype_double_press) keyMap.trigger.keys.forEachIndexed { index, key -> @@ -58,8 +58,8 @@ class KeyMapListItemCreator( is TriggerKeyDevice.External -> { if (showDeviceDescriptors) { InputDeviceUtils.appendDeviceDescriptorToName( - key.device.descriptor, - key.device.name + key.device.descriptor, + key.device.name ) } else { key.device.name @@ -110,33 +110,33 @@ class KeyMapListItemCreator( when (it) { KeyMapTriggerError.DND_ACCESS_DENIED -> ChipUi.Error( - id = KeyMapTriggerError.DND_ACCESS_DENIED.toString(), - text = getString(R.string.trigger_error_dnd_access_denied_short), - error = Error.PermissionDenied(Permission.ACCESS_NOTIFICATION_POLICY) + id = KeyMapTriggerError.DND_ACCESS_DENIED.toString(), + text = getString(R.string.trigger_error_dnd_access_denied_short), + error = Error.PermissionDenied(Permission.ACCESS_NOTIFICATION_POLICY) ) KeyMapTriggerError.SCREEN_OFF_ROOT_DENIED -> ChipUi.Error( - id = KeyMapTriggerError.SCREEN_OFF_ROOT_DENIED.toString(), - text = getString(R.string.trigger_error_screen_off_root_permission_denied_short), - error = Error.PermissionDenied(Permission.ROOT) + id = KeyMapTriggerError.SCREEN_OFF_ROOT_DENIED.toString(), + text = getString(R.string.trigger_error_screen_off_root_permission_denied_short), + error = Error.PermissionDenied(Permission.ROOT) ) - + KeyMapTriggerError.CANT_DETECT_IN_PHONE_CALL -> ChipUi.Error( - id = KeyMapTriggerError.SCREEN_OFF_ROOT_DENIED.toString(), - text = getString(R.string.trigger_error_cant_detect_in_phone_call), - error = Error.CantDetectKeyEventsInPhoneCall + id = KeyMapTriggerError.SCREEN_OFF_ROOT_DENIED.toString(), + text = getString(R.string.trigger_error_cant_detect_in_phone_call), + error = Error.CantDetectKeyEventsInPhoneCall ) } } return KeyMapListItem.KeyMapUiState( - uid = keyMap.uid, - actionChipList = actionChipList, - constraintChipList = constraintChipList, - triggerDescription = triggerDescription, - optionsDescription = optionsDescription, - extraInfo = extraInfo, - triggerErrorChipList = triggerErrorChips + uid = keyMap.uid, + actionChipList = actionChipList, + constraintChipList = constraintChipList, + triggerDescription = triggerDescription, + optionsDescription = optionsDescription, + extraInfo = extraInfo, + triggerErrorChipList = triggerErrorChips ) } diff --git a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/KeyMapListViewModel.kt b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/KeyMapListViewModel.kt index bc2435d377..48cda08ae1 100644 --- a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/KeyMapListViewModel.kt +++ b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/KeyMapListViewModel.kt @@ -4,10 +4,28 @@ import io.github.sds100.keymapper.system.permissions.Permission import io.github.sds100.keymapper.util.Error import io.github.sds100.keymapper.util.State import io.github.sds100.keymapper.util.mapData -import io.github.sds100.keymapper.util.ui.* +import io.github.sds100.keymapper.util.ui.ChipUi +import io.github.sds100.keymapper.util.ui.MultiSelectProvider +import io.github.sds100.keymapper.util.ui.NavDestination +import io.github.sds100.keymapper.util.ui.NavigationViewModel +import io.github.sds100.keymapper.util.ui.NavigationViewModelImpl +import io.github.sds100.keymapper.util.ui.PopupViewModel +import io.github.sds100.keymapper.util.ui.PopupViewModelImpl +import io.github.sds100.keymapper.util.ui.ResourceProvider +import io.github.sds100.keymapper.util.ui.SelectionState +import io.github.sds100.keymapper.util.ui.ViewModelHelper +import io.github.sds100.keymapper.util.ui.navigate import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.flow.* +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.collectLatest +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.drop +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.flowOn +import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.launch open class KeyMapListViewModel constructor( @@ -150,9 +168,9 @@ open class KeyMapListViewModel constructor( private fun showDialogAndFixError(error: Error) { coroutineScope.launch { ViewModelHelper.showFixErrorDialog( - resourceProvider = this@KeyMapListViewModel, - popupViewModel = this@KeyMapListViewModel, - error + resourceProvider = this@KeyMapListViewModel, + popupViewModel = this@KeyMapListViewModel, + error ) { useCase.fixError(error) } diff --git a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/TriggerKeyMapFromOtherAppsController.kt b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/TriggerKeyMapFromOtherAppsController.kt index 28c4680f60..ec867d3b1d 100644 --- a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/TriggerKeyMapFromOtherAppsController.kt +++ b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/TriggerKeyMapFromOtherAppsController.kt @@ -1,10 +1,9 @@ package io.github.sds100.keymapper.mappings.keymaps -import io.github.sds100.keymapper.constraints.DetectConstraintsUseCase import io.github.sds100.keymapper.actions.PerformActionsUseCase +import io.github.sds100.keymapper.constraints.DetectConstraintsUseCase import io.github.sds100.keymapper.mappings.SimpleMappingController import io.github.sds100.keymapper.mappings.keymaps.detection.DetectKeyMapsUseCase -import io.github.sds100.keymapper.util.* import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.launch @@ -42,7 +41,7 @@ class TriggerKeyMapFromOtherAppsController( onDetected(keyMap.uid, keyMap) Timber.d("Triggered key map successfully from Intent, $keyMap") - }else{ + } else { Timber.d("Failed to trigger key map from intent because key map doesn't exist, uid = $uid") } } diff --git a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/detection/DetectKeyMapsUseCase.kt b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/detection/DetectKeyMapsUseCase.kt index d5370b7809..d83e418511 100644 --- a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/detection/DetectKeyMapsUseCase.kt +++ b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/detection/DetectKeyMapsUseCase.kt @@ -27,7 +27,11 @@ import io.github.sds100.keymapper.system.volume.VolumeAdapter import io.github.sds100.keymapper.util.InputEventType import io.github.sds100.keymapper.util.State import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.flow.* +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.flowOn +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.mapNotNull import timber.log.Timber /** diff --git a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/detection/DetectScreenOffKeyEventsController.kt b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/detection/DetectScreenOffKeyEventsController.kt index 58d88a0adf..7af96198a4 100644 --- a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/detection/DetectScreenOffKeyEventsController.kt +++ b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/detection/DetectScreenOffKeyEventsController.kt @@ -7,8 +7,12 @@ import io.github.sds100.keymapper.system.keyevents.KeyEventUtils import io.github.sds100.keymapper.system.root.SuAdapter import io.github.sds100.keymapper.util.State import io.github.sds100.keymapper.util.valueOrNull -import kotlinx.coroutines.* +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job import kotlinx.coroutines.flow.first +import kotlinx.coroutines.isActive +import kotlinx.coroutines.launch import timber.log.Timber /** diff --git a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/detection/KeyMapController.kt b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/detection/KeyMapController.kt index 4b8ce4c56c..48a8570fc6 100644 --- a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/detection/KeyMapController.kt +++ b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/detection/KeyMapController.kt @@ -880,7 +880,7 @@ class KeyMapController( return true } } - } + } return false } @@ -1146,37 +1146,37 @@ class KeyMapController( } } - //long press - if (keyAwaitingRelease && trigger.matchingEventAtIndex( - event.withLongPress, - keyIndex - ) - ) { - parallelTriggerEventsAwaitingRelease[triggerIndex][keyIndex] = false + //long press + if (keyAwaitingRelease && trigger.matchingEventAtIndex( + event.withLongPress, + keyIndex + ) + ) { + parallelTriggerEventsAwaitingRelease[triggerIndex][keyIndex] = false - parallelTriggerLongPressJobs[triggerIndex]?.cancel() + parallelTriggerLongPressJobs[triggerIndex]?.cancel() - if (triggers[triggerIndex].keys[keyIndex].consumeKeyEvent) { - consumeEvent = true - } + if (triggers[triggerIndex].keys[keyIndex].consumeKeyEvent) { + consumeEvent = true + } - val lastMatchedIndex = lastMatchedEventIndices[triggerIndex] + val lastMatchedIndex = lastMatchedEventIndices[triggerIndex] - if (isSingleKeyTrigger && successfulLongPressTrigger) { - longPressSingleKeyTriggerJustReleased = true - } + if (isSingleKeyTrigger && successfulLongPressTrigger) { + longPressSingleKeyTriggerJustReleased = true + } - if (!imitateDownUpKeyEvent) { - if (isSingleKeyTrigger && !successfulLongPressTrigger && !releasedSuccessfulTrigger) { - imitateDownUpKeyEvent = true - } else if (lastMatchedIndex > -1 - && lastMatchedIndex < triggers[triggerIndex].keys.lastIndex - && !releasedSuccessfulTrigger - ) { - imitateDownUpKeyEvent = true - } + if (!imitateDownUpKeyEvent) { + if (isSingleKeyTrigger && !successfulLongPressTrigger && !releasedSuccessfulTrigger) { + imitateDownUpKeyEvent = true + } else if (lastMatchedIndex > -1 + && lastMatchedIndex < triggers[triggerIndex].keys.lastIndex + && !releasedSuccessfulTrigger + ) { + imitateDownUpKeyEvent = true } } + } if (parallelTriggerEventsAwaitingRelease[triggerIndex][keyIndex] && lastHeldDownEventIndex == keyIndex - 1 diff --git a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/detection/ParallelTriggerActionPerformer.kt b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/detection/ParallelTriggerActionPerformer.kt index 9caec173dd..4a9524d631 100644 --- a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/detection/ParallelTriggerActionPerformer.kt +++ b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/detection/ParallelTriggerActionPerformer.kt @@ -7,10 +7,14 @@ import io.github.sds100.keymapper.data.PreferenceDefaults import io.github.sds100.keymapper.mappings.keymaps.KeyMapAction import io.github.sds100.keymapper.system.keyevents.KeyEventUtils import io.github.sds100.keymapper.util.InputEventType -import kotlinx.coroutines.* +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Job +import kotlinx.coroutines.delay import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.isActive +import kotlinx.coroutines.launch /** * Created by sds100 on 16/06/2021. diff --git a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/trigger/ChooseTriggerKeyDeviceModel.kt b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/trigger/ChooseTriggerKeyDeviceModel.kt index 04eaf6af6e..955b633646 100644 --- a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/trigger/ChooseTriggerKeyDeviceModel.kt +++ b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/trigger/ChooseTriggerKeyDeviceModel.kt @@ -1,7 +1,5 @@ package io.github.sds100.keymapper.mappings.keymaps.trigger -import io.github.sds100.keymapper.mappings.keymaps.trigger.TriggerKeyDevice - /** * Created by sds100 on 07/03/2021. */ diff --git a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/trigger/ConfigTriggerKeyViewModel.kt b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/trigger/ConfigTriggerKeyViewModel.kt index ad8e169889..c56f77d79d 100644 --- a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/trigger/ConfigTriggerKeyViewModel.kt +++ b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/trigger/ConfigTriggerKeyViewModel.kt @@ -13,7 +13,11 @@ import io.github.sds100.keymapper.util.ui.RadioButtonTripleListItem import io.github.sds100.keymapper.util.ui.ResourceProvider import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.flow.* +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.flowOn +import kotlinx.coroutines.flow.stateIn /** * Created by sds100 on 12/04/2021. diff --git a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/trigger/ConfigTriggerOptionsFragment.kt b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/trigger/ConfigTriggerOptionsFragment.kt index 94540a04cc..e6b633ce9e 100644 --- a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/trigger/ConfigTriggerOptionsFragment.kt +++ b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/trigger/ConfigTriggerOptionsFragment.kt @@ -10,14 +10,16 @@ import io.github.sds100.keymapper.mappings.keymaps.ConfigKeyMapTriggerOptionsVie import io.github.sds100.keymapper.mappings.keymaps.ConfigKeyMapViewModel import io.github.sds100.keymapper.system.url.UrlUtils import io.github.sds100.keymapper.triggerFromOtherApps -import io.github.sds100.keymapper.ui.* import io.github.sds100.keymapper.ui.utils.configuredCheckBox import io.github.sds100.keymapper.ui.utils.configuredSlider import io.github.sds100.keymapper.util.FragmentInfo import io.github.sds100.keymapper.util.Inject import io.github.sds100.keymapper.util.State import io.github.sds100.keymapper.util.str -import io.github.sds100.keymapper.util.ui.* +import io.github.sds100.keymapper.util.ui.CheckBoxListItem +import io.github.sds100.keymapper.util.ui.ListItem +import io.github.sds100.keymapper.util.ui.SimpleRecyclerViewFragment +import io.github.sds100.keymapper.util.ui.SliderListItem import kotlinx.coroutines.flow.Flow import splitties.toast.toast diff --git a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/trigger/RecordTriggerUseCase.kt b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/trigger/RecordTriggerUseCase.kt index 122903e9ce..783722069b 100644 --- a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/trigger/RecordTriggerUseCase.kt +++ b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/trigger/RecordTriggerUseCase.kt @@ -4,7 +4,11 @@ import io.github.sds100.keymapper.system.accessibility.ServiceAdapter import io.github.sds100.keymapper.util.Event import io.github.sds100.keymapper.util.Result import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.flow.* +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.mapNotNull +import kotlinx.coroutines.flow.onEach /** * Created by sds100 on 04/03/2021. diff --git a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/trigger/TriggerFragment.kt b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/trigger/TriggerFragment.kt index d008442f56..84521da718 100644 --- a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/trigger/TriggerFragment.kt +++ b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/trigger/TriggerFragment.kt @@ -17,7 +17,11 @@ import io.github.sds100.keymapper.fixError import io.github.sds100.keymapper.mappings.keymaps.ConfigKeyMapTriggerViewModel import io.github.sds100.keymapper.mappings.keymaps.ConfigKeyMapViewModel import io.github.sds100.keymapper.triggerKey -import io.github.sds100.keymapper.util.* +import io.github.sds100.keymapper.util.FragmentInfo +import io.github.sds100.keymapper.util.Inject +import io.github.sds100.keymapper.util.State +import io.github.sds100.keymapper.util.color +import io.github.sds100.keymapper.util.launchRepeatOnLifecycle import io.github.sds100.keymapper.util.ui.RecyclerViewFragment import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.collectLatest diff --git a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/trigger/TriggerKey.kt b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/trigger/TriggerKey.kt index 1d0653affa..95c752af4f 100644 --- a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/trigger/TriggerKey.kt +++ b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/trigger/TriggerKey.kt @@ -5,7 +5,7 @@ import io.github.sds100.keymapper.mappings.ClickType import kotlinx.serialization.Serializable import splitties.bitflags.hasFlag import splitties.bitflags.withFlag -import java.util.* +import java.util.UUID /** * Created by sds100 on 21/02/2021. diff --git a/app/src/main/java/io/github/sds100/keymapper/onboarding/AppIntroViewModel.kt b/app/src/main/java/io/github/sds100/keymapper/onboarding/AppIntroViewModel.kt index 74730f74a8..cc5617c87f 100644 --- a/app/src/main/java/io/github/sds100/keymapper/onboarding/AppIntroViewModel.kt +++ b/app/src/main/java/io/github/sds100/keymapper/onboarding/AppIntroViewModel.kt @@ -43,11 +43,13 @@ class AppIntroViewModel( AppIntroSlide.BATTERY_OPTIMISATION -> batteryOptimisationSlide(isBatteryOptimised) AppIntroSlide.FINGERPRINT_GESTURE_SUPPORT -> fingerprintGestureSupportSlide(fingerprintGesturesSupported) + AppIntroSlide.CONTRIBUTING -> contributingSlide() AppIntroSlide.SETUP_CHOSEN_DEVICES_AGAIN -> setupChosenDevicesAgainSlide() AppIntroSlide.GRANT_SHIZUKU_PERMISSION -> requestShizukuPermissionSlide( isShizukuPermissionGranted ) + else -> throw Exception("Unknown slide $slide") } } @@ -67,6 +69,7 @@ class AppIntroViewModel( PopupUi.OpenUrl(getString(R.string.url_dont_kill_my_app)) ) } + ID_BUTTON_DISABLE_BATTERY_OPTIMISATION -> useCase.ignoreBatteryOptimisation() ID_BUTTON_MORE_SHIZUKU_INFO -> runBlocking { showPopup( diff --git a/app/src/main/java/io/github/sds100/keymapper/onboarding/OnboardingUseCase.kt b/app/src/main/java/io/github/sds100/keymapper/onboarding/OnboardingUseCase.kt index 04ead1ad45..568898943e 100644 --- a/app/src/main/java/io/github/sds100/keymapper/onboarding/OnboardingUseCase.kt +++ b/app/src/main/java/io/github/sds100/keymapper/onboarding/OnboardingUseCase.kt @@ -42,17 +42,17 @@ class OnboardingUseCaseImpl( packageManagerAdapter.isAppInstalled(KeyMapperImeHelper.KEY_MAPPER_GUI_IME_PACKAGE) val isShizukuInstalled = shizukuAdapter.isInstalled.value - + return (acknowledged == null || !acknowledged) - && !isGuiKeyboardInstalled - && !isShizukuInstalled - && action.canUseImeToPerform() + && !isGuiKeyboardInstalled + && !isShizukuInstalled + && action.canUseImeToPerform() } override suspend fun showInstallShizukuPrompt(action: ActionData): Boolean { return !shizukuAdapter.isInstalled.value - && ShizukuUtils.isRecommendedForSdkVersion() - && action.canUseShizukuToPerform() + && ShizukuUtils.isRecommendedForSdkVersion() + && action.canUseShizukuToPerform() } override fun neverShowGuiKeyboardPromptsAgain() { @@ -97,9 +97,9 @@ class OnboardingUseCaseImpl( val handledUpdateInHomeScreen = !showWhatsNew oldVersionCode < VersionHelper.FINGERPRINT_GESTURES_MIN_VERSION - && !handledUpdateInHomeScreen - && !approvedPrompt - && shownAppIntro + && !handledUpdateInHomeScreen + && !approvedPrompt + && shownAppIntro } } diff --git a/app/src/main/java/io/github/sds100/keymapper/reportbug/ReportBugActivity.kt b/app/src/main/java/io/github/sds100/keymapper/reportbug/ReportBugActivity.kt index c80b245bf8..f087a3dd73 100644 --- a/app/src/main/java/io/github/sds100/keymapper/reportbug/ReportBugActivity.kt +++ b/app/src/main/java/io/github/sds100/keymapper/reportbug/ReportBugActivity.kt @@ -1,7 +1,7 @@ package io.github.sds100.keymapper.reportbug import android.os.Bundle -import androidx.activity.result.contract.ActivityResultContracts +import androidx.activity.result.contract.ActivityResultContracts.CreateDocument import androidx.activity.viewModels import androidx.core.os.bundleOf import androidx.fragment.app.Fragment @@ -27,7 +27,7 @@ class ReportBugActivity : AppIntro2() { private lateinit var requestPermissionDelegate: RequestPermissionDelegate private val chooseReportLocationLauncher = - registerForActivityResult(ActivityResultContracts.CreateDocument()) { + registerForActivityResult(CreateDocument("todo/todo")) { it ?: return@registerForActivityResult viewModel.onChooseBugReportLocation(it.toString()) diff --git a/app/src/main/java/io/github/sds100/keymapper/reportbug/ReportBugUseCase.kt b/app/src/main/java/io/github/sds100/keymapper/reportbug/ReportBugUseCase.kt index 3f107905ce..3ec0f22530 100644 --- a/app/src/main/java/io/github/sds100/keymapper/reportbug/ReportBugUseCase.kt +++ b/app/src/main/java/io/github/sds100/keymapper/reportbug/ReportBugUseCase.kt @@ -7,12 +7,16 @@ import io.github.sds100.keymapper.logging.LogRepository import io.github.sds100.keymapper.logging.LogUtils import io.github.sds100.keymapper.system.files.FileAdapter import io.github.sds100.keymapper.system.files.IFile -import io.github.sds100.keymapper.util.* +import io.github.sds100.keymapper.util.Error +import io.github.sds100.keymapper.util.Result +import io.github.sds100.keymapper.util.State +import io.github.sds100.keymapper.util.ifIsData +import io.github.sds100.keymapper.util.onFailure import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.first import kotlinx.coroutines.withContext import timber.log.Timber -import java.util.* +import java.util.UUID /** * Created by sds100 on 30/06/2021. diff --git a/app/src/main/java/io/github/sds100/keymapper/reroutekeyevents/RerouteKeyEventsController.kt b/app/src/main/java/io/github/sds100/keymapper/reroutekeyevents/RerouteKeyEventsController.kt index 02fe440791..6926ee8b00 100644 --- a/app/src/main/java/io/github/sds100/keymapper/reroutekeyevents/RerouteKeyEventsController.kt +++ b/app/src/main/java/io/github/sds100/keymapper/reroutekeyevents/RerouteKeyEventsController.kt @@ -4,7 +4,11 @@ import android.view.KeyEvent import io.github.sds100.keymapper.system.devices.InputDeviceInfo import io.github.sds100.keymapper.system.inputmethod.InputKeyModel import io.github.sds100.keymapper.util.InputEventType -import kotlinx.coroutines.* +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Job +import kotlinx.coroutines.delay +import kotlinx.coroutines.isActive +import kotlinx.coroutines.launch /** * Created by sds100 on 27/04/2021. diff --git a/app/src/main/java/io/github/sds100/keymapper/settings/BaseSettingsFragment.kt b/app/src/main/java/io/github/sds100/keymapper/settings/BaseSettingsFragment.kt index b2f2f9f700..3ee74791be 100644 --- a/app/src/main/java/io/github/sds100/keymapper/settings/BaseSettingsFragment.kt +++ b/app/src/main/java/io/github/sds100/keymapper/settings/BaseSettingsFragment.kt @@ -31,7 +31,7 @@ abstract class BaseSettingsFragment : PreferenceFragmentCompat() { view.findViewById(R.id.appBar).apply { replaceMenu(R.menu.menu_settings) - + setNavigationOnClickListener { onBackPressed() } diff --git a/app/src/main/java/io/github/sds100/keymapper/settings/ConfigSettingsUseCase.kt b/app/src/main/java/io/github/sds100/keymapper/settings/ConfigSettingsUseCase.kt index 6d357b7799..3f5479c260 100644 --- a/app/src/main/java/io/github/sds100/keymapper/settings/ConfigSettingsUseCase.kt +++ b/app/src/main/java/io/github/sds100/keymapper/settings/ConfigSettingsUseCase.kt @@ -19,7 +19,11 @@ import io.github.sds100.keymapper.system.permissions.PermissionAdapter import io.github.sds100.keymapper.system.root.SuAdapter import io.github.sds100.keymapper.util.Result import io.github.sds100.keymapper.util.State -import kotlinx.coroutines.flow.* +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.channelFlow +import kotlinx.coroutines.flow.collectLatest +import kotlinx.coroutines.flow.map /** * Created by sds100 on 14/02/2021. diff --git a/app/src/main/java/io/github/sds100/keymapper/settings/DefaultOptionsSettingsFragment.kt b/app/src/main/java/io/github/sds100/keymapper/settings/DefaultOptionsSettingsFragment.kt index 5e63f61e3e..7492098389 100644 --- a/app/src/main/java/io/github/sds100/keymapper/settings/DefaultOptionsSettingsFragment.kt +++ b/app/src/main/java/io/github/sds100/keymapper/settings/DefaultOptionsSettingsFragment.kt @@ -3,7 +3,9 @@ package io.github.sds100.keymapper.settings import android.os.Bundle import android.view.View import androidx.lifecycle.Lifecycle -import androidx.preference.* +import androidx.preference.Preference +import androidx.preference.SeekBarPreference +import androidx.preference.isEmpty import io.github.sds100.keymapper.R import io.github.sds100.keymapper.data.Keys import io.github.sds100.keymapper.data.PreferenceDefaults diff --git a/app/src/main/java/io/github/sds100/keymapper/settings/MainSettingsFragment.kt b/app/src/main/java/io/github/sds100/keymapper/settings/MainSettingsFragment.kt index f3b8fe6c62..7700884b32 100644 --- a/app/src/main/java/io/github/sds100/keymapper/settings/MainSettingsFragment.kt +++ b/app/src/main/java/io/github/sds100/keymapper/settings/MainSettingsFragment.kt @@ -5,7 +5,7 @@ import android.content.Intent import android.os.Build import android.os.Bundle import android.view.View -import androidx.activity.result.contract.ActivityResultContracts +import androidx.activity.result.contract.ActivityResultContracts.CreateDocument import androidx.lifecycle.Lifecycle import androidx.navigation.fragment.findNavController import androidx.preference.* @@ -39,7 +39,7 @@ class MainSettingsFragment : BaseSettingsFragment() { } private val chooseAutomaticBackupLocationLauncher = - registerForActivityResult(ActivityResultContracts.CreateDocument()) { + registerForActivityResult(CreateDocument("todo/todo")) { it ?: return@registerForActivityResult viewModel.setAutomaticBackupLocation(it.toString()) diff --git a/app/src/main/java/io/github/sds100/keymapper/settings/ShizukuSettingsFragment.kt b/app/src/main/java/io/github/sds100/keymapper/settings/ShizukuSettingsFragment.kt index 75bb6e57f8..32b2cfbdd0 100644 --- a/app/src/main/java/io/github/sds100/keymapper/settings/ShizukuSettingsFragment.kt +++ b/app/src/main/java/io/github/sds100/keymapper/settings/ShizukuSettingsFragment.kt @@ -37,11 +37,11 @@ class ShizukuSettingsFragment : BaseSettingsFragment() { private fun populatePreferenceScreen() = preferenceScreen.apply { //summary - Preference(requireContext()).apply { + Preference(requireContext()).apply { setSummary(R.string.summary_pref_category_shizuku_follow_steps) addPreference(this) } - + //install shizuku Preference(requireContext()).apply { viewLifecycleOwner.launchRepeatOnLifecycle(Lifecycle.State.RESUMED) { diff --git a/app/src/main/java/io/github/sds100/keymapper/shizuku/InputEventInjector.kt b/app/src/main/java/io/github/sds100/keymapper/shizuku/InputEventInjector.kt index fb22e0c8b0..a3c6a520dd 100644 --- a/app/src/main/java/io/github/sds100/keymapper/shizuku/InputEventInjector.kt +++ b/app/src/main/java/io/github/sds100/keymapper/shizuku/InputEventInjector.kt @@ -3,7 +3,6 @@ package io.github.sds100.keymapper.shizuku import android.annotation.SuppressLint import android.content.Context import android.hardware.input.IInputManager -import android.os.IBinder import android.os.SystemClock import android.view.KeyEvent import io.github.sds100.keymapper.system.inputmethod.InputKeyModel diff --git a/app/src/main/java/io/github/sds100/keymapper/shizuku/ShizukuAdapterImpl.kt b/app/src/main/java/io/github/sds100/keymapper/shizuku/ShizukuAdapterImpl.kt index 8b678ac54e..613f7e013a 100644 --- a/app/src/main/java/io/github/sds100/keymapper/shizuku/ShizukuAdapterImpl.kt +++ b/app/src/main/java/io/github/sds100/keymapper/shizuku/ShizukuAdapterImpl.kt @@ -4,7 +4,13 @@ import io.github.sds100.keymapper.system.apps.PackageManagerAdapter import io.github.sds100.keymapper.util.State import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.flow.* +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.filter +import kotlinx.coroutines.flow.flowOn +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.stateIn import rikka.shizuku.Shizuku /** diff --git a/app/src/main/java/io/github/sds100/keymapper/system/BuildUtils.kt b/app/src/main/java/io/github/sds100/keymapper/system/BuildUtils.kt index b6a7de59b3..f742625803 100644 --- a/app/src/main/java/io/github/sds100/keymapper/system/BuildUtils.kt +++ b/app/src/main/java/io/github/sds100/keymapper/system/BuildUtils.kt @@ -1,7 +1,22 @@ package io.github.sds100.keymapper.system import android.os.Build -import android.os.Build.VERSION_CODES.* +import android.os.Build.VERSION_CODES.JELLY_BEAN +import android.os.Build.VERSION_CODES.JELLY_BEAN_MR1 +import android.os.Build.VERSION_CODES.JELLY_BEAN_MR2 +import android.os.Build.VERSION_CODES.KITKAT +import android.os.Build.VERSION_CODES.LOLLIPOP +import android.os.Build.VERSION_CODES.LOLLIPOP_MR1 +import android.os.Build.VERSION_CODES.M +import android.os.Build.VERSION_CODES.N +import android.os.Build.VERSION_CODES.N_MR1 +import android.os.Build.VERSION_CODES.O +import android.os.Build.VERSION_CODES.O_MR1 +import android.os.Build.VERSION_CODES.P +import android.os.Build.VERSION_CODES.Q +import android.os.Build.VERSION_CODES.R +import android.os.Build.VERSION_CODES.S +import android.os.Build.VERSION_CODES.S_V2 /** * Created by sds100 on 12/01/2019. diff --git a/app/src/main/java/io/github/sds100/keymapper/system/accessibility/AccessibilityServiceAdapter.kt b/app/src/main/java/io/github/sds100/keymapper/system/accessibility/AccessibilityServiceAdapter.kt index a6ea4ca24d..eb3b7a95b8 100644 --- a/app/src/main/java/io/github/sds100/keymapper/system/accessibility/AccessibilityServiceAdapter.kt +++ b/app/src/main/java/io/github/sds100/keymapper/system/accessibility/AccessibilityServiceAdapter.kt @@ -15,10 +15,19 @@ import io.github.sds100.keymapper.system.JobSchedulerHelper import io.github.sds100.keymapper.system.SettingsUtils import io.github.sds100.keymapper.system.permissions.Permission import io.github.sds100.keymapper.system.permissions.PermissionAdapter -import io.github.sds100.keymapper.util.* +import io.github.sds100.keymapper.util.Error +import io.github.sds100.keymapper.util.Event +import io.github.sds100.keymapper.util.Result +import io.github.sds100.keymapper.util.Success +import io.github.sds100.keymapper.util.onFailure +import io.github.sds100.keymapper.util.onSuccess import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.delay -import kotlinx.coroutines.flow.* +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch import kotlinx.coroutines.withTimeoutOrNull import timber.log.Timber diff --git a/app/src/main/java/io/github/sds100/keymapper/system/accessibility/AccessibilityServiceController.kt b/app/src/main/java/io/github/sds100/keymapper/system/accessibility/AccessibilityServiceController.kt index e651cf6c44..33a092e867 100644 --- a/app/src/main/java/io/github/sds100/keymapper/system/accessibility/AccessibilityServiceController.kt +++ b/app/src/main/java/io/github/sds100/keymapper/system/accessibility/AccessibilityServiceController.kt @@ -27,8 +27,25 @@ import io.github.sds100.keymapper.system.inputmethod.InputMethodAdapter import io.github.sds100.keymapper.system.root.SuAdapter import io.github.sds100.keymapper.util.Event import io.github.sds100.keymapper.util.firstBlocking -import kotlinx.coroutines.* -import kotlinx.coroutines.flow.* +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharedFlow +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.drop +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.merge +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.isActive +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import splitties.bitflags.hasFlag import splitties.bitflags.minusFlag import splitties.bitflags.withFlag diff --git a/app/src/main/java/io/github/sds100/keymapper/system/accessibility/IAccessibilityService.kt b/app/src/main/java/io/github/sds100/keymapper/system/accessibility/IAccessibilityService.kt index c9799b5d34..37f6566dbc 100644 --- a/app/src/main/java/io/github/sds100/keymapper/system/accessibility/IAccessibilityService.kt +++ b/app/src/main/java/io/github/sds100/keymapper/system/accessibility/IAccessibilityService.kt @@ -2,6 +2,7 @@ package io.github.sds100.keymapper.system.accessibility import android.os.Build import androidx.annotation.RequiresApi +import io.github.sds100.keymapper.actions.pinchscreen.PinchScreenType import io.github.sds100.keymapper.util.InputEventType import io.github.sds100.keymapper.util.Result import kotlinx.coroutines.flow.Flow @@ -13,14 +14,33 @@ interface IAccessibilityService { fun doGlobalAction(action: Int): Result<*> fun tapScreen(x: Int, y: Int, inputEventType: InputEventType): Result<*> - fun swipeScreen(xStart: Int, yStart: Int, xEnd: Int, yEnd: Int, fingerCount: Int, duration: Int, inputEventType: InputEventType): Result<*> + + fun swipeScreen( + xStart: Int, + yStart: Int, + xEnd: Int, + yEnd: Int, + fingerCount: Int, + duration: Int, + inputEventType: InputEventType + ): Result<*> + + fun pinchScreen( + x: Int, + y: Int, + distance: Int, + pinchType: PinchScreenType, + fingerCount: Int, + duration: Int, + inputEventType: InputEventType + ): Result<*> val isFingerprintGestureDetectionAvailable: Boolean var serviceFlags: Int? var serviceFeedbackType: Int? var serviceEventTypes: Int? - + fun performActionOnNode( findNode: (node: AccessibilityNodeModel) -> Boolean, performAction: (node: AccessibilityNodeModel) -> AccessibilityNodeAction? diff --git a/app/src/main/java/io/github/sds100/keymapper/system/accessibility/MyAccessibilityService.kt b/app/src/main/java/io/github/sds100/keymapper/system/accessibility/MyAccessibilityService.kt index 78df3b5392..7522c9b2fc 100644 --- a/app/src/main/java/io/github/sds100/keymapper/system/accessibility/MyAccessibilityService.kt +++ b/app/src/main/java/io/github/sds100/keymapper/system/accessibility/MyAccessibilityService.kt @@ -6,7 +6,12 @@ import android.accessibilityservice.GestureDescription import android.accessibilityservice.GestureDescription.StrokeDescription import android.app.ActivityManager import android.app.Service -import android.content.* +import android.content.BroadcastReceiver +import android.content.ComponentName +import android.content.Context +import android.content.Intent +import android.content.IntentFilter +import android.content.ServiceConnection import android.graphics.Path import android.graphics.Point import android.os.Build @@ -18,13 +23,19 @@ import androidx.core.os.bundleOf import androidx.lifecycle.Lifecycle import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.LifecycleRegistry +import io.github.sds100.keymapper.actions.pinchscreen.PinchScreenType import io.github.sds100.keymapper.api.Api import io.github.sds100.keymapper.api.IKeyEventReceiver import io.github.sds100.keymapper.api.IKeyEventReceiverCallback import io.github.sds100.keymapper.api.KeyEventReceiver import io.github.sds100.keymapper.mappings.fingerprintmaps.FingerprintMapId import io.github.sds100.keymapper.system.devices.InputDeviceUtils -import io.github.sds100.keymapper.util.* +import io.github.sds100.keymapper.util.Error +import io.github.sds100.keymapper.util.Inject +import io.github.sds100.keymapper.util.InputEventType +import io.github.sds100.keymapper.util.MathUtils +import io.github.sds100.keymapper.util.Result +import io.github.sds100.keymapper.util.Success import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import timber.log.Timber @@ -36,6 +47,9 @@ import timber.log.Timber class MyAccessibilityService : AccessibilityService(), LifecycleOwner, IAccessibilityService { + // virtual distance between fingers on multitouch gestures + private val fingerGestureDistance = 10L + /** * Broadcast receiver for all intents sent from within the app. */ @@ -56,7 +70,7 @@ class MyAccessibilityService : AccessibilityService(), LifecycleOwner, IAccessib private lateinit var lifecycleRegistry: LifecycleRegistry private var fingerprintGestureCallback: - FingerprintGestureController.FingerprintGestureCallback? = null + FingerprintGestureController.FingerprintGestureCallback? = null override val rootNode: AccessibilityNodeModel? get() { @@ -284,12 +298,12 @@ class MyAccessibilityService : AccessibilityService(), LifecycleOwner, IAccessib if (controller != null) { return controller!!.onKeyEvent( - event.keyCode, - event.action, - device, - event.metaState, - event.scanCode, - event.eventTime + event.keyCode, + event.action, + device, + event.metaState, + event.scanCode, + event.eventTime ) } @@ -318,8 +332,8 @@ class MyAccessibilityService : AccessibilityService(), LifecycleOwner, IAccessib } override fun performActionOnNode( - findNode: (node: AccessibilityNodeModel) -> Boolean, - performAction: (node: AccessibilityNodeModel) -> AccessibilityNodeAction? + findNode: (node: AccessibilityNodeModel) -> Boolean, + performAction: (node: AccessibilityNodeModel) -> AccessibilityNodeAction? ): Result<*> { val node = rootInActiveWindow.findNodeRecursively { findNode(it.toModel()) @@ -357,25 +371,25 @@ class MyAccessibilityService : AccessibilityService(), LifecycleOwner, IAccessib } val strokeDescription = - when { - inputEventType == InputEventType.DOWN && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O -> - GestureDescription.StrokeDescription( - path, - 0, - duration, - true - ) - - inputEventType == InputEventType.UP && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O -> - GestureDescription.StrokeDescription( - path, - 59999, - duration, - false - ) - - else -> GestureDescription.StrokeDescription(path, 0, duration) - } + when { + inputEventType == InputEventType.DOWN && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O -> + StrokeDescription( + path, + 0, + duration, + true + ) + + inputEventType == InputEventType.UP && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O -> + StrokeDescription( + path, + 59999, + duration, + false + ) + + else -> StrokeDescription(path, 0, duration) + } strokeDescription.let { val gestureDescription = GestureDescription.Builder().apply { @@ -395,10 +409,23 @@ class MyAccessibilityService : AccessibilityService(), LifecycleOwner, IAccessib return Error.SdkVersionTooLow(Build.VERSION_CODES.N) } - override fun swipeScreen(xStart: Int, yStart: Int, xEnd: Int, yEnd: Int, fingerCount: Int, duration: Int, inputEventType: InputEventType): Result<*> { - Timber.d("ACCESSIBILITY SWIPE SCREEN %d, %d, %d, %d, %s, %d, %s", xStart, yStart, xEnd, yEnd, fingerCount, duration, inputEventType); - + override fun swipeScreen( + xStart: Int, + yStart: Int, + xEnd: Int, + yEnd: Int, + fingerCount: Int, + duration: Int, + inputEventType: InputEventType + ): Result<*> { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + if (fingerCount >= GestureDescription.getMaxStrokeCount()) { + return Error.GestureStrokeCountTooHigh + } + if (duration >= GestureDescription.getMaxGestureDuration()) { + return Error.GestureDurationTooHigh + } + val pStart = Point(xStart, yStart) val pEnd = Point(xEnd, yEnd) @@ -410,56 +437,102 @@ class MyAccessibilityService : AccessibilityService(), LifecycleOwner, IAccessib p.lineTo(pEnd.x.toFloat(), pEnd.y.toFloat()) gestureBuilder.addStroke(StrokeDescription(p, 0, duration.toLong())) } else { - // virtual distance between the fingers - val fingerDistance = 10L // segments between fingers val segmentCount = fingerCount - 1 // the line of the perpendicular line which will be created to place the virtual fingers on it - val perpendicularLineLength = (fingerDistance * fingerCount).toInt() + val perpendicularLineLength = (fingerGestureDistance * fingerCount).toInt() + // the length of each segment between fingers val segmentLength = perpendicularLineLength / segmentCount // perpendicular line of the start swipe point - val perpendicularLineStart = getPerpendicularOfLine(pStart, pEnd, + val perpendicularLineStart = MathUtils.getPerpendicularOfLine( + pStart, pEnd, perpendicularLineLength - ); + ) // perpendicular line of the end swipe point - val perpendicularLineEnd = getPerpendicularOfLine(pEnd, pStart, - perpendicularLineLength, true); - + val perpendicularLineEnd = MathUtils.getPerpendicularOfLine( + pEnd, pStart, + perpendicularLineLength, true + ) - val startFingerCoordinatesList = mutableListOf() - val endFingerCoordinatesList = mutableListOf() // this is the angle between start and end point to rotate all virtual fingers on the perpendicular lines in the same direction - val angle = angleBetweenPoints(Point(xStart, yStart), Point(xEnd, yEnd)) - 90; + val angle = MathUtils.angleBetweenPoints(Point(xStart, yStart), Point(xEnd, yEnd)) - 90 // create the virtual fingers for (index in 0..segmentCount) { // offset of each finger - val fingerOffsetLength = index * segmentLength * 2; + val fingerOffsetLength = index * segmentLength * 2 // move the coordinates of the current virtual finger on the perpendicular line for the start coordinates - val startFingerCoordinateWithOffset = movePointByDistanceAndAngle(perpendicularLineStart.start, fingerOffsetLength, angle) + val startFingerCoordinateWithOffset = + MathUtils.movePointByDistanceAndAngle(perpendicularLineStart.start, fingerOffsetLength, angle) // move the coordinates of the current virtual finger on the perpendicular line for the end coordinates - val endFingerCoordinateWithOffset = movePointByDistanceAndAngle(perpendicularLineEnd.start, fingerOffsetLength, angle) + val endFingerCoordinateWithOffset = + MathUtils.movePointByDistanceAndAngle(perpendicularLineEnd.start, fingerOffsetLength, angle) // create a path for each finger, move the the coordinates on the perpendicular line and draw it to the end coordinates of the perpendicular line of the end swipe point val p = Path() p.moveTo(startFingerCoordinateWithOffset.x.toFloat(), startFingerCoordinateWithOffset.y.toFloat()) p.lineTo(endFingerCoordinateWithOffset.x.toFloat(), endFingerCoordinateWithOffset.y.toFloat()) - //startFingerCoordinatesList.add(startFingerCoordinateWithOffset) - //endFingerCoordinatesList.add(endFingerCoordinateWithOffset) gestureBuilder.addStroke(StrokeDescription(p, 0, duration.toLong())) } } - val success = dispatchGesture(gestureBuilder.build(), null, null); + val success = dispatchGesture(gestureBuilder.build(), null, null) + + return if (success) { + Success(Unit) + } else { + Error.FailedToDispatchGesture + } + } + + return Error.SdkVersionTooLow(Build.VERSION_CODES.N) + } + + override fun pinchScreen( + x: Int, + y: Int, + distance: Int, + pinchType: PinchScreenType, + fingerCount: Int, + duration: Int, + inputEventType: InputEventType + ): Result<*> { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + if (fingerCount >= GestureDescription.getMaxStrokeCount()) { + return Error.GestureStrokeCountTooHigh + } + if (duration >= GestureDescription.getMaxGestureDuration()) { + return Error.GestureDurationTooHigh + } + + val gestureBuilder = GestureDescription.Builder() + val distributedPoints: List = + MathUtils.distributePointsOnCircle(Point(x, y), distance.toFloat() / 2, fingerCount) + + for (index in distributedPoints.indices) { + val p = Path() + if (pinchType == PinchScreenType.PINCH_IN) { + p.moveTo(x.toFloat(), y.toFloat()) + p.lineTo(distributedPoints[index].x.toFloat(), distributedPoints[index].y.toFloat()) + } else { + p.moveTo(distributedPoints[index].x.toFloat(), distributedPoints[index].y.toFloat()) + p.lineTo(x.toFloat(), y.toFloat()) + } + + gestureBuilder.addStroke(StrokeDescription(p, 0, duration.toLong())) + } + + val success = dispatchGesture(gestureBuilder.build(), null, null) return if (success) { Success(Unit) } else { Error.FailedToDispatchGesture } + } return Error.SdkVersionTooLow(Build.VERSION_CODES.N) diff --git a/app/src/main/java/io/github/sds100/keymapper/system/apps/AndroidAppShortcutAdapter.kt b/app/src/main/java/io/github/sds100/keymapper/system/apps/AndroidAppShortcutAdapter.kt index 42db77b015..7acfa460d9 100644 --- a/app/src/main/java/io/github/sds100/keymapper/system/apps/AndroidAppShortcutAdapter.kt +++ b/app/src/main/java/io/github/sds100/keymapper/system/apps/AndroidAppShortcutAdapter.kt @@ -6,17 +6,20 @@ import android.content.Context import android.content.Intent import android.content.pm.PackageManager import android.graphics.drawable.Drawable -import android.os.Build import android.os.Bundle import androidx.core.content.pm.ShortcutInfoCompat import androidx.core.content.pm.ShortcutManagerCompat import androidx.core.graphics.drawable.IconCompat import androidx.core.graphics.drawable.toBitmap import io.github.sds100.keymapper.api.LaunchKeyMapShortcutActivity -import io.github.sds100.keymapper.util.* +import io.github.sds100.keymapper.util.Error +import io.github.sds100.keymapper.util.Result +import io.github.sds100.keymapper.util.State +import io.github.sds100.keymapper.util.Success +import io.github.sds100.keymapper.util.success import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flow -import java.util.* +import java.util.UUID /** * Created by sds100 on 20/03/2021. @@ -109,7 +112,7 @@ class AndroidAppShortcutAdapter(context: Context) : AppShortcutAdapter { try { val pendingIntent = - PendingIntent.getActivity(ctx, 0, intent, PendingIntent.FLAG_IMMUTABLE) + PendingIntent.getActivity(ctx, 0, intent, PendingIntent.FLAG_IMMUTABLE) pendingIntent.send() return Success(Unit) diff --git a/app/src/main/java/io/github/sds100/keymapper/system/apps/AndroidPackageManagerAdapter.kt b/app/src/main/java/io/github/sds100/keymapper/system/apps/AndroidPackageManagerAdapter.kt index 23bf4bbfa9..7cd3a7f15b 100644 --- a/app/src/main/java/io/github/sds100/keymapper/system/apps/AndroidPackageManagerAdapter.kt +++ b/app/src/main/java/io/github/sds100/keymapper/system/apps/AndroidPackageManagerAdapter.kt @@ -145,6 +145,7 @@ class AndroidPackageManagerAdapter( return Success(appPackage.isEnabled) } } + State.Loading -> return try { Success(packageManager.getApplicationInfo(packageName, 0).enabled) } catch (e: PackageManager.NameNotFoundException) { @@ -164,6 +165,7 @@ class AndroidPackageManagerAdapter( return appPackage != null } + State.Loading -> return try { packageManager.getApplicationInfo(packageName, 0) true diff --git a/app/src/main/java/io/github/sds100/keymapper/system/apps/AppShortcutAdapter.kt b/app/src/main/java/io/github/sds100/keymapper/system/apps/AppShortcutAdapter.kt index b8e4896a43..79d656c081 100644 --- a/app/src/main/java/io/github/sds100/keymapper/system/apps/AppShortcutAdapter.kt +++ b/app/src/main/java/io/github/sds100/keymapper/system/apps/AppShortcutAdapter.kt @@ -4,8 +4,8 @@ import android.content.Intent import android.graphics.drawable.Drawable import android.os.Bundle import androidx.core.content.pm.ShortcutInfoCompat -import io.github.sds100.keymapper.util.State import io.github.sds100.keymapper.util.Result +import io.github.sds100.keymapper.util.State import kotlinx.coroutines.flow.Flow /** @@ -24,7 +24,7 @@ interface AppShortcutAdapter { ): ShortcutInfoCompat fun pinShortcut(shortcut: ShortcutInfoCompat): Result<*> - fun createShortcutResultIntent(shortcut: ShortcutInfoCompat):Intent + fun createShortcutResultIntent(shortcut: ShortcutInfoCompat): Intent fun getShortcutName(info: AppShortcutInfo): Result fun getShortcutIcon(info: AppShortcutInfo): Result diff --git a/app/src/main/java/io/github/sds100/keymapper/system/apps/ChooseAppShortcutFragment.kt b/app/src/main/java/io/github/sds100/keymapper/system/apps/ChooseAppShortcutFragment.kt index 2a0769ced6..8542d878d1 100644 --- a/app/src/main/java/io/github/sds100/keymapper/system/apps/ChooseAppShortcutFragment.kt +++ b/app/src/main/java/io/github/sds100/keymapper/system/apps/ChooseAppShortcutFragment.kt @@ -11,7 +11,9 @@ import com.airbnb.epoxy.EpoxyRecyclerView import io.github.sds100.keymapper.R import io.github.sds100.keymapper.databinding.FragmentSimpleRecyclerviewBinding import io.github.sds100.keymapper.simple -import io.github.sds100.keymapper.util.* +import io.github.sds100.keymapper.util.Inject +import io.github.sds100.keymapper.util.State +import io.github.sds100.keymapper.util.launchRepeatOnLifecycle import io.github.sds100.keymapper.util.ui.RecyclerViewUtils import io.github.sds100.keymapper.util.ui.SimpleRecyclerViewFragment import io.github.sds100.keymapper.util.ui.showPopups diff --git a/app/src/main/java/io/github/sds100/keymapper/system/apps/ChooseAppShortcutViewModel.kt b/app/src/main/java/io/github/sds100/keymapper/system/apps/ChooseAppShortcutViewModel.kt index d3fd34c9ef..907c750bf4 100644 --- a/app/src/main/java/io/github/sds100/keymapper/system/apps/ChooseAppShortcutViewModel.kt +++ b/app/src/main/java/io/github/sds100/keymapper/system/apps/ChooseAppShortcutViewModel.kt @@ -59,6 +59,7 @@ class ChooseAppShortcutViewModel internal constructor( _state.value = it } } + State.Loading -> _state.value = State.Loading } }.launchIn(viewModelScope) diff --git a/app/src/main/java/io/github/sds100/keymapper/system/apps/DisplayAppShortcutsUseCase.kt b/app/src/main/java/io/github/sds100/keymapper/system/apps/DisplayAppShortcutsUseCase.kt index f85d51e98b..9ed8e198a7 100644 --- a/app/src/main/java/io/github/sds100/keymapper/system/apps/DisplayAppShortcutsUseCase.kt +++ b/app/src/main/java/io/github/sds100/keymapper/system/apps/DisplayAppShortcutsUseCase.kt @@ -1,8 +1,8 @@ package io.github.sds100.keymapper.system.apps import android.graphics.drawable.Drawable -import io.github.sds100.keymapper.util.State import io.github.sds100.keymapper.util.Result +import io.github.sds100.keymapper.util.State import kotlinx.coroutines.flow.Flow /** diff --git a/app/src/main/java/io/github/sds100/keymapper/system/apps/PackageUtils.kt b/app/src/main/java/io/github/sds100/keymapper/system/apps/PackageUtils.kt index cf5de713bd..6669d01e36 100644 --- a/app/src/main/java/io/github/sds100/keymapper/system/apps/PackageUtils.kt +++ b/app/src/main/java/io/github/sds100/keymapper/system/apps/PackageUtils.kt @@ -1,9 +1,6 @@ package io.github.sds100.keymapper.system.apps -import android.content.ActivityNotFoundException import android.content.Context -import android.content.Intent -import android.net.Uri /** * Created by sds100 on 27/10/2018. diff --git a/app/src/main/java/io/github/sds100/keymapper/system/bluetooth/BluetoothBroadcastReceiver.kt b/app/src/main/java/io/github/sds100/keymapper/system/bluetooth/BluetoothBroadcastReceiver.kt index 118c971ccd..e314bb9ecd 100644 --- a/app/src/main/java/io/github/sds100/keymapper/system/bluetooth/BluetoothBroadcastReceiver.kt +++ b/app/src/main/java/io/github/sds100/keymapper/system/bluetooth/BluetoothBroadcastReceiver.kt @@ -1,12 +1,10 @@ package io.github.sds100.keymapper.system.bluetooth -import android.bluetooth.BluetoothAdapter import android.bluetooth.BluetoothDevice import android.content.BroadcastReceiver import android.content.Context import android.content.Intent import io.github.sds100.keymapper.KeyMapperApp -import timber.log.Timber /** * Created by sds100 on 28/12/2018. diff --git a/app/src/main/java/io/github/sds100/keymapper/system/bluetooth/ChooseBluetoothDeviceFragment.kt b/app/src/main/java/io/github/sds100/keymapper/system/bluetooth/ChooseBluetoothDeviceFragment.kt index 20dddd60f9..8f1c0cf75a 100644 --- a/app/src/main/java/io/github/sds100/keymapper/system/bluetooth/ChooseBluetoothDeviceFragment.kt +++ b/app/src/main/java/io/github/sds100/keymapper/system/bluetooth/ChooseBluetoothDeviceFragment.kt @@ -10,7 +10,11 @@ import io.github.sds100.keymapper.simple import io.github.sds100.keymapper.util.Inject import io.github.sds100.keymapper.util.State import io.github.sds100.keymapper.util.launchRepeatOnLifecycle -import io.github.sds100.keymapper.util.ui.* +import io.github.sds100.keymapper.util.ui.ListItem +import io.github.sds100.keymapper.util.ui.RecyclerViewUtils +import io.github.sds100.keymapper.util.ui.SimpleListItem +import io.github.sds100.keymapper.util.ui.SimpleRecyclerViewFragment +import io.github.sds100.keymapper.util.ui.TextListItem import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.collectLatest diff --git a/app/src/main/java/io/github/sds100/keymapper/system/camera/AndroidCameraAdapter.kt b/app/src/main/java/io/github/sds100/keymapper/system/camera/AndroidCameraAdapter.kt index 570a391b3e..ad2e672ebe 100644 --- a/app/src/main/java/io/github/sds100/keymapper/system/camera/AndroidCameraAdapter.kt +++ b/app/src/main/java/io/github/sds100/keymapper/system/camera/AndroidCameraAdapter.kt @@ -37,6 +37,7 @@ class AndroidCameraAdapter(context: Context) : CameraAdapter { when (lensFacing) { CameraCharacteristics.LENS_FACING_FRONT -> isFlashEnabledMap[CameraLens.FRONT] = enabled + CameraCharacteristics.LENS_FACING_BACK -> isFlashEnabledMap[CameraLens.BACK] = enabled } diff --git a/app/src/main/java/io/github/sds100/keymapper/system/camera/CameraLensUtils.kt b/app/src/main/java/io/github/sds100/keymapper/system/camera/CameraLensUtils.kt index d733b911e0..47911ed216 100644 --- a/app/src/main/java/io/github/sds100/keymapper/system/camera/CameraLensUtils.kt +++ b/app/src/main/java/io/github/sds100/keymapper/system/camera/CameraLensUtils.kt @@ -1,7 +1,6 @@ package io.github.sds100.keymapper.system.camera import io.github.sds100.keymapper.R -import io.github.sds100.keymapper.system.camera.CameraLens /** * Created by sds100 on 23/03/2021. diff --git a/app/src/main/java/io/github/sds100/keymapper/system/clipboard/AndroidClipboardAdapter.kt b/app/src/main/java/io/github/sds100/keymapper/system/clipboard/AndroidClipboardAdapter.kt index 0fda2a9f80..307b34ccbb 100644 --- a/app/src/main/java/io/github/sds100/keymapper/system/clipboard/AndroidClipboardAdapter.kt +++ b/app/src/main/java/io/github/sds100/keymapper/system/clipboard/AndroidClipboardAdapter.kt @@ -4,8 +4,6 @@ import android.content.ClipData import android.content.ClipboardManager import android.content.Context import androidx.core.content.getSystemService -import io.github.sds100.keymapper.R -import io.github.sds100.keymapper.util.str /** * Created by sds100 on 14/05/2021. diff --git a/app/src/main/java/io/github/sds100/keymapper/system/devices/AndroidDevicesAdapter.kt b/app/src/main/java/io/github/sds100/keymapper/system/devices/AndroidDevicesAdapter.kt index 1f1ea78a47..b8637b2638 100644 --- a/app/src/main/java/io/github/sds100/keymapper/system/devices/AndroidDevicesAdapter.kt +++ b/app/src/main/java/io/github/sds100/keymapper/system/devices/AndroidDevicesAdapter.kt @@ -10,9 +10,18 @@ import androidx.core.content.getSystemService import io.github.sds100.keymapper.system.bluetooth.BluetoothDeviceInfo import io.github.sds100.keymapper.system.permissions.Permission import io.github.sds100.keymapper.system.permissions.PermissionAdapter -import io.github.sds100.keymapper.util.* +import io.github.sds100.keymapper.util.Error +import io.github.sds100.keymapper.util.Result +import io.github.sds100.keymapper.util.State +import io.github.sds100.keymapper.util.Success +import io.github.sds100.keymapper.util.ifIsData import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.flow.* +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.collectLatest +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.merge +import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch import splitties.mainthread.mainLooper diff --git a/app/src/main/java/io/github/sds100/keymapper/system/devices/InputDeviceInfo.kt b/app/src/main/java/io/github/sds100/keymapper/system/devices/InputDeviceInfo.kt index bfa578b35c..c484289ecf 100644 --- a/app/src/main/java/io/github/sds100/keymapper/system/devices/InputDeviceInfo.kt +++ b/app/src/main/java/io/github/sds100/keymapper/system/devices/InputDeviceInfo.kt @@ -10,8 +10,10 @@ import kotlinx.serialization.Serializable @Parcelize @Serializable -data class InputDeviceInfo(val descriptor: String, - val name: String, - val id: Int, - val isExternal: Boolean, - val isGameController: Boolean) : Parcelable \ No newline at end of file +data class InputDeviceInfo( + val descriptor: String, + val name: String, + val id: Int, + val isExternal: Boolean, + val isGameController: Boolean +) : Parcelable \ No newline at end of file diff --git a/app/src/main/java/io/github/sds100/keymapper/system/display/DisplayAdapter.kt b/app/src/main/java/io/github/sds100/keymapper/system/display/DisplayAdapter.kt index 4a67247099..024199edf4 100644 --- a/app/src/main/java/io/github/sds100/keymapper/system/display/DisplayAdapter.kt +++ b/app/src/main/java/io/github/sds100/keymapper/system/display/DisplayAdapter.kt @@ -16,8 +16,8 @@ interface DisplayAdapter { fun setOrientation(orientation: Orientation): Result<*> fun isAutoBrightnessEnabled(): Boolean - fun increaseBrightness():Result<*> - fun decreaseBrightness():Result<*> - fun enableAutoBrightness():Result<*> - fun disableAutoBrightness():Result<*> + fun increaseBrightness(): Result<*> + fun decreaseBrightness(): Result<*> + fun enableAutoBrightness(): Result<*> + fun disableAutoBrightness(): Result<*> } \ No newline at end of file diff --git a/app/src/main/java/io/github/sds100/keymapper/system/display/OrientationUtils.kt b/app/src/main/java/io/github/sds100/keymapper/system/display/OrientationUtils.kt index 2119cbbe79..0e90bb4641 100644 --- a/app/src/main/java/io/github/sds100/keymapper/system/display/OrientationUtils.kt +++ b/app/src/main/java/io/github/sds100/keymapper/system/display/OrientationUtils.kt @@ -1,7 +1,6 @@ package io.github.sds100.keymapper.system.display import io.github.sds100.keymapper.R -import io.github.sds100.keymapper.system.display.Orientation /** * Created by sds100 on 23/03/2021. diff --git a/app/src/main/java/io/github/sds100/keymapper/system/files/AndroidFileAdapter.kt b/app/src/main/java/io/github/sds100/keymapper/system/files/AndroidFileAdapter.kt index 9745bafbba..01185b41ac 100644 --- a/app/src/main/java/io/github/sds100/keymapper/system/files/AndroidFileAdapter.kt +++ b/app/src/main/java/io/github/sds100/keymapper/system/files/AndroidFileAdapter.kt @@ -11,7 +11,7 @@ import kotlinx.coroutines.withContext import net.lingala.zip4j.ZipFile import java.io.File import java.io.InputStream -import java.util.* +import java.util.UUID /** * Created by sds100 on 13/04/2021. diff --git a/app/src/main/java/io/github/sds100/keymapper/system/files/DocumentFileWrapper.kt b/app/src/main/java/io/github/sds100/keymapper/system/files/DocumentFileWrapper.kt index 037026b6d0..91ed6b5c3e 100644 --- a/app/src/main/java/io/github/sds100/keymapper/system/files/DocumentFileWrapper.kt +++ b/app/src/main/java/io/github/sds100/keymapper/system/files/DocumentFileWrapper.kt @@ -4,7 +4,13 @@ import android.content.Context import android.webkit.MimeTypeMap import androidx.documentfile.provider.DocumentFile import com.anggrayudi.storage.callback.FileCallback -import com.anggrayudi.storage.file.* +import com.anggrayudi.storage.file.MimeType +import com.anggrayudi.storage.file.copyFileTo +import com.anggrayudi.storage.file.getAbsolutePath +import com.anggrayudi.storage.file.isRawFile +import com.anggrayudi.storage.file.openInputStream +import com.anggrayudi.storage.file.openOutputStream +import com.anggrayudi.storage.file.recreateFile import com.anggrayudi.storage.media.FileDescription import io.github.sds100.keymapper.util.Error import io.github.sds100.keymapper.util.Result @@ -48,7 +54,7 @@ class DocumentFileWrapper( override val isFile: Boolean get() = file.isFile || toJavaFile().isFile - override fun listFiles(): List? { + override fun listFiles(): List { return file.listFiles() .toList() .map { DocumentFileWrapper(it, ctx) } diff --git a/app/src/main/java/io/github/sds100/keymapper/system/inputmethod/AndroidInputMethodAdapter.kt b/app/src/main/java/io/github/sds100/keymapper/system/inputmethod/AndroidInputMethodAdapter.kt index 4a7d7df8c8..1c5a90b3c6 100644 --- a/app/src/main/java/io/github/sds100/keymapper/system/inputmethod/AndroidInputMethodAdapter.kt +++ b/app/src/main/java/io/github/sds100/keymapper/system/inputmethod/AndroidInputMethodAdapter.kt @@ -19,9 +19,26 @@ import io.github.sds100.keymapper.system.accessibility.ServiceState import io.github.sds100.keymapper.system.permissions.Permission import io.github.sds100.keymapper.system.permissions.PermissionAdapter import io.github.sds100.keymapper.system.root.SuAdapter -import io.github.sds100.keymapper.util.* +import io.github.sds100.keymapper.util.Error +import io.github.sds100.keymapper.util.Event +import io.github.sds100.keymapper.util.Result +import io.github.sds100.keymapper.util.Success +import io.github.sds100.keymapper.util.onFailure +import io.github.sds100.keymapper.util.onSuccess +import io.github.sds100.keymapper.util.otherwise +import io.github.sds100.keymapper.util.then +import io.github.sds100.keymapper.util.valueOrNull import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.flow.* +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.channelFlow +import kotlinx.coroutines.flow.collectLatest +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch import kotlinx.coroutines.withTimeoutOrNull import timber.log.Timber diff --git a/app/src/main/java/io/github/sds100/keymapper/system/inputmethod/AutoSwitchImeController.kt b/app/src/main/java/io/github/sds100/keymapper/system/inputmethod/AutoSwitchImeController.kt index 23f5dfb4c2..1287e49210 100644 --- a/app/src/main/java/io/github/sds100/keymapper/system/inputmethod/AutoSwitchImeController.kt +++ b/app/src/main/java/io/github/sds100/keymapper/system/inputmethod/AutoSwitchImeController.kt @@ -8,7 +8,13 @@ import io.github.sds100.keymapper.mappings.PauseMappingsUseCase import io.github.sds100.keymapper.system.accessibility.ServiceAdapter import io.github.sds100.keymapper.system.devices.DevicesAdapter import io.github.sds100.keymapper.system.popup.PopupMessageAdapter -import io.github.sds100.keymapper.util.* +import io.github.sds100.keymapper.util.Event +import io.github.sds100.keymapper.util.PrefDelegate +import io.github.sds100.keymapper.util.Success +import io.github.sds100.keymapper.util.getFullMessage +import io.github.sds100.keymapper.util.onFailure +import io.github.sds100.keymapper.util.onSuccess +import io.github.sds100.keymapper.util.otherwise import io.github.sds100.keymapper.util.ui.ResourceProvider import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.launchIn @@ -103,6 +109,7 @@ class AutoSwitchImeController( chooseCompatibleIme(imePickerAllowed = false) } } + else -> Unit } }.launchIn(coroutineScope) diff --git a/app/src/main/java/io/github/sds100/keymapper/system/inputmethod/KeyMapperImeHelper.kt b/app/src/main/java/io/github/sds100/keymapper/system/inputmethod/KeyMapperImeHelper.kt index 6a794bb13d..52c14d9d64 100644 --- a/app/src/main/java/io/github/sds100/keymapper/system/inputmethod/KeyMapperImeHelper.kt +++ b/app/src/main/java/io/github/sds100/keymapper/system/inputmethod/KeyMapperImeHelper.kt @@ -1,7 +1,13 @@ package io.github.sds100.keymapper.system.inputmethod import io.github.sds100.keymapper.Constants -import io.github.sds100.keymapper.util.* +import io.github.sds100.keymapper.util.Error +import io.github.sds100.keymapper.util.Result +import io.github.sds100.keymapper.util.Success +import io.github.sds100.keymapper.util.firstBlocking +import io.github.sds100.keymapper.util.onSuccess +import io.github.sds100.keymapper.util.suspendThen +import io.github.sds100.keymapper.util.then import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map diff --git a/app/src/main/java/io/github/sds100/keymapper/system/inputmethod/KeyMapperImeService.kt b/app/src/main/java/io/github/sds100/keymapper/system/inputmethod/KeyMapperImeService.kt index 54133682e4..3105c0ec04 100644 --- a/app/src/main/java/io/github/sds100/keymapper/system/inputmethod/KeyMapperImeService.kt +++ b/app/src/main/java/io/github/sds100/keymapper/system/inputmethod/KeyMapperImeService.kt @@ -1,7 +1,12 @@ package io.github.sds100.keymapper.system.inputmethod import android.app.Service -import android.content.* +import android.content.BroadcastReceiver +import android.content.ComponentName +import android.content.Context +import android.content.Intent +import android.content.IntentFilter +import android.content.ServiceConnection import android.inputmethodservice.InputMethodService import android.os.IBinder import android.view.KeyEvent @@ -16,10 +21,14 @@ class KeyMapperImeService : InputMethodService() { companion object { //DON'T CHANGE THESE!!! - private const val KEY_MAPPER_INPUT_METHOD_ACTION_INPUT_DOWN_UP = "io.github.sds100.keymapper.inputmethod.ACTION_INPUT_DOWN_UP" - private const val KEY_MAPPER_INPUT_METHOD_ACTION_INPUT_DOWN = "io.github.sds100.keymapper.inputmethod.ACTION_INPUT_DOWN" - private const val KEY_MAPPER_INPUT_METHOD_ACTION_INPUT_UP = "io.github.sds100.keymapper.inputmethod.ACTION_INPUT_UP" - private const val KEY_MAPPER_INPUT_METHOD_ACTION_TEXT = "io.github.sds100.keymapper.inputmethod.ACTION_INPUT_TEXT" + private const val KEY_MAPPER_INPUT_METHOD_ACTION_INPUT_DOWN_UP = + "io.github.sds100.keymapper.inputmethod.ACTION_INPUT_DOWN_UP" + private const val KEY_MAPPER_INPUT_METHOD_ACTION_INPUT_DOWN = + "io.github.sds100.keymapper.inputmethod.ACTION_INPUT_DOWN" + private const val KEY_MAPPER_INPUT_METHOD_ACTION_INPUT_UP = + "io.github.sds100.keymapper.inputmethod.ACTION_INPUT_UP" + private const val KEY_MAPPER_INPUT_METHOD_ACTION_TEXT = + "io.github.sds100.keymapper.inputmethod.ACTION_INPUT_TEXT" private const val KEY_MAPPER_INPUT_METHOD_EXTRA_TEXT = "io.github.sds100.keymapper.inputmethod.EXTRA_TEXT" const val KEY_MAPPER_INPUT_METHOD_EXTRA_KEY_EVENT = "io.github.sds100.keymapper.inputmethod.EXTRA_KEY_EVENT" @@ -39,7 +48,7 @@ class KeyMapperImeService : InputMethodService() { KEY_MAPPER_INPUT_METHOD_ACTION_INPUT_DOWN_UP -> { val downEvent = intent.getParcelableExtra( - KEY_MAPPER_INPUT_METHOD_EXTRA_KEY_EVENT + KEY_MAPPER_INPUT_METHOD_EXTRA_KEY_EVENT ) currentInputConnection?.sendKeyEvent(downEvent) @@ -49,7 +58,7 @@ class KeyMapperImeService : InputMethodService() { KEY_MAPPER_INPUT_METHOD_ACTION_INPUT_DOWN -> { var downEvent = intent.getParcelableExtra( - KEY_MAPPER_INPUT_METHOD_EXTRA_KEY_EVENT + KEY_MAPPER_INPUT_METHOD_EXTRA_KEY_EVENT ) downEvent = KeyEvent.changeAction(downEvent, KeyEvent.ACTION_DOWN) diff --git a/app/src/main/java/io/github/sds100/keymapper/system/inputmethod/ToggleCompatibleImeUseCase.kt b/app/src/main/java/io/github/sds100/keymapper/system/inputmethod/ToggleCompatibleImeUseCase.kt index 24088da1f8..3b2cce7643 100644 --- a/app/src/main/java/io/github/sds100/keymapper/system/inputmethod/ToggleCompatibleImeUseCase.kt +++ b/app/src/main/java/io/github/sds100/keymapper/system/inputmethod/ToggleCompatibleImeUseCase.kt @@ -16,12 +16,12 @@ class ToggleCompatibleImeUseCaseImpl( inputMethodAdapter.isUserInputRequiredToChangeIme override suspend fun toggle(): Result { - return keyMapperImeHelper.toggleCompatibleInputMethod() + return keyMapperImeHelper.toggleCompatibleInputMethod() } } interface ToggleCompatibleImeUseCase { val sufficientPermissions: Flow - suspend fun toggle(): Result + suspend fun toggle(): Result } \ No newline at end of file diff --git a/app/src/main/java/io/github/sds100/keymapper/system/intents/ConfigIntentViewModel.kt b/app/src/main/java/io/github/sds100/keymapper/system/intents/ConfigIntentViewModel.kt index 246e750a20..97bf0ce1ee 100644 --- a/app/src/main/java/io/github/sds100/keymapper/system/intents/ConfigIntentViewModel.kt +++ b/app/src/main/java/io/github/sds100/keymapper/system/intents/ConfigIntentViewModel.kt @@ -429,43 +429,43 @@ class ConfigIntentViewModel(resourceProvider: ResourceProvider) : ViewModel(), InputType.TYPE_CLASS_NUMBER or InputType.TYPE_NUMBER_FLAG_SIGNED is IntArrayExtraType -> InputType.TYPE_CLASS_NUMBER or - InputType.TYPE_NUMBER_FLAG_SIGNED or InputType.TYPE_CLASS_TEXT + InputType.TYPE_NUMBER_FLAG_SIGNED or InputType.TYPE_CLASS_TEXT is LongExtraType -> InputType.TYPE_CLASS_NUMBER or InputType.TYPE_NUMBER_FLAG_SIGNED is LongArrayExtraType -> InputType.TYPE_CLASS_NUMBER or - InputType.TYPE_NUMBER_FLAG_SIGNED or InputType.TYPE_CLASS_TEXT + InputType.TYPE_NUMBER_FLAG_SIGNED or InputType.TYPE_CLASS_TEXT is ByteExtraType -> InputType.TYPE_CLASS_NUMBER or InputType.TYPE_NUMBER_FLAG_SIGNED is ByteArrayExtraType -> InputType.TYPE_CLASS_NUMBER or - InputType.TYPE_NUMBER_FLAG_SIGNED or InputType.TYPE_CLASS_TEXT + InputType.TYPE_NUMBER_FLAG_SIGNED or InputType.TYPE_CLASS_TEXT is DoubleExtraType -> InputType.TYPE_CLASS_NUMBER or InputType.TYPE_NUMBER_FLAG_SIGNED or - InputType.TYPE_NUMBER_FLAG_DECIMAL + InputType.TYPE_NUMBER_FLAG_DECIMAL is DoubleArrayExtraType -> InputType.TYPE_CLASS_NUMBER or - InputType.TYPE_NUMBER_FLAG_DECIMAL or - InputType.TYPE_NUMBER_FLAG_SIGNED or - InputType.TYPE_CLASS_TEXT + InputType.TYPE_NUMBER_FLAG_DECIMAL or + InputType.TYPE_NUMBER_FLAG_SIGNED or + InputType.TYPE_CLASS_TEXT is FloatExtraType -> InputType.TYPE_CLASS_NUMBER or InputType.TYPE_NUMBER_FLAG_SIGNED or - InputType.TYPE_NUMBER_FLAG_DECIMAL + InputType.TYPE_NUMBER_FLAG_DECIMAL is FloatArrayExtraType -> InputType.TYPE_CLASS_NUMBER or - InputType.TYPE_NUMBER_FLAG_DECIMAL or - InputType.TYPE_NUMBER_FLAG_SIGNED or - InputType.TYPE_CLASS_TEXT + InputType.TYPE_NUMBER_FLAG_DECIMAL or + InputType.TYPE_NUMBER_FLAG_SIGNED or + InputType.TYPE_CLASS_TEXT is ShortExtraType -> InputType.TYPE_CLASS_NUMBER or InputType.TYPE_NUMBER_FLAG_SIGNED is ShortArrayExtraType -> InputType.TYPE_CLASS_NUMBER or - InputType.TYPE_NUMBER_FLAG_SIGNED or InputType.TYPE_CLASS_TEXT + InputType.TYPE_NUMBER_FLAG_SIGNED or InputType.TYPE_CLASS_TEXT else -> InputType.TYPE_CLASS_TEXT } diff --git a/app/src/main/java/io/github/sds100/keymapper/system/intents/IntentAdapter.kt b/app/src/main/java/io/github/sds100/keymapper/system/intents/IntentAdapter.kt index 49d92acd0e..eebecbac98 100644 --- a/app/src/main/java/io/github/sds100/keymapper/system/intents/IntentAdapter.kt +++ b/app/src/main/java/io/github/sds100/keymapper/system/intents/IntentAdapter.kt @@ -25,6 +25,7 @@ class IntentAdapterImpl(context: Context) : IntentAdapter { ctx.startActivity(intent) } + IntentTarget.BROADCAST_RECEIVER -> ctx.sendBroadcast(intent) IntentTarget.SERVICE -> ctx.startService(intent) } diff --git a/app/src/main/java/io/github/sds100/keymapper/system/intents/IntentExtraModel.kt b/app/src/main/java/io/github/sds100/keymapper/system/intents/IntentExtraModel.kt index 44fdb99e5b..dc913206d9 100644 --- a/app/src/main/java/io/github/sds100/keymapper/system/intents/IntentExtraModel.kt +++ b/app/src/main/java/io/github/sds100/keymapper/system/intents/IntentExtraModel.kt @@ -1,6 +1,6 @@ package io.github.sds100.keymapper.system.intents -import java.util.* +import java.util.UUID /** * Created by sds100 on 01/01/21. diff --git a/app/src/main/java/io/github/sds100/keymapper/system/intents/IntentExtraType.kt b/app/src/main/java/io/github/sds100/keymapper/system/intents/IntentExtraType.kt index c6128c9753..fe5a24985b 100644 --- a/app/src/main/java/io/github/sds100/keymapper/system/intents/IntentExtraType.kt +++ b/app/src/main/java/io/github/sds100/keymapper/system/intents/IntentExtraType.kt @@ -116,7 +116,7 @@ class StringArrayExtraType : IntentExtraType() { intent.putExtra(name, parse(value)) } - override fun parse(value: String): Array? { + override fun parse(value: String): Array { return value .trim() .split(',') diff --git a/app/src/main/java/io/github/sds100/keymapper/system/media/AndroidMediaAdapter.kt b/app/src/main/java/io/github/sds100/keymapper/system/media/AndroidMediaAdapter.kt index 898e126276..95603c0e6b 100644 --- a/app/src/main/java/io/github/sds100/keymapper/system/media/AndroidMediaAdapter.kt +++ b/app/src/main/java/io/github/sds100/keymapper/system/media/AndroidMediaAdapter.kt @@ -7,8 +7,6 @@ import android.media.MediaPlayer import android.media.session.MediaController import android.media.session.PlaybackState import android.net.Uri -import android.os.Build -import android.telecom.TelecomManager import android.view.KeyEvent import androidx.core.content.getSystemService import io.github.sds100.keymapper.system.volume.VolumeStream diff --git a/app/src/main/java/io/github/sds100/keymapper/system/navigation/OpenMenuHelper.kt b/app/src/main/java/io/github/sds100/keymapper/system/navigation/OpenMenuHelper.kt index cf4f7b2cfd..7fe8cfdc70 100644 --- a/app/src/main/java/io/github/sds100/keymapper/system/navigation/OpenMenuHelper.kt +++ b/app/src/main/java/io/github/sds100/keymapper/system/navigation/OpenMenuHelper.kt @@ -40,6 +40,7 @@ class OpenMenuHelper( return success() } + suAdapter.isGranted.firstBlocking() -> return suAdapter.execute("input keyevent ${KeyEvent.KEYCODE_MENU}\n") diff --git a/app/src/main/java/io/github/sds100/keymapper/system/nfc/AndroidNfcAdapter.kt b/app/src/main/java/io/github/sds100/keymapper/system/nfc/AndroidNfcAdapter.kt index cf76b93ae2..739ec48325 100644 --- a/app/src/main/java/io/github/sds100/keymapper/system/nfc/AndroidNfcAdapter.kt +++ b/app/src/main/java/io/github/sds100/keymapper/system/nfc/AndroidNfcAdapter.kt @@ -9,8 +9,10 @@ import io.github.sds100.keymapper.util.Result /** * Created by sds100 on 24/04/2021. */ -class AndroidNfcAdapter(context: Context, -private val suAdapter: SuAdapter) : NfcAdapter { +class AndroidNfcAdapter( + context: Context, + private val suAdapter: SuAdapter +) : NfcAdapter { private val ctx = context.applicationContext private val nfcManager: NfcManager by lazy { ctx.getSystemService()!! } diff --git a/app/src/main/java/io/github/sds100/keymapper/system/notifications/NotificationController.kt b/app/src/main/java/io/github/sds100/keymapper/system/notifications/NotificationController.kt index 676f2aacd2..002f7cc82a 100644 --- a/app/src/main/java/io/github/sds100/keymapper/system/notifications/NotificationController.kt +++ b/app/src/main/java/io/github/sds100/keymapper/system/notifications/NotificationController.kt @@ -209,10 +209,12 @@ class NotificationController( }.onFailure { _showToast.emit(it.getFullMessage(this)) } + ACTION_FINGERPRINT_GESTURE_FEATURE -> { onboardingUseCase.approvedFingerprintFeaturePrompt = true _openApp.emit(null) } + ACTION_ON_SETUP_CHOSEN_DEVICES_AGAIN -> { onboardingUseCase.approvedSetupChosenDevicesAgainNotification() _openApp.emit(null) diff --git a/app/src/main/java/io/github/sds100/keymapper/system/permissions/AndroidPermissionAdapter.kt b/app/src/main/java/io/github/sds100/keymapper/system/permissions/AndroidPermissionAdapter.kt index 07d504c0cb..c5beea076c 100644 --- a/app/src/main/java/io/github/sds100/keymapper/system/permissions/AndroidPermissionAdapter.kt +++ b/app/src/main/java/io/github/sds100/keymapper/system/permissions/AndroidPermissionAdapter.kt @@ -20,9 +20,20 @@ import io.github.sds100.keymapper.shizuku.ShizukuUtils import io.github.sds100.keymapper.system.DeviceAdmin import io.github.sds100.keymapper.system.accessibility.ServiceAdapter import io.github.sds100.keymapper.system.root.SuAdapter -import io.github.sds100.keymapper.util.* +import io.github.sds100.keymapper.util.Error +import io.github.sds100.keymapper.util.Result +import io.github.sds100.keymapper.util.getIdentifier +import io.github.sds100.keymapper.util.onFailure +import io.github.sds100.keymapper.util.onSuccess +import io.github.sds100.keymapper.util.success import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.flow.* +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.asSharedFlow +import kotlinx.coroutines.flow.callbackFlow +import kotlinx.coroutines.flow.drop +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch import org.lsposed.hiddenapibypass.HiddenApiBypass import rikka.shizuku.Shizuku diff --git a/app/src/main/java/io/github/sds100/keymapper/system/permissions/AutoGrantPermissionController.kt b/app/src/main/java/io/github/sds100/keymapper/system/permissions/AutoGrantPermissionController.kt index 971aa90628..5b0a0a9104 100644 --- a/app/src/main/java/io/github/sds100/keymapper/system/permissions/AutoGrantPermissionController.kt +++ b/app/src/main/java/io/github/sds100/keymapper/system/permissions/AutoGrantPermissionController.kt @@ -16,14 +16,16 @@ class AutoGrantPermissionController( private val coroutineScope: CoroutineScope, private val permissionAdapter: PermissionAdapter, private val popupAdapter: PopupMessageAdapter, - private val resourceProvider: ResourceProvider) { + private val resourceProvider: ResourceProvider +) { fun start() { //automatically grant WRITE_SECURE_SETTINGS if Key Mapper has root or shizuku permission combine( permissionAdapter.isGrantedFlow(Permission.ROOT), permissionAdapter.isGrantedFlow(Permission.SHIZUKU), - permissionAdapter.isGrantedFlow(Permission.WRITE_SECURE_SETTINGS)) { isRootGranted, isShizukuGranted, isWriteSecureSettingsGranted -> + permissionAdapter.isGrantedFlow(Permission.WRITE_SECURE_SETTINGS) + ) { isRootGranted, isShizukuGranted, isWriteSecureSettingsGranted -> if (!isWriteSecureSettingsGranted && (isRootGranted || isShizukuGranted)) { permissionAdapter.grant(Manifest.permission.WRITE_SECURE_SETTINGS).onSuccess { diff --git a/app/src/main/java/io/github/sds100/keymapper/system/phone/AndroidPhoneAdapter.kt b/app/src/main/java/io/github/sds100/keymapper/system/phone/AndroidPhoneAdapter.kt index 6dde8ab3ae..bfc998eff1 100644 --- a/app/src/main/java/io/github/sds100/keymapper/system/phone/AndroidPhoneAdapter.kt +++ b/app/src/main/java/io/github/sds100/keymapper/system/phone/AndroidPhoneAdapter.kt @@ -14,7 +14,6 @@ import io.github.sds100.keymapper.util.Result import io.github.sds100.keymapper.util.Success import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.MutableSharedFlow -import kotlinx.coroutines.flow.collect import kotlinx.coroutines.launch /** diff --git a/app/src/main/java/io/github/sds100/keymapper/system/root/SuAdapter.kt b/app/src/main/java/io/github/sds100/keymapper/system/root/SuAdapter.kt index 54d29c406e..457ebbcc3d 100644 --- a/app/src/main/java/io/github/sds100/keymapper/system/root/SuAdapter.kt +++ b/app/src/main/java/io/github/sds100/keymapper/system/root/SuAdapter.kt @@ -21,8 +21,8 @@ import java.io.InputStream */ class SuAdapterImpl( - coroutineScope: CoroutineScope, - private val preferenceRepository: PreferenceRepository + coroutineScope: CoroutineScope, + private val preferenceRepository: PreferenceRepository ) : SuAdapter { private var process: Process? = null diff --git a/app/src/main/java/io/github/sds100/keymapper/system/vibrator/VibratorAdapter.kt b/app/src/main/java/io/github/sds100/keymapper/system/vibrator/VibratorAdapter.kt index 3ddcdeb37a..c97b565e54 100644 --- a/app/src/main/java/io/github/sds100/keymapper/system/vibrator/VibratorAdapter.kt +++ b/app/src/main/java/io/github/sds100/keymapper/system/vibrator/VibratorAdapter.kt @@ -4,5 +4,5 @@ package io.github.sds100.keymapper.system.vibrator * Created by sds100 on 17/04/2021. */ interface VibratorAdapter { - fun vibrate(duration:Long) + fun vibrate(duration: Long) } \ No newline at end of file diff --git a/app/src/main/java/io/github/sds100/keymapper/util/CoroutineUtils.kt b/app/src/main/java/io/github/sds100/keymapper/util/CoroutineUtils.kt index f91b64c110..1c3d878c85 100644 --- a/app/src/main/java/io/github/sds100/keymapper/util/CoroutineUtils.kt +++ b/app/src/main/java/io/github/sds100/keymapper/util/CoroutineUtils.kt @@ -1,7 +1,12 @@ package io.github.sds100.keymapper.util import androidx.fragment.app.Fragment -import androidx.lifecycle.* +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.LifecycleCoroutineScope +import androidx.lifecycle.LifecycleOwner +import androidx.lifecycle.coroutineScope +import androidx.lifecycle.lifecycleScope +import androidx.lifecycle.repeatOnLifecycle import kotlinx.coroutines.CancellableContinuation import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.Flow diff --git a/app/src/main/java/io/github/sds100/keymapper/util/ErrorUtils.kt b/app/src/main/java/io/github/sds100/keymapper/util/ErrorUtils.kt index 8afc4ec288..b97784c2aa 100644 --- a/app/src/main/java/io/github/sds100/keymapper/util/ErrorUtils.kt +++ b/app/src/main/java/io/github/sds100/keymapper/util/ErrorUtils.kt @@ -12,17 +12,20 @@ import io.github.sds100.keymapper.util.ui.ResourceProvider fun Error.getFullMessage(resourceProvider: ResourceProvider) = when (this) { is Error.PermissionDenied -> Error.PermissionDenied.getMessageForPermission( - resourceProvider, - permission + resourceProvider, + permission ) + is Error.AppNotFound -> resourceProvider.getString( - R.string.error_app_isnt_installed, - packageName + R.string.error_app_isnt_installed, + packageName ) + is Error.AppDisabled -> resourceProvider.getString( - R.string.error_app_is_disabled_package_name, - this.packageName + R.string.error_app_is_disabled_package_name, + this.packageName ) + is Error.NoCompatibleImeEnabled -> resourceProvider.getString(R.string.error_key_mapper_ime_service_disabled) is Error.NoCompatibleImeChosen -> resourceProvider.getString(R.string.error_ime_must_be_chosen) is Error.SystemFeatureNotSupported -> when (this.feature) { @@ -36,19 +39,23 @@ fun Error.getFullMessage(resourceProvider: ResourceProvider) = when (this) { PackageManager.FEATURE_TELEPHONY -> resourceProvider.getString(R.string.error_system_feature_telephony_unsupported) else -> throw Exception("Don't know how to get error message for this system feature ${this.feature}") } + is Error.ExtraNotFound -> resourceProvider.getString(R.string.error_extra_not_found, extraId) is Error.SdkVersionTooLow -> resourceProvider.getString( - R.string.error_sdk_version_too_low, - BuildUtils.getSdkVersionName(minSdk) + R.string.error_sdk_version_too_low, + BuildUtils.getSdkVersionName(minSdk) ) + is Error.SdkVersionTooHigh -> resourceProvider.getString( - R.string.error_sdk_version_too_high, - BuildUtils.getSdkVersionName(maxSdk) + R.string.error_sdk_version_too_high, + BuildUtils.getSdkVersionName(maxSdk) ) + is Error.InputMethodNotFound -> resourceProvider.getString( - R.string.error_ime_not_found, - imeLabel + R.string.error_ime_not_found, + imeLabel ) + is Error.FrontFlashNotFound -> resourceProvider.getString(R.string.error_front_flash_not_found) is Error.BackFlashNotFound -> resourceProvider.getString(R.string.error_back_flash_not_found) is Error.DeviceNotFound -> resourceProvider.getString(R.string.error_device_not_found) @@ -69,8 +76,8 @@ fun Error.getFullMessage(resourceProvider: ResourceProvider) = when (this) { Error.CantShowImePickerInBackground -> resourceProvider.getString(R.string.error_cant_show_ime_picker_in_background) Error.FailedToFindAccessibilityNode -> resourceProvider.getString(R.string.error_failed_to_find_accessibility_node) is Error.FailedToPerformAccessibilityGlobalAction -> resourceProvider.getString( - R.string.error_failed_to_perform_accessibility_global_action, - action + R.string.error_failed_to_perform_accessibility_global_action, + action ) Error.FailedToDispatchGesture -> resourceProvider.getString(R.string.error_failed_to_dispatch_gesture) @@ -84,9 +91,10 @@ fun Error.getFullMessage(resourceProvider: ResourceProvider) = when (this) { Error.CameraDisconnected -> resourceProvider.getString(R.string.error_camera_disconnected) Error.MaxCamerasInUse -> resourceProvider.getString(R.string.error_max_cameras_in_use) is Error.FailedToModifySystemSetting -> resourceProvider.getString( - R.string.error_failed_to_modify_system_setting, - setting + R.string.error_failed_to_modify_system_setting, + setting ) + is Error.ImeDisabled -> resourceProvider.getString(R.string.error_ime_disabled, this.ime.label) Error.FailedToChangeIme -> resourceProvider.getString(R.string.error_failed_to_change_ime) Error.NoCameraApp -> resourceProvider.getString(R.string.error_no_camera_app) @@ -98,34 +106,41 @@ fun Error.getFullMessage(resourceProvider: ResourceProvider) = when (this) { is Error.CorruptJsonFile -> reason is Error.CannotCreateFileInTarget -> resourceProvider.getString( - R.string.error_file_access_denied, - uri + R.string.error_file_access_denied, + uri ) + Error.FileOperationCancelled -> resourceProvider.getString(R.string.error_file_operation_cancelled) is Error.NoSpaceLeftOnTarget -> resourceProvider.getString( - R.string.error_no_space_left_at_target, - uri + R.string.error_no_space_left_at_target, + uri ) + is Error.NotADirectory -> resourceProvider.getString(R.string.error_not_a_directory, uri) is Error.NotAFile -> resourceProvider.getString(R.string.error_not_a_file, uri) is Error.SourceFileNotFound -> resourceProvider.getString( - R.string.error_source_file_not_found, - uri + R.string.error_source_file_not_found, + uri ) + Error.StoragePermissionDenied -> resourceProvider.getString(R.string.error_storage_permission_denied) Error.TargetDirectoryMatchesSourceDirectory -> resourceProvider.getString(R.string.error_matching_source_and_target_paths) is Error.TargetDirectoryNotFound -> resourceProvider.getString( - R.string.error_directory_not_found, - uri + R.string.error_directory_not_found, + uri ) + is Error.TargetFileNotFound -> resourceProvider.getString( - R.string.error_target_file_not_found, - uri + R.string.error_target_file_not_found, + uri ) + Error.UnknownIOError -> resourceProvider.getString(R.string.error_io_error) Error.ShizukuNotStarted -> resourceProvider.getString(R.string.error_shizuku_not_started) Error.NoFileName -> resourceProvider.getString(R.string.error_no_file_name) Error.CantDetectKeyEventsInPhoneCall -> resourceProvider.getString(R.string.trigger_error_cant_detect_in_phone_call_explanation) + Error.GestureStrokeCountTooHigh -> resourceProvider.getString(R.string.trigger_error_gesture_stroke_count_too_high) + Error.GestureDurationTooHigh -> resourceProvider.getString(R.string.trigger_error_gesture_duration_too_high) } val Error.isFixable: Boolean diff --git a/app/src/main/java/io/github/sds100/keymapper/util/FilterUtils.kt b/app/src/main/java/io/github/sds100/keymapper/util/FilterUtils.kt index 03442cfe94..ea6e7d483b 100644 --- a/app/src/main/java/io/github/sds100/keymapper/util/FilterUtils.kt +++ b/app/src/main/java/io/github/sds100/keymapper/util/FilterUtils.kt @@ -5,7 +5,7 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flow import kotlinx.coroutines.withContext -import java.util.* +import java.util.Locale /** * Created by sds100 on 22/03/2021. diff --git a/app/src/main/java/io/github/sds100/keymapper/util/FragmentInfo.kt b/app/src/main/java/io/github/sds100/keymapper/util/FragmentInfo.kt index 7e79b23035..19fbb4703b 100644 --- a/app/src/main/java/io/github/sds100/keymapper/util/FragmentInfo.kt +++ b/app/src/main/java/io/github/sds100/keymapper/util/FragmentInfo.kt @@ -7,7 +7,9 @@ import androidx.fragment.app.Fragment * Created by sds100 on 17/01/21. */ -open class FragmentInfo(@StringRes val header: Int? = null, - @StringRes val supportUrl: Int? = null, - val instantiate: () -> Fragment) +open class FragmentInfo( + @StringRes val header: Int? = null, + @StringRes val supportUrl: Int? = null, + val instantiate: () -> Fragment +) diff --git a/app/src/main/java/io/github/sds100/keymapper/util/GenericFragmentPagerAdapter.kt b/app/src/main/java/io/github/sds100/keymapper/util/GenericFragmentPagerAdapter.kt index 247b2d582d..9de18313d4 100644 --- a/app/src/main/java/io/github/sds100/keymapper/util/GenericFragmentPagerAdapter.kt +++ b/app/src/main/java/io/github/sds100/keymapper/util/GenericFragmentPagerAdapter.kt @@ -7,8 +7,9 @@ import androidx.viewpager2.adapter.FragmentStateAdapter * Created by sds100 on 26/01/2020. */ -class GenericFragmentPagerAdapter(fragment: Fragment, - private val fragmentCreatorsList: List Fragment>> +class GenericFragmentPagerAdapter( + fragment: Fragment, + private val fragmentCreatorsList: List Fragment>> ) : FragmentStateAdapter(fragment) { private val itemIds = fragmentCreatorsList.map { it.first } diff --git a/app/src/main/java/io/github/sds100/keymapper/util/Inject.kt b/app/src/main/java/io/github/sds100/keymapper/util/Inject.kt index 39434975be..9635f2a8a5 100644 --- a/app/src/main/java/io/github/sds100/keymapper/util/Inject.kt +++ b/app/src/main/java/io/github/sds100/keymapper/util/Inject.kt @@ -10,6 +10,7 @@ import io.github.sds100.keymapper.actions.TestActionUseCaseImpl import io.github.sds100.keymapper.actions.keyevent.ChooseKeyCodeViewModel import io.github.sds100.keymapper.actions.keyevent.ConfigKeyEventActionViewModel import io.github.sds100.keymapper.actions.keyevent.ConfigKeyEventUseCaseImpl +import io.github.sds100.keymapper.actions.pinchscreen.PinchPickDisplayCoordinateViewModel import io.github.sds100.keymapper.actions.sound.ChooseSoundFileUseCaseImpl import io.github.sds100.keymapper.actions.sound.ChooseSoundFileViewModel import io.github.sds100.keymapper.actions.swipescreen.SwipePickDisplayCoordinateViewModel @@ -133,6 +134,12 @@ object Inject { ) } + fun pinchCoordinateActionTypeViewModel(context: Context): PinchPickDisplayCoordinateViewModel.Factory { + return PinchPickDisplayCoordinateViewModel.Factory( + ServiceLocator.resourceProvider(context) + ) + } + fun configKeyMapViewModel( ctx: Context ): ConfigKeyMapViewModel.Factory { diff --git a/app/src/main/java/io/github/sds100/keymapper/util/ListUtils.kt b/app/src/main/java/io/github/sds100/keymapper/util/ListUtils.kt index 1df537368d..cc10ade44d 100644 --- a/app/src/main/java/io/github/sds100/keymapper/util/ListUtils.kt +++ b/app/src/main/java/io/github/sds100/keymapper/util/ListUtils.kt @@ -1,6 +1,6 @@ package io.github.sds100.keymapper.util -import java.util.* +import java.util.Collections /** * Created by sds100 on 11/03/2021. diff --git a/app/src/main/java/io/github/sds100/keymapper/util/MathUtils.kt b/app/src/main/java/io/github/sds100/keymapper/util/MathUtils.kt index fa87ee6d33..7e3fe85227 100644 --- a/app/src/main/java/io/github/sds100/keymapper/util/MathUtils.kt +++ b/app/src/main/java/io/github/sds100/keymapper/util/MathUtils.kt @@ -11,44 +11,71 @@ data class Line( val end: Point ) -fun deg2rad(degrees: Double): Double { - return degrees * Math.PI / 180; -} - -fun rad2deg(radians: Double): Double { - return radians * 180 / Math.PI; -} - -fun getPerpendicularOfLine( - p1: Point, - p2: Point, - length: Int, - reverse: Boolean = false -): Line { - var px = p1.y - p2.y - var py = p2.x - p1.x - - val len = (length / hypot(px.toFloat(), py.toFloat())).toInt() - px *= len - py *= len - - val start = Point(p1.x + px, p1.y + py) - val end = Point(p1.x - px, p1.y - py) - - return if (!reverse) { - Line(start, end) - } else { - Line(end, start) +object MathUtils { + fun deg2rad(degrees: Double): Double { + return degrees * Math.PI / 180 } -} -fun movePointByDistanceAndAngle(p: Point, distance: Int, degrees: Double): Point { - val newX = (p.x + cos(deg2rad(degrees)) * distance).toInt(); - val newY = (p.y + sin(deg2rad(degrees)) * distance).toInt(); + fun rad2deg(radians: Double): Double { + return radians * 180 / Math.PI + } + + fun getPerpendicularOfLine( + p1: Point, + p2: Point, + length: Int, + reverse: Boolean = false + ): Line { + var px = p1.y - p2.y + var py = p2.x - p1.x + + val len = (length / hypot(px.toFloat(), py.toFloat())).toInt() + px *= len + py *= len + + val start = Point(p1.x + px, p1.y + py) + val end = Point(p1.x - px, p1.y - py) + + return if (!reverse) { + Line(start, end) + } else { + Line(end, start) + } + } + + fun movePointByDistanceAndAngle(p: Point, distance: Int, degrees: Double): Point { + val newX = (p.x + cos(deg2rad(degrees)) * distance).toInt() + val newY = (p.y + sin(deg2rad(degrees)) * distance).toInt() + + return Point(newX, newY) + } + + fun angleBetweenPoints(p1: Point, p2: Point): Double { + return rad2deg(atan2((p2.y - p1.y).toDouble(), (p2.x - p1.x).toDouble())) + } + + fun distributePointsOnCircle( + circleCenter: Point, + circleRadius: Float, + numPoints: Int + ): List { - return Point(newX, newY) -} + val points = arrayListOf() + var angle: Double = 0.0 + val step = (2 * Math.PI) / numPoints + + for (index in 0..numPoints) { + points.add( + Point( + (circleCenter.x + circleRadius * cos(angle)).toInt().coerceAtLeast(0), + (circleCenter.y + circleRadius * sin(angle)).toInt().coerceAtLeast(0) + ) + ) + angle += step + } + + return points + + } -fun angleBetweenPoints(p1: Point, p2: Point): Double { - return rad2deg(atan2((p2.y - p1.y).toDouble(), (p2.x - p1.x).toDouble())) -} +} \ No newline at end of file diff --git a/app/src/main/java/io/github/sds100/keymapper/util/Result.kt b/app/src/main/java/io/github/sds100/keymapper/util/Result.kt index cd55da3b9a..0d08909eee 100644 --- a/app/src/main/java/io/github/sds100/keymapper/util/Result.kt +++ b/app/src/main/java/io/github/sds100/keymapper/util/Result.kt @@ -53,6 +53,8 @@ sealed class Error : Result() { object CantShowImePickerInBackground : Error() object CantFindImeSettings : Error() + object GestureStrokeCountTooHigh : Error() + object GestureDurationTooHigh : Error() data class PermissionDenied(val permission: Permission) : Error() { companion object { diff --git a/app/src/main/java/io/github/sds100/keymapper/util/SharedPrefsDataStoreWrapper.kt b/app/src/main/java/io/github/sds100/keymapper/util/SharedPrefsDataStoreWrapper.kt index cfc2e9877b..789a7c6cd2 100644 --- a/app/src/main/java/io/github/sds100/keymapper/util/SharedPrefsDataStoreWrapper.kt +++ b/app/src/main/java/io/github/sds100/keymapper/util/SharedPrefsDataStoreWrapper.kt @@ -1,6 +1,12 @@ package io.github.sds100.keymapper.util -import androidx.datastore.preferences.core.* +import androidx.datastore.preferences.core.booleanPreferencesKey +import androidx.datastore.preferences.core.doublePreferencesKey +import androidx.datastore.preferences.core.floatPreferencesKey +import androidx.datastore.preferences.core.intPreferencesKey +import androidx.datastore.preferences.core.longPreferencesKey +import androidx.datastore.preferences.core.stringPreferencesKey +import androidx.datastore.preferences.core.stringSetPreferencesKey import androidx.preference.PreferenceDataStore import io.github.sds100.keymapper.settings.ConfigSettingsUseCase import kotlinx.coroutines.flow.first @@ -33,16 +39,22 @@ class SharedPrefsDataStoreWrapper( when (default) { is String? -> configSettingsUseCase.getPreference(stringPreferencesKey(key)).first() ?: default + is Boolean? -> configSettingsUseCase.getPreference(booleanPreferencesKey(key)) .first() ?: default + is Int? -> configSettingsUseCase.getPreference(intPreferencesKey(key)).first() ?: default + is Long? -> configSettingsUseCase.getPreference(longPreferencesKey(key)).first() ?: default + is Float? -> configSettingsUseCase.getPreference(floatPreferencesKey(key)).first() ?: default + is Double? -> configSettingsUseCase.getPreference(doublePreferencesKey(key)).first() ?: default + else -> { val type = T::class.java.name throw IllegalArgumentException("Don't know how to set a value in shared preferences for this type $type") diff --git a/app/src/main/java/io/github/sds100/keymapper/util/State.kt b/app/src/main/java/io/github/sds100/keymapper/util/State.kt index 1dff74debc..7e1ce53822 100644 --- a/app/src/main/java/io/github/sds100/keymapper/util/State.kt +++ b/app/src/main/java/io/github/sds100/keymapper/util/State.kt @@ -1,8 +1,5 @@ package io.github.sds100.keymapper.util -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.first - /** * Created by sds100 on 17/03/2021. */ diff --git a/app/src/main/java/io/github/sds100/keymapper/util/StringUtils.kt b/app/src/main/java/io/github/sds100/keymapper/util/StringUtils.kt index 35d21f2728..ed73c5e88a 100644 --- a/app/src/main/java/io/github/sds100/keymapper/util/StringUtils.kt +++ b/app/src/main/java/io/github/sds100/keymapper/util/StringUtils.kt @@ -39,6 +39,6 @@ fun String.getWordBoundaries(@IntRange(from = 0L) cursorPosition: Int): Pair Fragment) { + instantiate: () -> Fragment + ) { if (childFragmentManager.findFragmentById(container.id) == null) { childFragmentManager.beginTransaction() diff --git a/app/src/main/java/io/github/sds100/keymapper/util/ui/NavDestination.kt b/app/src/main/java/io/github/sds100/keymapper/util/ui/NavDestination.kt index 62ee45ed6e..235dd117a6 100644 --- a/app/src/main/java/io/github/sds100/keymapper/util/ui/NavDestination.kt +++ b/app/src/main/java/io/github/sds100/keymapper/util/ui/NavDestination.kt @@ -1,6 +1,7 @@ package io.github.sds100.keymapper.util.ui import io.github.sds100.keymapper.actions.ActionData +import io.github.sds100.keymapper.actions.pinchscreen.PinchPickCoordinateResult import io.github.sds100.keymapper.actions.sound.ChooseSoundFileResult import io.github.sds100.keymapper.actions.swipescreen.SwipePickCoordinateResult import io.github.sds100.keymapper.actions.tapscreen.PickCoordinateResult @@ -24,6 +25,7 @@ sealed class NavDestination { const val ID_KEY_EVENT = "key_event" const val ID_PICK_COORDINATE = "pick_coordinate" const val ID_PICK_SWIPE_COORDINATE = "pick_swipe_coordinate" + const val ID_PICK_PINCH_COORDINATE = "pick_pinch_coordinate" const val ID_CONFIG_INTENT = "config_intent" const val ID_CHOOSE_ACTIVITY = "choose_activity" const val ID_CHOOSE_SOUND = "choose_sound" @@ -46,6 +48,7 @@ sealed class NavDestination { is ConfigKeyEventAction -> ID_KEY_EVENT is PickCoordinate -> ID_PICK_COORDINATE is PickSwipeCoordinate -> ID_PICK_SWIPE_COORDINATE + is PickPinchCoordinate -> ID_PICK_PINCH_COORDINATE is ConfigIntent -> ID_CONFIG_INTENT ChooseActivity -> ID_CHOOSE_ACTIVITY ChooseSound -> ID_CHOOSE_SOUND @@ -80,6 +83,9 @@ sealed class NavDestination { data class PickSwipeCoordinate(val result: SwipePickCoordinateResult? = null) : NavDestination() + data class PickPinchCoordinate(val result: PinchPickCoordinateResult? = null) : + NavDestination() + data class ConfigIntent(val result: ConfigIntentResult? = null) : NavDestination() diff --git a/app/src/main/java/io/github/sds100/keymapper/util/ui/NavigationViewModel.kt b/app/src/main/java/io/github/sds100/keymapper/util/ui/NavigationViewModel.kt index 859f120065..410bdd5be6 100644 --- a/app/src/main/java/io/github/sds100/keymapper/util/ui/NavigationViewModel.kt +++ b/app/src/main/java/io/github/sds100/keymapper/util/ui/NavigationViewModel.kt @@ -12,6 +12,8 @@ import io.github.sds100.keymapper.actions.ActionData import io.github.sds100.keymapper.actions.ChooseActionFragment import io.github.sds100.keymapper.actions.keyevent.ChooseKeyCodeFragment import io.github.sds100.keymapper.actions.keyevent.ConfigKeyEventActionFragment +import io.github.sds100.keymapper.actions.pinchscreen.PinchPickCoordinateResult +import io.github.sds100.keymapper.actions.pinchscreen.PinchPickDisplayCoordinateFragment import io.github.sds100.keymapper.actions.sound.ChooseSoundFileFragment import io.github.sds100.keymapper.actions.sound.ChooseSoundFileResult import io.github.sds100.keymapper.actions.swipescreen.SwipePickCoordinateResult @@ -20,14 +22,26 @@ import io.github.sds100.keymapper.actions.tapscreen.PickCoordinateResult import io.github.sds100.keymapper.actions.tapscreen.PickDisplayCoordinateFragment import io.github.sds100.keymapper.constraints.ChooseConstraintFragment import io.github.sds100.keymapper.constraints.Constraint -import io.github.sds100.keymapper.system.apps.* +import io.github.sds100.keymapper.system.apps.ActivityInfo +import io.github.sds100.keymapper.system.apps.ChooseActivityFragment +import io.github.sds100.keymapper.system.apps.ChooseAppFragment +import io.github.sds100.keymapper.system.apps.ChooseAppShortcutFragment +import io.github.sds100.keymapper.system.apps.ChooseAppShortcutResult import io.github.sds100.keymapper.system.bluetooth.BluetoothDeviceInfo import io.github.sds100.keymapper.system.bluetooth.ChooseBluetoothDeviceFragment import io.github.sds100.keymapper.system.intents.ConfigIntentFragment import io.github.sds100.keymapper.system.intents.ConfigIntentResult import io.github.sds100.keymapper.ui.utils.getJsonSerializable import io.github.sds100.keymapper.util.ui.NavDestination.Companion.getId -import kotlinx.coroutines.flow.* +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.SharedFlow +import kotlinx.coroutines.flow.asSharedFlow +import kotlinx.coroutines.flow.dropWhile +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.merge +import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.runBlocking import kotlinx.serialization.decodeFromString import kotlinx.serialization.encodeToString @@ -133,7 +147,7 @@ fun NavigationViewModel.setupNavigation(fragment: Fragment) { } val direction = when (destination) { - is NavDestination.ChooseApp -> NavAppDirections.chooseApp(destination.allowHiddenApps, requestKey) + is NavDestination.ChooseApp -> NavAppDirections.chooseApp(destination.allowHiddenApps, requestKey) NavDestination.ChooseAppShortcut -> NavAppDirections.chooseAppShortcut(requestKey) NavDestination.ChooseKeyCode -> NavAppDirections.chooseKeyCode(requestKey) is NavDestination.ConfigKeyEventAction -> { @@ -143,6 +157,7 @@ fun NavigationViewModel.setupNavigation(fragment: Fragment) { NavAppDirections.configKeyEvent(requestKey, json) } + is NavDestination.PickCoordinate -> { val json = destination.result?.let { Json.encodeToString(it) @@ -150,6 +165,7 @@ fun NavigationViewModel.setupNavigation(fragment: Fragment) { NavAppDirections.pickDisplayCoordinate(requestKey, json) } + is NavDestination.PickSwipeCoordinate -> { val json = destination.result?.let { Json.encodeToString(it) @@ -157,6 +173,15 @@ fun NavigationViewModel.setupNavigation(fragment: Fragment) { NavAppDirections.swipePickDisplayCoordinate(requestKey, json) } + + is NavDestination.PickPinchCoordinate -> { + val json = destination.result?.let { + Json.encodeToString(it) + } + + NavAppDirections.pinchPickDisplayCoordinate(requestKey, json) + } + is NavDestination.ConfigIntent -> { val json = destination.result?.let { Json.encodeToString(it) @@ -164,6 +189,7 @@ fun NavigationViewModel.setupNavigation(fragment: Fragment) { NavAppDirections.configIntent(requestKey, json) } + is NavDestination.ChooseActivity -> NavAppDirections.chooseActivity(requestKey) is NavDestination.ChooseSound -> NavAppDirections.chooseSoundFile(requestKey) NavDestination.ChooseAction -> NavAppDirections.toChooseActionFragment(requestKey) @@ -171,9 +197,11 @@ fun NavigationViewModel.setupNavigation(fragment: Fragment) { supportedConstraints = Json.encodeToString(destination.supportedConstraints), requestKey = requestKey ) + is NavDestination.ChooseBluetoothDevice -> NavAppDirections.chooseBluetoothDevice( requestKey ) + NavDestination.FixAppKilling -> NavAppDirections.goToFixAppKillingActivity() NavDestination.ReportBug -> NavAppDirections.goToReportBugActivity() NavDestination.About -> NavAppDirections.actionGlobalAboutFragment() @@ -237,6 +265,13 @@ fun NavigationViewModel.sendNavResultFromBundle( onNavResult(NavResult(requestKey, result)) } + NavDestination.ID_PICK_PINCH_COORDINATE -> { + val json = bundle.getString(PinchPickDisplayCoordinateFragment.EXTRA_RESULT)!! + val result = Json.decodeFromString(json) + + onNavResult(NavResult(requestKey, result)) + } + NavDestination.ID_CONFIG_INTENT -> { val json = bundle.getString(ConfigIntentFragment.EXTRA_RESULT)!! val result = Json.decodeFromString(json) diff --git a/app/src/main/java/io/github/sds100/keymapper/util/ui/OnChipClickCallback.kt b/app/src/main/java/io/github/sds100/keymapper/util/ui/OnChipClickCallback.kt index 17dfd916c4..423f23f698 100644 --- a/app/src/main/java/io/github/sds100/keymapper/util/ui/OnChipClickCallback.kt +++ b/app/src/main/java/io/github/sds100/keymapper/util/ui/OnChipClickCallback.kt @@ -1,7 +1,5 @@ package io.github.sds100.keymapper.util.ui -import io.github.sds100.keymapper.util.ui.ChipUi - /** * Created by sds100 on 07/03/2020. */ diff --git a/app/src/main/java/io/github/sds100/keymapper/util/ui/RadioButtonPairListItem.kt b/app/src/main/java/io/github/sds100/keymapper/util/ui/RadioButtonPairListItem.kt index d747527374..d7f8d2b495 100644 --- a/app/src/main/java/io/github/sds100/keymapper/util/ui/RadioButtonPairListItem.kt +++ b/app/src/main/java/io/github/sds100/keymapper/util/ui/RadioButtonPairListItem.kt @@ -14,4 +14,4 @@ data class RadioButtonPairListItem( val rightButtonId: String, val rightButtonText: String, val rightButtonChecked: Boolean -): ListItem +) : ListItem diff --git a/app/src/main/java/io/github/sds100/keymapper/util/ui/RadioButtonTripleListItem.kt b/app/src/main/java/io/github/sds100/keymapper/util/ui/RadioButtonTripleListItem.kt index dc3fb6d288..4eb8b52ecc 100644 --- a/app/src/main/java/io/github/sds100/keymapper/util/ui/RadioButtonTripleListItem.kt +++ b/app/src/main/java/io/github/sds100/keymapper/util/ui/RadioButtonTripleListItem.kt @@ -18,4 +18,4 @@ data class RadioButtonTripleListItem( val rightButtonId: String, val rightButtonText: String, val rightButtonChecked: Boolean -): ListItem +) : ListItem diff --git a/app/src/main/java/io/github/sds100/keymapper/util/ui/ResourceExt.kt b/app/src/main/java/io/github/sds100/keymapper/util/ui/ResourceExt.kt index 5c657cd702..49580e40ef 100644 --- a/app/src/main/java/io/github/sds100/keymapper/util/ui/ResourceExt.kt +++ b/app/src/main/java/io/github/sds100/keymapper/util/ui/ResourceExt.kt @@ -6,7 +6,15 @@ import android.content.res.TypedArray import android.graphics.drawable.Drawable import android.util.AttributeSet import android.view.View -import androidx.annotation.* +import androidx.annotation.ArrayRes +import androidx.annotation.AttrRes +import androidx.annotation.BoolRes +import androidx.annotation.ColorInt +import androidx.annotation.ColorRes +import androidx.annotation.DrawableRes +import androidx.annotation.IntegerRes +import androidx.annotation.StringRes +import androidx.annotation.StyleableRes import androidx.appcompat.content.res.AppCompatResources import androidx.core.content.ContextCompat import androidx.core.content.res.getResourceIdOrThrow diff --git a/app/src/main/java/io/github/sds100/keymapper/util/ui/SliderWithLabel.kt b/app/src/main/java/io/github/sds100/keymapper/util/ui/SliderWithLabel.kt index b52a34dc8b..45b1d96cd4 100644 --- a/app/src/main/java/io/github/sds100/keymapper/util/ui/SliderWithLabel.kt +++ b/app/src/main/java/io/github/sds100/keymapper/util/ui/SliderWithLabel.kt @@ -14,9 +14,10 @@ import io.github.sds100.keymapper.util.str /** * Created by sds100 on 04/06/20. */ -class SliderWithLabel(context: Context, - attrs: AttributeSet?, - defStyleAttr: Int +class SliderWithLabel( + context: Context, + attrs: AttributeSet?, + defStyleAttr: Int ) : FrameLayout(context, attrs, defStyleAttr) { constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0) @@ -126,7 +127,7 @@ class SliderWithLabel(context: Context, private fun setSliderValueTextViewText(value: Float) { //Set text to "default" if the slider is in the "default" step position. if (isDefaultStepEnabled && value == slider.valueFrom) { - sliderValue.setText(buttonDefaultText) + sliderValue.text = buttonDefaultText } else { val text = try { value.toInt().toString() diff --git a/app/src/main/java/io/github/sds100/keymapper/util/ui/SnackBarUtils.kt b/app/src/main/java/io/github/sds100/keymapper/util/ui/SnackBarUtils.kt index 11efd338ce..af0fba38fc 100644 --- a/app/src/main/java/io/github/sds100/keymapper/util/ui/SnackBarUtils.kt +++ b/app/src/main/java/io/github/sds100/keymapper/util/ui/SnackBarUtils.kt @@ -44,7 +44,7 @@ object SnackBarUtils { } //if there is no action then there is no point waiting for a user response - if (actionText == null){ + if (actionText == null) { continuation.resume(null) } diff --git a/app/src/main/java/io/github/sds100/keymapper/util/ui/TwoFragments.kt b/app/src/main/java/io/github/sds100/keymapper/util/ui/TwoFragments.kt index 3e73efd11a..749604f942 100644 --- a/app/src/main/java/io/github/sds100/keymapper/util/ui/TwoFragments.kt +++ b/app/src/main/java/io/github/sds100/keymapper/util/ui/TwoFragments.kt @@ -13,7 +13,8 @@ import io.github.sds100.keymapper.util.FragmentInfo */ abstract class TwoFragments( private val top: FragmentInfo, - private val bottom: FragmentInfo) : Fragment() { + private val bottom: FragmentInfo +) : Fragment() { override fun onCreateView( inflater: LayoutInflater, @@ -31,7 +32,8 @@ abstract class TwoFragments( private fun addFragment( container: FragmentContainerView, - instantiateFragment: () -> Fragment) { + instantiateFragment: () -> Fragment + ) { if (childFragmentManager.findFragmentById(container.id) == null) { childFragmentManager.beginTransaction() diff --git a/app/src/main/java/io/github/sds100/keymapper/util/ui/ViewModelHelper.kt b/app/src/main/java/io/github/sds100/keymapper/util/ui/ViewModelHelper.kt index b1f4e1b61c..c707b592ec 100644 --- a/app/src/main/java/io/github/sds100/keymapper/util/ui/ViewModelHelper.kt +++ b/app/src/main/java/io/github/sds100/keymapper/util/ui/ViewModelHelper.kt @@ -12,30 +12,30 @@ import io.github.sds100.keymapper.util.isFixable */ object ViewModelHelper { suspend fun handleKeyMapperCrashedDialog( - resourceProvider: ResourceProvider, - navigationViewModel: NavigationViewModel, - popupViewModel: PopupViewModel, - restartService: () -> Boolean + resourceProvider: ResourceProvider, + navigationViewModel: NavigationViewModel, + popupViewModel: PopupViewModel, + restartService: () -> Boolean ) { val dialog = PopupUi.Dialog( - title = resourceProvider.getString(R.string.dialog_title_key_mapper_crashed), - message = resourceProvider.getText(R.string.dialog_message_key_mapper_crashed), - positiveButtonText = resourceProvider.getString(R.string.dialog_button_read_dont_kill_my_app_no), - negativeButtonText = resourceProvider.getString(R.string.neg_cancel), - neutralButtonText = resourceProvider.getString(R.string.dialog_button_read_dont_kill_my_app_yes) + title = resourceProvider.getString(R.string.dialog_title_key_mapper_crashed), + message = resourceProvider.getText(R.string.dialog_message_key_mapper_crashed), + positiveButtonText = resourceProvider.getString(R.string.dialog_button_read_dont_kill_my_app_no), + negativeButtonText = resourceProvider.getString(R.string.neg_cancel), + neutralButtonText = resourceProvider.getString(R.string.dialog_button_read_dont_kill_my_app_yes) ) val response = popupViewModel.showPopup("app_crashed_prompt", dialog) ?: return when (response) { DialogResponse.POSITIVE -> navigationViewModel.navigate( - "fix_app_killing", - NavDestination.FixAppKilling + "fix_app_killing", + NavDestination.FixAppKilling ) DialogResponse.NEUTRAL -> { val restartServiceDialog = PopupUi.Ok( - message = resourceProvider.getString(R.string.dialog_message_restart_accessibility_service) + message = resourceProvider.getString(R.string.dialog_message_restart_accessibility_service) ) popupViewModel.showPopup("restart_accessibility_service", restartServiceDialog) @@ -79,11 +79,11 @@ object ViewModelHelper { ) val response = - popupViewModel.showPopup("cant_find_accessibility_settings", dialog) ?: return + popupViewModel.showPopup("cant_find_accessibility_settings", dialog) ?: return if (response == DialogResponse.POSITIVE) { val url = - resourceProvider.getString(R.string.url_cant_find_accessibility_settings_issue) + resourceProvider.getString(R.string.url_cant_find_accessibility_settings_issue) val openUrlPopup = PopupUi.OpenUrl(url) popupViewModel.showPopup("url_cant_find_accessibility_settings_issue", openUrlPopup) @@ -132,17 +132,19 @@ object ViewModelHelper { } } - suspend fun showFixErrorDialog(resourceProvider: ResourceProvider, - popupViewModel: PopupViewModel, - error: Error, - fixError: suspend () -> Unit) { + suspend fun showFixErrorDialog( + resourceProvider: ResourceProvider, + popupViewModel: PopupViewModel, + error: Error, + fixError: suspend () -> Unit + ) { if (error.isFixable) { val dialog = PopupUi.Dialog( - title = resourceProvider.getString(R.string.dialog_title_home_fix_error), - message = error.getFullMessage(resourceProvider), - positiveButtonText = resourceProvider.getString(R.string.dialog_button_fix), - negativeButtonText = resourceProvider.getText(R.string.neg_cancel) + title = resourceProvider.getString(R.string.dialog_title_home_fix_error), + message = error.getFullMessage(resourceProvider), + positiveButtonText = resourceProvider.getString(R.string.dialog_button_fix), + negativeButtonText = resourceProvider.getText(R.string.neg_cancel) ) val response = popupViewModel.showPopup("fix_error", dialog) diff --git a/app/src/main/res/drawable/ic_outline_pinch_app_24.xml b/app/src/main/res/drawable/ic_outline_pinch_app_24.xml new file mode 100644 index 0000000000..1752dab910 --- /dev/null +++ b/app/src/main/res/drawable/ic_outline_pinch_app_24.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_outline_swipe_app_24.xml b/app/src/main/res/drawable/ic_outline_swipe_app_24.xml new file mode 100644 index 0000000000..274d5166f8 --- /dev/null +++ b/app/src/main/res/drawable/ic_outline_swipe_app_24.xml @@ -0,0 +1,6 @@ + + + + diff --git a/app/src/main/res/layout/fragment_pinch_pick_coordinates.xml b/app/src/main/res/layout/fragment_pinch_pick_coordinates.xml new file mode 100644 index 0000000000..59e2d18c05 --- /dev/null +++ b/app/src/main/res/layout/fragment_pinch_pick_coordinates.xml @@ -0,0 +1,287 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +