@@ -26,6 +26,7 @@ import io.github.sds100.keymapper.data.entities.FingerprintMapEntity
2626import io.github.sds100.keymapper.data.entities.FloatingButtonEntity
2727import io.github.sds100.keymapper.data.entities.FloatingButtonKeyEntity
2828import io.github.sds100.keymapper.data.entities.FloatingLayoutEntity
29+ import io.github.sds100.keymapper.data.entities.FloatingLayoutEntityWithButtons
2930import io.github.sds100.keymapper.data.entities.GroupEntity
3031import io.github.sds100.keymapper.data.entities.KeyMapEntity
3132import io.github.sds100.keymapper.data.entities.TriggerEntity
@@ -59,13 +60,11 @@ import io.github.sds100.keymapper.util.then
5960import kotlinx.coroutines.CoroutineScope
6061import kotlinx.coroutines.flow.Flow
6162import kotlinx.coroutines.flow.MutableSharedFlow
62- import kotlinx.coroutines.flow.collectLatest
63- import kotlinx.coroutines.flow.drop
63+ import kotlinx.coroutines.flow.collect
64+ import kotlinx.coroutines.flow.combine
6465import kotlinx.coroutines.flow.filterIsInstance
6566import kotlinx.coroutines.flow.first
66- import kotlinx.coroutines.flow.launchIn
6767import kotlinx.coroutines.flow.map
68- import kotlinx.coroutines.flow.onEach
6968import kotlinx.coroutines.launch
7069import kotlinx.coroutines.withContext
7170import timber.log.Timber
@@ -128,39 +127,25 @@ class BackupManagerImpl(
128127 .get(Keys .automaticBackupLocation).map { it != null }
129128
130129 init {
131- val doAutomaticBackup = MutableSharedFlow <AutomaticBackup >()
132-
133130 coroutineScope.launch {
134- doAutomaticBackup.collectLatest { backupData ->
135- if (! backupAutomatically.first()) return @collectLatest
136-
137- val backupLocation = preferenceRepository.get(Keys .automaticBackupLocation).first()
138- ? : return @collectLatest
131+ combine(
132+ backupAutomatically,
133+ preferenceRepository.get(Keys .automaticBackupLocation),
134+ keyMapRepository.keyMapList.filterIsInstance<State .Data <List <KeyMapEntity >>>(),
135+ groupRepository.getAllGroups(),
136+ floatingLayoutRepository.layouts.filterIsInstance<State .Data <List <FloatingLayoutEntityWithButtons >>>(),
137+ ) { backupAutomatically, location, keyMaps, groups, floatingLayouts ->
138+ if (! backupAutomatically) {
139+ return @combine
140+ }
139141
140- val outputFile = fileAdapter.getFileFromUri(backupLocation)
141- val result = backupAsync(outputFile, backupData.keyMapList)
142+ location ? : return @combine
142143
144+ val outputFile = fileAdapter.getFileFromUri(location)
145+ val result = backupAsync(outputFile, keyMaps.data, groups, floatingLayouts.data)
143146 onAutomaticBackupResult.emit(result)
144- }
147+ }.collect()
145148 }
146-
147- coroutineScope.launch {
148- keyMapRepository.requestBackup.collectLatest { keyMapList ->
149- val backupData = AutomaticBackup (keyMapList = keyMapList)
150-
151- doAutomaticBackup.emit(backupData)
152- }
153- }
154-
155- // automatically back up when the location changes
156- preferenceRepository.get(Keys .automaticBackupLocation).drop(1 ).onEach {
157- val keyMaps =
158- keyMapRepository.keyMapList.first { it is State .Data } as State .Data
159-
160- val data = AutomaticBackup (keyMapList = keyMaps.data)
161-
162- doAutomaticBackup.emit(data)
163- }.launchIn(coroutineScope)
164149 }
165150
166151 override suspend fun backupKeyMaps (output : IFile , keyMapIds : List <String >): Result <Unit > {
@@ -186,7 +171,11 @@ class BackupManagerImpl(
186171
187172 val groups = groupRepository.getAllGroups().first()
188173
189- backupAsync(output, keyMaps.data, groups)
174+ val layouts = floatingLayoutRepository.layouts
175+ .filterIsInstance<State .Data <List <FloatingLayoutEntityWithButtons >>>()
176+ .first()
177+
178+ backupAsync(output, keyMaps.data, groups, layouts.data)
190179
191180 Success (Unit )
192181 }
@@ -624,8 +613,9 @@ class BackupManagerImpl(
624613
625614 private suspend fun backupAsync (
626615 output : IFile ,
627- keyMapList : List <KeyMapEntity >? = null ,
616+ keyMapList : List <KeyMapEntity > = emptyList() ,
628617 extraGroups : List <GroupEntity > = emptyList(),
618+ extraLayouts : List <FloatingLayoutEntityWithButtons > = emptyList(),
629619 ): Result <IFile > {
630620 return withContext(dispatchers.io()) {
631621 val backupUid = uuidGenerator.random()
@@ -637,80 +627,7 @@ class BackupManagerImpl(
637627 // delete the contents of the file
638628 output.clear()
639629
640- val floatingLayouts: MutableList <FloatingLayoutEntity > = mutableListOf ()
641- val floatingButtons: MutableList <FloatingButtonEntity > = mutableListOf ()
642- val groupMap: MutableMap <String , GroupEntity > = mutableMapOf ()
643-
644- if (keyMapList != null ) {
645- val floatingButtonTriggerKeys = keyMapList
646- .flatMap { it.trigger.keys }
647- .filterIsInstance<FloatingButtonKeyEntity >()
648- .map { it.buttonUid }
649- .distinct()
650-
651- for (buttonUid in floatingButtonTriggerKeys) {
652- val buttonWithLayout = floatingButtonRepository.get(buttonUid) ? : continue
653-
654- if (floatingLayouts.none { it.uid == buttonWithLayout.layout.uid }) {
655- floatingLayouts.add(buttonWithLayout.layout)
656- }
657-
658- floatingButtons.add(buttonWithLayout.button)
659- }
660-
661- for (keyMap in keyMapList) {
662- val groupUid = keyMap.groupUid ? : continue
663- if (! groupMap.containsKey(groupUid)) {
664- val groupEntity = groupRepository.getGroup(groupUid) ? : continue
665- groupMap[groupUid] = groupEntity
666- }
667- }
668-
669- for (group in extraGroups) {
670- if (! groupMap.containsKey(group.uid)) {
671- groupMap[group.uid] = group
672- }
673- }
674- }
675-
676- val backupContent = BackupContent (
677- AppDatabase .DATABASE_VERSION ,
678- Constants .VERSION_CODE ,
679- keyMapList,
680- defaultLongPressDelay =
681- preferenceRepository
682- .get(Keys .defaultLongPressDelay)
683- .first()
684- .takeIf { it != PreferenceDefaults .LONG_PRESS_DELAY },
685- defaultDoublePressDelay =
686- preferenceRepository
687- .get(Keys .defaultDoublePressDelay)
688- .first()
689- .takeIf { it != PreferenceDefaults .DOUBLE_PRESS_DELAY },
690- defaultRepeatDelay =
691- preferenceRepository
692- .get(Keys .defaultRepeatDelay)
693- .first()
694- .takeIf { it != PreferenceDefaults .REPEAT_DELAY },
695- defaultRepeatRate =
696- preferenceRepository
697- .get(Keys .defaultRepeatRate)
698- .first()
699- .takeIf { it != PreferenceDefaults .REPEAT_RATE },
700- defaultSequenceTriggerTimeout =
701- preferenceRepository
702- .get(Keys .defaultSequenceTriggerTimeout)
703- .first()
704- .takeIf { it != PreferenceDefaults .SEQUENCE_TRIGGER_TIMEOUT },
705- defaultVibrationDuration =
706- preferenceRepository
707- .get(Keys .defaultVibrateDuration)
708- .first()
709- .takeIf { it != PreferenceDefaults .VIBRATION_DURATION },
710- floatingLayouts = floatingLayouts.takeIf { it.isNotEmpty() },
711- floatingButtons = floatingButtons.takeIf { it.isNotEmpty() },
712- groups = groupMap.values.toList(),
713- )
630+ val backupContent = createBackupContent(keyMapList, extraGroups, extraLayouts)
714631
715632 val json = gson.toJson(backupContent)
716633
@@ -758,9 +675,100 @@ class BackupManagerImpl(
758675 }
759676 }
760677
761- private data class AutomaticBackup (
762- val keyMapList : List <KeyMapEntity >? ,
763- )
678+ suspend fun createBackupContent (
679+ keyMapList : List <KeyMapEntity >,
680+ extraGroups : List <GroupEntity >,
681+ extraLayouts : List <FloatingLayoutEntityWithButtons >,
682+ ): BackupContent {
683+ val floatingLayoutsMap: MutableMap <String , FloatingLayoutEntity > = mutableMapOf ()
684+ val floatingButtonsMap: MutableMap <String , FloatingButtonEntity > = mutableMapOf ()
685+ val groupMap: MutableMap <String , GroupEntity > = mutableMapOf ()
686+
687+ val floatingButtonTriggerKeys = keyMapList
688+ .flatMap { it.trigger.keys }
689+ .filterIsInstance<FloatingButtonKeyEntity >()
690+ .map { it.buttonUid }
691+ .distinct()
692+
693+ for (buttonUid in floatingButtonTriggerKeys) {
694+ val buttonWithLayout = floatingButtonRepository.get(buttonUid) ? : continue
695+ val layoutUid = buttonWithLayout.layout.uid
696+
697+ if (! floatingLayoutsMap.containsKey(layoutUid)) {
698+ floatingLayoutsMap[layoutUid] = buttonWithLayout.layout
699+ }
700+
701+ if (! floatingButtonsMap.containsKey(buttonUid)) {
702+ floatingButtonsMap[buttonUid] = buttonWithLayout.button
703+ }
704+ }
705+
706+ for (keyMap in keyMapList) {
707+ val groupUid = keyMap.groupUid ? : continue
708+ if (! groupMap.containsKey(groupUid)) {
709+ val groupEntity = groupRepository.getGroup(groupUid) ? : continue
710+ groupMap[groupUid] = groupEntity
711+ }
712+ }
713+
714+ for (group in extraGroups) {
715+ if (! groupMap.containsKey(group.uid)) {
716+ groupMap[group.uid] = group
717+ }
718+ }
719+
720+ for (layoutWithButtons in extraLayouts) {
721+ if (! floatingLayoutsMap.containsKey(layoutWithButtons.layout.uid)) {
722+ floatingLayoutsMap[layoutWithButtons.layout.uid] = layoutWithButtons.layout
723+ }
724+
725+ for (button in layoutWithButtons.buttons) {
726+ if (! floatingButtonsMap.containsKey(button.uid)) {
727+ floatingButtonsMap[button.uid] = button
728+ }
729+ }
730+ }
731+
732+ val backupContent = BackupContent (
733+ AppDatabase .DATABASE_VERSION ,
734+ Constants .VERSION_CODE ,
735+ keyMapList,
736+ defaultLongPressDelay =
737+ preferenceRepository
738+ .get(Keys .defaultLongPressDelay)
739+ .first()
740+ .takeIf { it != PreferenceDefaults .LONG_PRESS_DELAY },
741+ defaultDoublePressDelay =
742+ preferenceRepository
743+ .get(Keys .defaultDoublePressDelay)
744+ .first()
745+ .takeIf { it != PreferenceDefaults .DOUBLE_PRESS_DELAY },
746+ defaultRepeatDelay =
747+ preferenceRepository
748+ .get(Keys .defaultRepeatDelay)
749+ .first()
750+ .takeIf { it != PreferenceDefaults .REPEAT_DELAY },
751+ defaultRepeatRate =
752+ preferenceRepository
753+ .get(Keys .defaultRepeatRate)
754+ .first()
755+ .takeIf { it != PreferenceDefaults .REPEAT_RATE },
756+ defaultSequenceTriggerTimeout =
757+ preferenceRepository
758+ .get(Keys .defaultSequenceTriggerTimeout)
759+ .first()
760+ .takeIf { it != PreferenceDefaults .SEQUENCE_TRIGGER_TIMEOUT },
761+ defaultVibrationDuration =
762+ preferenceRepository
763+ .get(Keys .defaultVibrateDuration)
764+ .first()
765+ .takeIf { it != PreferenceDefaults .VIBRATION_DURATION },
766+ floatingLayouts = floatingLayoutsMap.values.toList().takeIf { it.isNotEmpty() },
767+ floatingButtons = floatingButtonsMap.values.toList().takeIf { it.isNotEmpty() },
768+ groups = groupMap.values.toList().takeIf { it.isNotEmpty() },
769+ )
770+ return backupContent
771+ }
764772}
765773
766774interface BackupManager {
0 commit comments