diff --git a/app-common/src/main/java/eu/darken/capod/devices/core/DeviceProfile.kt b/app-common/src/main/java/eu/darken/capod/devices/core/DeviceProfile.kt new file mode 100644 index 00000000..cb33e984 --- /dev/null +++ b/app-common/src/main/java/eu/darken/capod/devices/core/DeviceProfile.kt @@ -0,0 +1,23 @@ +package eu.darken.capod.devices.core + +import android.os.Parcelable +import com.squareup.moshi.JsonClass +import eu.darken.capod.common.bluetooth.BluetoothAddress +import eu.darken.capod.pods.core.PodDevice +import eu.darken.capod.pods.core.apple.protocol.IdentityResolvingKey +import eu.darken.capod.pods.core.apple.protocol.ProximityEncryptionKey +import kotlinx.parcelize.Parcelize +import java.util.UUID + +@Parcelize +@JsonClass(generateAdapter = true) +data class DeviceProfile( + val id: String = UUID.randomUUID().toString(), + val name: String, + val address: BluetoothAddress? = null, + val model: PodDevice.Model = PodDevice.Model.UNKNOWN, + val identityKey: IdentityResolvingKey? = null, + val encryptionKey: ProximityEncryptionKey? = null, + val minimumSignalQuality: Float = 0.20f, + val isEnabled: Boolean = true +) : Parcelable \ No newline at end of file diff --git a/app-common/src/main/java/eu/darken/capod/devices/core/DeviceProfilesRepo.kt b/app-common/src/main/java/eu/darken/capod/devices/core/DeviceProfilesRepo.kt new file mode 100644 index 00000000..1f51943d --- /dev/null +++ b/app-common/src/main/java/eu/darken/capod/devices/core/DeviceProfilesRepo.kt @@ -0,0 +1,87 @@ +package eu.darken.capod.devices.core + +import android.content.Context +import android.content.SharedPreferences +import com.squareup.moshi.Moshi +import com.squareup.moshi.Types +import dagger.hilt.android.qualifiers.ApplicationContext +import eu.darken.capod.common.debug.logging.Logging.Priority.VERBOSE +import eu.darken.capod.common.debug.logging.log +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class DeviceProfilesRepo @Inject constructor( + @ApplicationContext private val context: Context, + private val moshi: Moshi, +) { + + private val preferences: SharedPreferences = context.getSharedPreferences("device_profiles", Context.MODE_PRIVATE) + + private val _profiles = MutableStateFlow>(emptyList()) + val profiles: Flow> = _profiles.asStateFlow() + + private val listType = Types.newParameterizedType(List::class.java, DeviceProfile::class.java) + private val adapter = moshi.adapter>(listType) + + init { + loadProfiles() + } + + private fun loadProfiles() { + val json = preferences.getString(KEY_PROFILES, null) + val loadedProfiles = if (json != null) { + try { + adapter.fromJson(json) ?: emptyList() + } catch (e: Exception) { + log(VERBOSE) { "Failed to load device profiles: $e" } + emptyList() + } + } else { + emptyList() + } + _profiles.value = loadedProfiles + log(VERBOSE) { "Loaded ${loadedProfiles.size} device profiles" } + } + + private fun saveProfiles() { + val json = adapter.toJson(_profiles.value) + preferences.edit().putString(KEY_PROFILES, json).apply() + log(VERBOSE) { "Saved ${_profiles.value.size} device profiles" } + } + + fun addProfile(profile: DeviceProfile) { + val updatedProfiles = _profiles.value.toMutableList() + updatedProfiles.add(profile) + _profiles.value = updatedProfiles + saveProfiles() + } + + fun updateProfile(profile: DeviceProfile) { + val updatedProfiles = _profiles.value.toMutableList() + val index = updatedProfiles.indexOfFirst { it.id == profile.id } + if (index != -1) { + updatedProfiles[index] = profile + _profiles.value = updatedProfiles + saveProfiles() + } + } + + fun removeProfile(profileId: String) { + val updatedProfiles = _profiles.value.toMutableList() + updatedProfiles.removeAll { it.id == profileId } + _profiles.value = updatedProfiles + saveProfiles() + } + + fun getProfile(profileId: String): DeviceProfile? { + return _profiles.value.find { it.id == profileId } + } + + companion object { + private const val KEY_PROFILES = "profiles" + } +} \ No newline at end of file diff --git a/app/src/main/java/eu/darken/capod/devices/ui/DeviceProfileVH.kt b/app/src/main/java/eu/darken/capod/devices/ui/DeviceProfileVH.kt index d3129852..71bca170 100644 --- a/app/src/main/java/eu/darken/capod/devices/ui/DeviceProfileVH.kt +++ b/app/src/main/java/eu/darken/capod/devices/ui/DeviceProfileVH.kt @@ -21,6 +21,10 @@ class DeviceProfileVH(parent: ViewGroup) : deviceName.text = profile.name deviceDetails.text = buildString { + profile.address?.let { + append(it.toString()) + append(" • ") + } append(profile.model.name) } diff --git a/app/src/main/res/navigation/nav_graph.xml b/app/src/main/res/navigation/nav_graph.xml index d6c886b1..54a6bb9d 100644 --- a/app/src/main/res/navigation/nav_graph.xml +++ b/app/src/main/res/navigation/nav_graph.xml @@ -35,6 +35,11 @@ android:id="@+id/action_settingsFragment_to_troubleShooterFragment" app:destination="@id/troubleShooterFragment" /> +