Skip to content

Commit 52d1d87

Browse files
committed
Merge branch 'copilot/create-notification-channel' into develop
2 parents ec764dd + c0ac7a4 commit 52d1d87

File tree

17 files changed

+586
-15
lines changed

17 files changed

+586
-15
lines changed

base/src/main/java/io/github/sds100/keymapper/base/BaseMainActivity.kt

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,10 @@ import com.anggrayudi.storage.extension.toDocumentFile
2727
import io.github.sds100.keymapper.base.compose.ComposeColors
2828
import io.github.sds100.keymapper.base.input.InputEventDetectionSource
2929
import io.github.sds100.keymapper.base.input.InputEventHubImpl
30+
import io.github.sds100.keymapper.base.keymaps.ConfigKeyMapStateImpl
3031
import io.github.sds100.keymapper.base.onboarding.OnboardingUseCase
3132
import io.github.sds100.keymapper.base.system.accessibility.AccessibilityServiceAdapterImpl
3233
import io.github.sds100.keymapper.base.system.permissions.RequestPermissionDelegate
33-
import io.github.sds100.keymapper.base.trigger.RecordTriggerControllerImpl
3434
import io.github.sds100.keymapper.base.utils.navigation.NavigationProvider
3535
import io.github.sds100.keymapper.base.utils.ui.ResourceProviderImpl
3636
import io.github.sds100.keymapper.common.BuildConfigProvider
@@ -56,9 +56,6 @@ abstract class BaseMainActivity : AppCompatActivity() {
5656
const val ACTION_SHOW_ACCESSIBILITY_SETTINGS_NOT_FOUND_DIALOG =
5757
"${BuildConfig.LIBRARY_PACKAGE_NAME}.ACTION_SHOW_ACCESSIBILITY_SETTINGS_NOT_FOUND_DIALOG"
5858

59-
const val ACTION_USE_FLOATING_BUTTONS =
60-
"${BuildConfig.LIBRARY_PACKAGE_NAME}.ACTION_USE_FLOATING_BUTTONS"
61-
6259
const val ACTION_SAVE_FILE = "${BuildConfig.LIBRARY_PACKAGE_NAME}.ACTION_SAVE_FILE"
6360
const val EXTRA_FILE_URI = "${BuildConfig.LIBRARY_PACKAGE_NAME}.EXTRA_FILE_URI"
6461

@@ -78,9 +75,6 @@ abstract class BaseMainActivity : AppCompatActivity() {
7875
@Inject
7976
lateinit var onboardingUseCase: OnboardingUseCase
8077

81-
@Inject
82-
lateinit var recordTriggerController: RecordTriggerControllerImpl
83-
8478
@Inject
8579
lateinit var notificationReceiverAdapter: NotificationReceiverAdapterImpl
8680

@@ -108,6 +102,9 @@ abstract class BaseMainActivity : AppCompatActivity() {
108102
@Inject
109103
lateinit var navigationProvider: NavigationProvider
110104

105+
@Inject
106+
lateinit var configKeyMapState: ConfigKeyMapStateImpl
107+
111108
private lateinit var requestPermissionDelegate: RequestPermissionDelegate
112109

113110
private val currentNightMode: Int
@@ -158,6 +155,8 @@ abstract class BaseMainActivity : AppCompatActivity() {
158155
)
159156
super.onCreate(savedInstanceState)
160157

158+
savedInstanceState?.let { configKeyMapState.restoreState(it) }
159+
161160
requestPermissionDelegate = RequestPermissionDelegate(
162161
this,
163162
showDialogs = true,
@@ -209,6 +208,12 @@ abstract class BaseMainActivity : AppCompatActivity() {
209208
onboardingUseCase.handledMigrateScreenOffKeyMapsNotification()
210209
}
211210

211+
override fun onSaveInstanceState(outState: Bundle) {
212+
configKeyMapState.saveState(outState)
213+
214+
super.onSaveInstanceState(outState)
215+
}
216+
212217
override fun onDestroy() {
213218
onboardingUseCase.shownAppIntro = true
214219

base/src/main/java/io/github/sds100/keymapper/base/actions/ActionData.kt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -871,6 +871,17 @@ sealed class ActionData : Comparable<ActionData> {
871871
override val id: ActionId = ActionId.DISMISS_ALL_NOTIFICATIONS
872872
}
873873

874+
@Serializable
875+
data class CreateNotification(val title: String, val text: String, val timeoutMs: Long?) :
876+
ActionData() {
877+
override val id: ActionId = ActionId.CREATE_NOTIFICATION
878+
879+
override fun compareTo(other: ActionData) = when (other) {
880+
is CreateNotification -> title.compareTo(other.title)
881+
else -> super.compareTo(other)
882+
}
883+
}
884+
874885
@Serializable
875886
data object AnswerCall : ActionData() {
876887
override val id: ActionId = ActionId.ANSWER_PHONE_CALL

base/src/main/java/io/github/sds100/keymapper/base/actions/ActionDataEntityMapper.kt

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ object ActionDataEntityMapper {
5252
ActionEntity.Type.INTERACT_UI_ELEMENT -> ActionId.INTERACT_UI_ELEMENT
5353
ActionEntity.Type.SHELL_COMMAND -> ActionId.SHELL_COMMAND
5454
ActionEntity.Type.MODIFY_SETTING -> ActionId.MODIFY_SETTING
55+
ActionEntity.Type.CREATE_NOTIFICATION -> ActionId.CREATE_NOTIFICATION
5556
}
5657

5758
return when (actionId) {
@@ -558,6 +559,25 @@ object ActionDataEntityMapper {
558559
ActionId.SHOW_POWER_MENU -> ActionData.ShowPowerMenu
559560
ActionId.DISMISS_MOST_RECENT_NOTIFICATION -> ActionData.DismissLastNotification
560561
ActionId.DISMISS_ALL_NOTIFICATIONS -> ActionData.DismissAllNotifications
562+
ActionId.CREATE_NOTIFICATION -> {
563+
val title =
564+
entity.extras.getData(ActionEntity.EXTRA_NOTIFICATION_TITLE).valueOrNull()
565+
?: return null
566+
567+
val text = entity.data.takeIf { it.isNotBlank() }
568+
?: return null
569+
570+
val timeoutMs = entity.extras.getData(
571+
ActionEntity.EXTRA_NOTIFICATION_TIMEOUT,
572+
).valueOrNull()
573+
?.toLongOrNull()
574+
575+
ActionData.CreateNotification(
576+
title = title,
577+
text = text,
578+
timeoutMs = timeoutMs,
579+
)
580+
}
561581
ActionId.ANSWER_PHONE_CALL -> ActionData.AnswerCall
562582
ActionId.END_PHONE_CALL -> ActionData.EndCall
563583
ActionId.DEVICE_CONTROLS -> ActionData.DeviceControls
@@ -772,6 +792,7 @@ object ActionDataEntityMapper {
772792
is ActionData.InteractUiElement -> ActionEntity.Type.INTERACT_UI_ELEMENT
773793
is ActionData.ShellCommand -> ActionEntity.Type.SHELL_COMMAND
774794
is ActionData.ModifySetting -> ActionEntity.Type.MODIFY_SETTING
795+
is ActionData.CreateNotification -> ActionEntity.Type.CREATE_NOTIFICATION
775796
else -> ActionEntity.Type.SYSTEM_ACTION
776797
}
777798

@@ -842,6 +863,7 @@ object ActionDataEntityMapper {
842863
data.command.toByteArray(),
843864
Base64.DEFAULT,
844865
).trim() // Trim to remove trailing newline added by Base64.DEFAULT
866+
is ActionData.CreateNotification -> data.text
845867
is ActionData.HttpRequest -> SYSTEM_ACTION_ID_MAP[data.id]!!
846868
is ActionData.ControlMediaForApp.Rewind -> SYSTEM_ACTION_ID_MAP[data.id]!!
847869
is ActionData.ControlMediaForApp.Stop -> SYSTEM_ACTION_ID_MAP[data.id]!!
@@ -1134,6 +1156,13 @@ object ActionDataEntityMapper {
11341156
EntityExtra(ActionEntity.EXTRA_SETTING_TYPE, data.settingType.name),
11351157
)
11361158

1159+
is ActionData.CreateNotification -> buildList {
1160+
add(EntityExtra(ActionEntity.EXTRA_NOTIFICATION_TITLE, data.title))
1161+
data.timeoutMs?.let {
1162+
add(EntityExtra(ActionEntity.EXTRA_NOTIFICATION_TIMEOUT, it.toString()))
1163+
}
1164+
}
1165+
11371166
else -> emptyList()
11381167
}
11391168

base/src/main/java/io/github/sds100/keymapper/base/actions/ActionId.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ enum class ActionId {
138138

139139
DISMISS_MOST_RECENT_NOTIFICATION,
140140
DISMISS_ALL_NOTIFICATIONS,
141+
CREATE_NOTIFICATION,
141142

142143
ANSWER_PHONE_CALL,
143144
END_PHONE_CALL,

base/src/main/java/io/github/sds100/keymapper/base/actions/ActionUiHelper.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -658,6 +658,13 @@ class ActionUiHelper(
658658
arrayOf(action.settingKey, action.value),
659659
)
660660
}
661+
662+
is ActionData.CreateNotification -> {
663+
getString(
664+
R.string.action_create_notification_description,
665+
action.title,
666+
)
667+
}
661668
}
662669

663670
fun getIcon(action: ActionData): ComposeIconInfo = when (action) {

base/src/main/java/io/github/sds100/keymapper/base/actions/ActionUtils.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,7 @@ object ActionUtils {
248248

249249
ActionId.DISMISS_MOST_RECENT_NOTIFICATION -> ActionCategory.NOTIFICATIONS
250250
ActionId.DISMISS_ALL_NOTIFICATIONS -> ActionCategory.NOTIFICATIONS
251+
ActionId.CREATE_NOTIFICATION -> ActionCategory.NOTIFICATIONS
251252
ActionId.DEVICE_CONTROLS -> ActionCategory.APPS
252253

253254
ActionId.INTERACT_UI_ELEMENT -> ActionCategory.APPS
@@ -374,6 +375,7 @@ object ActionUtils {
374375
ActionId.DISMISS_MOST_RECENT_NOTIFICATION ->
375376
R.string.action_dismiss_most_recent_notification
376377
ActionId.DISMISS_ALL_NOTIFICATIONS -> R.string.action_dismiss_all_notifications
378+
ActionId.CREATE_NOTIFICATION -> R.string.action_create_notification
377379
ActionId.ANSWER_PHONE_CALL -> R.string.action_answer_call
378380
ActionId.END_PHONE_CALL -> R.string.action_end_call
379381
ActionId.SEND_SMS -> R.string.action_send_sms
@@ -503,6 +505,7 @@ object ActionUtils {
503505
ActionId.SOUND -> R.drawable.ic_outline_volume_up_24
504506
ActionId.DISMISS_MOST_RECENT_NOTIFICATION -> R.drawable.ic_baseline_clear_all_24
505507
ActionId.DISMISS_ALL_NOTIFICATIONS -> R.drawable.ic_baseline_clear_all_24
508+
ActionId.CREATE_NOTIFICATION -> R.drawable.ic_notification_play
506509
ActionId.ANSWER_PHONE_CALL -> R.drawable.ic_outline_call_24
507510
ActionId.END_PHONE_CALL -> R.drawable.ic_outline_call_end_24
508511
ActionId.SEND_SMS -> R.drawable.ic_outline_message_24
@@ -747,6 +750,8 @@ object ActionUtils {
747750
ActionId.DISMISS_MOST_RECENT_NOTIFICATION,
748751
-> return listOf(Permission.NOTIFICATION_LISTENER)
749752

753+
ActionId.CREATE_NOTIFICATION -> return listOf(Permission.POST_NOTIFICATIONS)
754+
750755
ActionId.ANSWER_PHONE_CALL,
751756
ActionId.END_PHONE_CALL,
752757
-> return listOf(Permission.ANSWER_PHONE_CALL)
@@ -888,6 +893,7 @@ object ActionUtils {
888893
ActionId.SOUND -> Icons.AutoMirrored.Outlined.VolumeUp
889894
ActionId.DISMISS_MOST_RECENT_NOTIFICATION -> Icons.Outlined.ClearAll
890895
ActionId.DISMISS_ALL_NOTIFICATIONS -> Icons.Outlined.ClearAll
896+
ActionId.CREATE_NOTIFICATION -> Icons.AutoMirrored.Outlined.Message
891897
ActionId.ANSWER_PHONE_CALL -> Icons.Outlined.Call
892898
ActionId.END_PHONE_CALL -> Icons.Outlined.CallEnd
893899
ActionId.DEVICE_CONTROLS -> KeyMapperIcons.HomeIotDevice
@@ -942,6 +948,7 @@ fun ActionData.isEditable(): Boolean = when (this) {
942948
is ActionData.ComposeSms,
943949
is ActionData.HttpRequest,
944950
is ActionData.ShellCommand,
951+
is ActionData.CreateNotification,
945952
is ActionData.InteractUiElement,
946953
is ActionData.MoveCursor,
947954
is ActionData.ModifySetting,

base/src/main/java/io/github/sds100/keymapper/base/actions/ChooseActionScreen.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ fun HandleActionBottomSheets(delegate: CreateActionDelegate) {
5757
SmsActionBottomSheet(delegate)
5858
VolumeActionBottomSheet(delegate)
5959
ModifySettingActionBottomSheet(delegate)
60+
CreateNotificationActionBottomSheet(delegate)
6061
}
6162

6263
@Composable

base/src/main/java/io/github/sds100/keymapper/base/actions/CreateActionDelegate.kt

Lines changed: 89 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import io.github.sds100.keymapper.common.utils.State
2525
import io.github.sds100.keymapper.system.SystemError
2626
import io.github.sds100.keymapper.system.camera.CameraLens
2727
import io.github.sds100.keymapper.system.network.HttpMethod
28+
import io.github.sds100.keymapper.system.permissions.Permission
2829
import io.github.sds100.keymapper.system.settings.SettingType
2930
import io.github.sds100.keymapper.system.volume.DndMode
3031
import io.github.sds100.keymapper.system.volume.RingerMode
@@ -60,9 +61,10 @@ class CreateActionDelegate(
6061
var httpRequestBottomSheetState: ActionData.HttpRequest? by mutableStateOf(null)
6162
var smsActionBottomSheetState: SmsActionBottomSheetState? by mutableStateOf(null)
6263
var volumeActionState: VolumeActionBottomSheetState? by mutableStateOf(null)
63-
var modifySettingActionBottomSheetState: ModifySettingActionBottomSheetState? by mutableStateOf(
64-
null,
65-
)
64+
var modifySettingActionBottomSheetState: ModifySettingActionBottomSheetState?
65+
by mutableStateOf(null)
66+
var createNotificationActionBottomSheetState: CreateNotificationActionBottomSheetState?
67+
by mutableStateOf(null)
6668

6769
init {
6870
coroutineScope.launch {
@@ -88,6 +90,20 @@ class CreateActionDelegate(
8890
)
8991
}
9092
}
93+
94+
coroutineScope.launch {
95+
snapshotFlow { createNotificationActionBottomSheetState }
96+
.filterNotNull()
97+
.flatMapLatest {
98+
useCase.isPermissionGrantedFlow(Permission.POST_NOTIFICATIONS)
99+
}
100+
.collectLatest { isGranted ->
101+
createNotificationActionBottomSheetState =
102+
createNotificationActionBottomSheetState?.copy(
103+
isPermissionGranted = isGranted,
104+
)
105+
}
106+
}
91107
}
92108

93109
fun onDoneConfigEnableFlashlightClick() {
@@ -280,12 +296,69 @@ class CreateActionDelegate(
280296
}
281297
}
282298

283-
fun onRequestModifySettingPermission() {
299+
fun onRequestModifySettingPermissionClick() {
284300
val state = modifySettingActionBottomSheetState ?: return
285301
val permission = useCase.getRequiredPermissionForSettingType(state.settingType)
286302
useCase.requestPermission(permission)
287303
}
288304

305+
fun onCreateNotificationTitleChange(title: String) {
306+
createNotificationActionBottomSheetState =
307+
createNotificationActionBottomSheetState?.copy(title = title)
308+
}
309+
310+
fun onCreateNotificationTextChange(text: String) {
311+
createNotificationActionBottomSheetState =
312+
createNotificationActionBottomSheetState?.copy(text = text)
313+
}
314+
315+
fun onCreateNotificationTimeoutEnabledChange(enabled: Boolean) {
316+
createNotificationActionBottomSheetState =
317+
createNotificationActionBottomSheetState?.copy(timeoutEnabled = enabled)
318+
}
319+
320+
fun onCreateNotificationTimeoutChange(timeoutSeconds: Int) {
321+
createNotificationActionBottomSheetState =
322+
createNotificationActionBottomSheetState?.copy(timeoutSeconds = timeoutSeconds)
323+
}
324+
325+
fun onTestCreateNotificationClick() {
326+
val state = createNotificationActionBottomSheetState ?: return
327+
328+
coroutineScope.launch {
329+
val timeoutMs = if (state.timeoutEnabled) {
330+
state.timeoutSeconds * 1000L
331+
} else {
332+
null
333+
}
334+
335+
useCase.testCreateNotification(state.title, state.text, timeoutMs)
336+
}
337+
}
338+
339+
fun onDoneCreateNotificationClick() {
340+
val state = createNotificationActionBottomSheetState ?: return
341+
342+
val timeoutMs = if (state.timeoutEnabled) {
343+
state.timeoutSeconds * 1000L
344+
} else {
345+
null
346+
}
347+
348+
val action = ActionData.CreateNotification(
349+
title = state.title,
350+
text = state.text,
351+
timeoutMs = timeoutMs,
352+
)
353+
354+
createNotificationActionBottomSheetState = null
355+
actionResult.update { action }
356+
}
357+
358+
fun onRequestNotificationPermissionClick() {
359+
useCase.requestPermission(Permission.POST_NOTIFICATIONS)
360+
}
361+
289362
suspend fun editAction(oldData: ActionData) {
290363
if (!oldData.isEditable()) {
291364
throw IllegalArgumentException("This action ${oldData.javaClass.name} can't be edited!")
@@ -974,6 +1047,18 @@ class CreateActionDelegate(
9741047
ActionId.DISABLE_DND_MODE -> return ActionData.DoNotDisturb.Disable
9751048
ActionId.DISMISS_MOST_RECENT_NOTIFICATION -> return ActionData.DismissLastNotification
9761049
ActionId.DISMISS_ALL_NOTIFICATIONS -> return ActionData.DismissAllNotifications
1050+
ActionId.CREATE_NOTIFICATION -> {
1051+
val oldAction = oldData as? ActionData.CreateNotification
1052+
1053+
createNotificationActionBottomSheetState = CreateNotificationActionBottomSheetState(
1054+
title = oldAction?.title ?: "",
1055+
text = oldAction?.text ?: "",
1056+
timeoutEnabled = oldAction?.timeoutMs != null,
1057+
timeoutSeconds = ((oldAction?.timeoutMs ?: 30000) / 1000).toInt(),
1058+
)
1059+
1060+
return null
1061+
}
9771062
ActionId.ANSWER_PHONE_CALL -> return ActionData.AnswerCall
9781063
ActionId.END_PHONE_CALL -> return ActionData.EndCall
9791064
ActionId.DEVICE_CONTROLS -> return ActionData.DeviceControls

0 commit comments

Comments
 (0)