From fd730a5daae5f4d90b6306935abaec8042e877f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sylwester=20Zieli=C5=84ski?= Date: Fri, 18 Feb 2022 12:46:51 +0100 Subject: [PATCH] Add data store to UART profile --- profile_uart/build.gradle | 2 +- .../android/uart/data/MacroSerializer.kt | 14 ++-- .../uart/data/UARTPersistentDataSource.kt | 78 +++++++++++++++++++ .../uart/data/UARTSharedPrefDataSource.kt | 26 ------- .../android/uart/viewmodel/UARTViewModel.kt | 18 +++-- profile_uart/src/main/proto/macro.proto | 2 +- 6 files changed, 101 insertions(+), 39 deletions(-) create mode 100644 profile_uart/src/main/java/no/nordicsemi/android/uart/data/UARTPersistentDataSource.kt delete mode 100644 profile_uart/src/main/java/no/nordicsemi/android/uart/data/UARTSharedPrefDataSource.kt diff --git a/profile_uart/build.gradle b/profile_uart/build.gradle index 246123f1..23060964 100644 --- a/profile_uart/build.gradle +++ b/profile_uart/build.gradle @@ -4,7 +4,7 @@ apply plugin: 'com.google.protobuf' protobuf { protoc { - artifact = "com.google.protobuf:protoc:3.14.0" + artifact = 'com.google.protobuf:protoc:3.14.0:osx-x86_64' } // Generates the java Protobuf-lite code for the Protobufs in this project. See diff --git a/profile_uart/src/main/java/no/nordicsemi/android/uart/data/MacroSerializer.kt b/profile_uart/src/main/java/no/nordicsemi/android/uart/data/MacroSerializer.kt index 6a5c92ac..40336cb7 100644 --- a/profile_uart/src/main/java/no/nordicsemi/android/uart/data/MacroSerializer.kt +++ b/profile_uart/src/main/java/no/nordicsemi/android/uart/data/MacroSerializer.kt @@ -1,23 +1,25 @@ package no.nordicsemi.android.uart.data +import androidx.datastore.core.CorruptionException import androidx.datastore.core.Serializer -import no.nordicsemi.android.Macro +import androidx.datastore.preferences.protobuf.InvalidProtocolBufferException +import no.nordicsemi.android.MacroSettings import java.io.InputStream import java.io.OutputStream -object MacroSerializer : Serializer { - override val defaultValue: UARTMacro = Macro.getDefaultInstance() +object MacroSerializer : Serializer { + override val defaultValue: MacroSettings = MacroSettings.getDefaultInstance() - override suspend fun readFrom(input: InputStream): UARTMacro { + override suspend fun readFrom(input: InputStream): MacroSettings { try { - return Settings.parseFrom(input) + return MacroSettings.parseFrom(input) } catch (exception: InvalidProtocolBufferException) { throw CorruptionException("Cannot read proto.", exception) } } override suspend fun writeTo( - t: UARTMacro, + t: MacroSettings, output: OutputStream ) = t.writeTo(output) } diff --git a/profile_uart/src/main/java/no/nordicsemi/android/uart/data/UARTPersistentDataSource.kt b/profile_uart/src/main/java/no/nordicsemi/android/uart/data/UARTPersistentDataSource.kt new file mode 100644 index 00000000..28bd20c5 --- /dev/null +++ b/profile_uart/src/main/java/no/nordicsemi/android/uart/data/UARTPersistentDataSource.kt @@ -0,0 +1,78 @@ +package no.nordicsemi.android.uart.data + +import android.content.Context +import androidx.datastore.core.DataStore +import androidx.datastore.dataStore +import dagger.hilt.android.qualifiers.ApplicationContext +import kotlinx.coroutines.flow.map +import no.nordicsemi.android.Macro +import no.nordicsemi.android.MacroSettings +import javax.inject.Inject +import javax.inject.Singleton + +private const val MACRO_FILE = "macro.proto" + +@Singleton +internal class UARTPersistentDataSource @Inject constructor( + @ApplicationContext + private val context: Context +) { + private val Context.dataStore: DataStore by dataStore(fileName = MACRO_FILE, MacroSerializer) + + val macros = context.dataStore.data.map { + it.macrosList.map { + UARTMacro(it.name, it.newLineType.toNewLineChar()) + } + } + + suspend fun saveMacros(uartMacros: List) { + context.dataStore.updateData { settings -> + val macros = uartMacros.map { it.toMacro() } + settings.toBuilder() + .clearMacros() + .addAllMacros(macros) + .build() + } + } + + suspend fun addNewMacro(uartMacro: UARTMacro) { + context.dataStore.updateData { settings -> + settings.toBuilder() + .addMacros(uartMacro.toMacro()) + .build() + } + } + + suspend fun deleteMacro(uartMacro: UARTMacro) { + context.dataStore.updateData { settings -> + val i = settings.macrosList.map { it.name }.indexOf(uartMacro.command) + settings.toBuilder() + .removeMacros(i) + .build() + } + } + + private fun UARTMacro.toMacro(): Macro { + return Macro.newBuilder() + .setName(command) + .setNewLineType(newLineChar.toMacroNewLineType()) + .build() + } + + private fun NewLineChar.toMacroNewLineType(): Macro.NewLineType { + return when (this) { + NewLineChar.LF -> Macro.NewLineType.LF + NewLineChar.CR_LF -> Macro.NewLineType.LF_CR + NewLineChar.CR -> Macro.NewLineType.CR + } + } + + private fun Macro.NewLineType.toNewLineChar(): NewLineChar { + return when (this) { + Macro.NewLineType.LF -> NewLineChar.LF + Macro.NewLineType.LF_CR -> NewLineChar.CR_LF + Macro.NewLineType.CR -> NewLineChar.CR + Macro.NewLineType.UNRECOGNIZED -> throw IllegalArgumentException("Unrecognized NewLineChar.") + } + } +} diff --git a/profile_uart/src/main/java/no/nordicsemi/android/uart/data/UARTSharedPrefDataSource.kt b/profile_uart/src/main/java/no/nordicsemi/android/uart/data/UARTSharedPrefDataSource.kt deleted file mode 100644 index 6f9b3633..00000000 --- a/profile_uart/src/main/java/no/nordicsemi/android/uart/data/UARTSharedPrefDataSource.kt +++ /dev/null @@ -1,26 +0,0 @@ -package no.nordicsemi.android.uart.data - -import android.content.Context -import androidx.datastore.core.DataStore -import androidx.datastore.dataStore -import dagger.hilt.android.qualifiers.ApplicationContext -import java.util.prefs.Preferences -import javax.inject.Inject - -private const val MACRO_FILE = "macro.proto" - -internal class UARTSharedPrefDataSource @Inject constructor( - @ApplicationContext - context: Context -) { -// val Context.dataStore: DataStore by dataStore(fileName = MACRO_FILE, MacroSerializer) -// -// private val sp = context.getSharedPreferences(PREFS_FILE, Context.MODE_PRIVATE) -// -//// val macros: -// -// init { -// -// sp.edit() -// } -} diff --git a/profile_uart/src/main/java/no/nordicsemi/android/uart/viewmodel/UARTViewModel.kt b/profile_uart/src/main/java/no/nordicsemi/android/uart/viewmodel/UARTViewModel.kt index db994bcf..a3e3b7b0 100644 --- a/profile_uart/src/main/java/no/nordicsemi/android/uart/viewmodel/UARTViewModel.kt +++ b/profile_uart/src/main/java/no/nordicsemi/android/uart/viewmodel/UARTViewModel.kt @@ -3,10 +3,12 @@ package no.nordicsemi.android.uart.viewmodel import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch import no.nordicsemi.android.navigation.* import no.nordicsemi.android.uart.data.UARTMacro +import no.nordicsemi.android.uart.data.UARTPersistentDataSource import no.nordicsemi.android.uart.data.UART_SERVICE_UUID import no.nordicsemi.android.uart.repository.UARTRepository import no.nordicsemi.android.uart.view.* @@ -18,7 +20,8 @@ import javax.inject.Inject @HiltViewModel internal class UARTViewModel @Inject constructor( private val repository: UARTRepository, - private val navigationManager: NavigationManager + private val navigationManager: NavigationManager, + private val dataSource: UARTPersistentDataSource ) : ViewModel() { private val _state = MutableStateFlow(UARTViewState()) @@ -34,6 +37,10 @@ internal class UARTViewModel @Inject constructor( repository.data.onEach { _state.value = _state.value.copy(uartManagerState = WorkingState(it)) }.launchIn(viewModelScope) + + dataSource.macros.onEach { + _state.value = _state.value.copy(macros = it) + }.launchIn(viewModelScope) } private fun requestBluetoothDevice() { @@ -64,14 +71,15 @@ internal class UARTViewModel @Inject constructor( } private fun addNewMacro(macro: UARTMacro) { - _state.tryEmit(_state.value.copy(macros = _state.value.macros + macro)) + viewModelScope.launch(Dispatchers.IO) { + dataSource.addNewMacro(macro) + } } private fun deleteMacro(macro: UARTMacro) { - val macros = _state.value.macros.toMutableList().apply { - remove(macro) + viewModelScope.launch(Dispatchers.IO) { + dataSource.deleteMacro(macro) } - _state.tryEmit(_state.value.copy(macros = macros)) } private fun disconnect() { diff --git a/profile_uart/src/main/proto/macro.proto b/profile_uart/src/main/proto/macro.proto index db4d3408..6265d4b5 100644 --- a/profile_uart/src/main/proto/macro.proto +++ b/profile_uart/src/main/proto/macro.proto @@ -14,5 +14,5 @@ message Macro { } message MacroSettings { - string macros = 1; + repeated Macro macros = 1; }