diff --git a/core/interfaces/src/main/java/info/nightscout/interfaces/maintenance/PrefMetadata.kt b/core/interfaces/src/main/java/info/nightscout/interfaces/maintenance/PrefMetadata.kt new file mode 100644 index 0000000000..a8953b2fe6 --- /dev/null +++ b/core/interfaces/src/main/java/info/nightscout/interfaces/maintenance/PrefMetadata.kt @@ -0,0 +1,7 @@ +package info.nightscout.interfaces.maintenance + +import android.os.Parcelable +import kotlinx.parcelize.Parcelize + +@Parcelize +data class PrefMetadata(var value: String, var status: PrefsStatus, var info: String? = null) : Parcelable diff --git a/core/interfaces/src/main/java/info/nightscout/interfaces/maintenance/PrefsMetadataKey.kt b/core/interfaces/src/main/java/info/nightscout/interfaces/maintenance/PrefsMetadataKey.kt new file mode 100644 index 0000000000..80c81ec0fb --- /dev/null +++ b/core/interfaces/src/main/java/info/nightscout/interfaces/maintenance/PrefsMetadataKey.kt @@ -0,0 +1,11 @@ +package info.nightscout.interfaces.maintenance + +import android.content.Context + +interface PrefsMetadataKey { + + val key: String + val icon: Int + val label: Int + fun formatForDisplay(context: Context, value: String): String +} \ No newline at end of file diff --git a/core/interfaces/src/main/java/info/nightscout/interfaces/maintenance/PrefsStatus.kt b/core/interfaces/src/main/java/info/nightscout/interfaces/maintenance/PrefsStatus.kt new file mode 100644 index 0000000000..e3df9f692e --- /dev/null +++ b/core/interfaces/src/main/java/info/nightscout/interfaces/maintenance/PrefsStatus.kt @@ -0,0 +1,8 @@ +package info.nightscout.interfaces.maintenance + +import android.os.Parcelable + +interface PrefsStatus : Parcelable { + + val icon: Int +} \ No newline at end of file diff --git a/core/interfaces/src/main/res/values/strings.xml b/core/interfaces/src/main/res/values/strings.xml index bc7e2675d6..983f5ad355 100644 --- a/core/interfaces/src/main/res/values/strings.xml +++ b/core/interfaces/src/main/res/values/strings.xml @@ -1,17 +1,5 @@ - - File format - Created at - AAPS Version - Build Variant - Exporting device patient name - Exporting device model - File encryption - New encrypted format - New debug format (unencrypted) - Unknown export format - Pump driver changed. diff --git a/implementation/src/main/java/info/nightscout/implementation/utils/DecimalFormatterImpl.kt b/implementation/src/main/java/info/nightscout/implementation/utils/DecimalFormatterImpl.kt index f627734e9a..dde9b43d80 100644 --- a/implementation/src/main/java/info/nightscout/implementation/utils/DecimalFormatterImpl.kt +++ b/implementation/src/main/java/info/nightscout/implementation/utils/DecimalFormatterImpl.kt @@ -1,6 +1,5 @@ package info.nightscout.implementation.utils -import info.nightscout.interfaces.R import info.nightscout.interfaces.utils.DecimalFormatter import info.nightscout.shared.interfaces.ResourceHelper import java.text.DecimalFormat diff --git a/plugins/configuration/build.gradle b/plugins/configuration/build.gradle index 8b66f55e8e..e407d97d9e 100644 --- a/plugins/configuration/build.gradle +++ b/plugins/configuration/build.gradle @@ -3,6 +3,7 @@ plugins { id 'kotlin-android' id 'kotlin-kapt' id 'kotlin-allopen' + id 'kotlin-parcelize' } apply from: "${project.rootDir}/core/main/android_dependencies.gradle" diff --git a/plugins/configuration/src/main/java/info/nightscout/configuration/maintenance/ImportExportPrefsImpl.kt b/plugins/configuration/src/main/java/info/nightscout/configuration/maintenance/ImportExportPrefsImpl.kt index e3aae49ae9..0a765eab2a 100644 --- a/plugins/configuration/src/main/java/info/nightscout/configuration/maintenance/ImportExportPrefsImpl.kt +++ b/plugins/configuration/src/main/java/info/nightscout/configuration/maintenance/ImportExportPrefsImpl.kt @@ -44,7 +44,7 @@ import info.nightscout.interfaces.maintenance.Prefs import info.nightscout.interfaces.maintenance.PrefsFile import info.nightscout.interfaces.maintenance.PrefsFormat import info.nightscout.interfaces.maintenance.PrefsMetadataKey -import info.nightscout.interfaces.maintenance.PrefsStatus +import info.nightscout.interfaces.maintenance.PrefsStatusImpl import info.nightscout.interfaces.protection.PasswordCheck import info.nightscout.interfaces.storage.Storage import info.nightscout.interfaces.ui.UiInteraction @@ -114,12 +114,12 @@ class ImportExportPrefsImpl @Inject constructor( val metadata: MutableMap = mutableMapOf() - metadata[PrefsMetadataKey.DEVICE_NAME] = PrefMetadata(detectUserName(context), PrefsStatus.OK) - metadata[PrefsMetadataKey.CREATED_AT] = PrefMetadata(dateUtil.toISOString(dateUtil.now()), PrefsStatus.OK) - metadata[PrefsMetadataKey.AAPS_VERSION] = PrefMetadata(config.VERSION_NAME, PrefsStatus.OK) - metadata[PrefsMetadataKey.AAPS_FLAVOUR] = PrefMetadata(config.FLAVOR, PrefsStatus.OK) - metadata[PrefsMetadataKey.DEVICE_MODEL] = PrefMetadata(config.currentDeviceModelString, PrefsStatus.OK) - metadata[PrefsMetadataKey.ENCRYPTION] = PrefMetadata("Enabled", PrefsStatus.OK) + metadata[PrefsMetadataKeyImpl.DEVICE_NAME] = PrefMetadata(detectUserName(context), PrefsStatusImpl.OK) + metadata[PrefsMetadataKeyImpl.CREATED_AT] = PrefMetadata(dateUtil.toISOString(dateUtil.now()), PrefsStatusImpl.OK) + metadata[PrefsMetadataKeyImpl.AAPS_VERSION] = PrefMetadata(config.VERSION_NAME, PrefsStatusImpl.OK) + metadata[PrefsMetadataKeyImpl.AAPS_FLAVOUR] = PrefMetadata(config.FLAVOR, PrefsStatusImpl.OK) + metadata[PrefsMetadataKeyImpl.DEVICE_MODEL] = PrefMetadata(config.currentDeviceModelString, PrefsStatusImpl.OK) + metadata[PrefsMetadataKeyImpl.ENCRYPTION] = PrefMetadata("Enabled", PrefsStatusImpl.OK) return metadata } @@ -133,7 +133,7 @@ class ImportExportPrefsImpl @Inject constructor( if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S || ActivityCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH_CONNECT) == PackageManager.PERMISSION_GRANTED) { (context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager?)?.adapter?.name } else null - } catch (e: Exception){ + } catch (e: Exception) { null } val n4 = Settings.System.getString(context.contentResolver, "device_name") @@ -219,7 +219,7 @@ class ImportExportPrefsImpl @Inject constructor( ) { // current master password was not the one used for decryption, so we prompt for old password... - if (!importOk && (prefs.metadata[PrefsMetadataKey.ENCRYPTION]?.status == PrefsStatus.ERROR)) { + if (!importOk && (prefs.metadata[PrefsMetadataKeyImpl.ENCRYPTION]?.status == PrefsStatusImpl.ERROR)) { askForEncryptionPass( activity, R.string.preferences_import_canceled, R.string.old_master_password, R.string.different_password_used, R.string.master_password_will_be_replaced @@ -303,6 +303,7 @@ class ImportExportPrefsImpl @Inject constructor( override fun importCustomWatchface(fragment: Fragment) { fragment.activity?.let { importCustomWatchface(it) } } + override fun importCustomWatchface(activity: FragmentActivity) { try { if (activity is DaggerAppCompatActivityWithResult) @@ -317,7 +318,7 @@ class ImportExportPrefsImpl @Inject constructor( override fun exportCustomWatchface(customWatchface: CwfData, withDate: Boolean) { prefFileList.ensureExportDirExists() - val newFile = prefFileList.newCwfFile(customWatchface.metadata[CwfMetadataKey.CWF_FILENAME] ?:"", withDate) + val newFile = prefFileList.newCwfFile(customWatchface.metadata[CwfMetadataKey.CWF_FILENAME] ?: "", withDate) ZipWatchfaceFormat.saveCustomWatchface(newFile, customWatchface) } @@ -374,7 +375,7 @@ class ImportExportPrefsImpl @Inject constructor( var importOk = true for ((_, value) in prefs.metadata) { - if (value.status == PrefsStatus.ERROR) + if (value.status == PrefsStatusImpl.ERROR) importOk = false } return importOk diff --git a/plugins/configuration/src/main/java/info/nightscout/configuration/maintenance/PrefFileListProviderImpl.kt b/plugins/configuration/src/main/java/info/nightscout/configuration/maintenance/PrefFileListProviderImpl.kt index ebef240c4b..cde245a724 100644 --- a/plugins/configuration/src/main/java/info/nightscout/configuration/maintenance/PrefFileListProviderImpl.kt +++ b/plugins/configuration/src/main/java/info/nightscout/configuration/maintenance/PrefFileListProviderImpl.kt @@ -14,7 +14,7 @@ import info.nightscout.interfaces.maintenance.PrefMetadataMap import info.nightscout.interfaces.maintenance.PrefsFile import info.nightscout.interfaces.maintenance.PrefsImportDir import info.nightscout.interfaces.maintenance.PrefsMetadataKey -import info.nightscout.interfaces.maintenance.PrefsStatus +import info.nightscout.interfaces.maintenance.PrefsStatusImpl import info.nightscout.interfaces.storage.Storage import info.nightscout.interfaces.versionChecker.VersionCheckerUtils import info.nightscout.rx.bus.RxBus @@ -89,8 +89,8 @@ class PrefFileListProviderImpl @Inject constructor( // we sort only if we have metadata to be used for that if (loadMetadata) { prefFiles.sortWith( - compareByDescending { it.metadata[PrefsMetadataKey.AAPS_FLAVOUR]?.status } - .thenByDescending { it.metadata[PrefsMetadataKey.CREATED_AT]?.value } + compareByDescending { it.metadata[PrefsMetadataKeyImpl.AAPS_FLAVOUR]?.status as PrefsStatusImpl } + .thenByDescending { it.metadata[PrefsMetadataKeyImpl.CREATED_AT]?.value } ) } @@ -169,29 +169,29 @@ class PrefFileListProviderImpl @Inject constructor( override fun newCwfFile(filename: String, withDate: Boolean): File { val timeLocal = LocalDateTime.now().toString(DateTimeFormat.forPattern("yyyy-MM-dd'_'HHmmss")) - return if (withDate) File(exportsPath, "${filename}_$timeLocal${ZipWatchfaceFormat.CWF_EXTENTION}") else File(exportsPath,"${filename}${ZipWatchfaceFormat.CWF_EXTENTION}") + return if (withDate) File(exportsPath, "${filename}_$timeLocal${ZipWatchfaceFormat.CWF_EXTENTION}") else File(exportsPath, "${filename}${ZipWatchfaceFormat.CWF_EXTENTION}") } // check metadata for known issues, change their status and add info with explanations override fun checkMetadata(metadata: Map): Map { val meta = metadata.toMutableMap() - meta[PrefsMetadataKey.AAPS_FLAVOUR]?.let { flavour -> + meta[PrefsMetadataKeyImpl.AAPS_FLAVOUR]?.let { flavour -> val flavourOfPrefs = flavour.value if (flavour.value != config.get().FLAVOR) { - flavour.status = PrefsStatus.WARN + flavour.status = PrefsStatusImpl.WARN flavour.info = rh.gs(R.string.metadata_warning_different_flavour, flavourOfPrefs, config.get().FLAVOR) } } - meta[PrefsMetadataKey.DEVICE_MODEL]?.let { model -> + meta[PrefsMetadataKeyImpl.DEVICE_MODEL]?.let { model -> if (model.value != config.get().currentDeviceModelString) { - model.status = PrefsStatus.WARN + model.status = PrefsStatusImpl.WARN model.info = rh.gs(R.string.metadata_warning_different_device) } } - meta[PrefsMetadataKey.CREATED_AT]?.let { createdAt -> + meta[PrefsMetadataKeyImpl.CREATED_AT]?.let { createdAt -> try { val date1 = DateTime.parse(createdAt.value) val date2 = DateTime.now() @@ -199,26 +199,26 @@ class PrefFileListProviderImpl @Inject constructor( val daysOld = Days.daysBetween(date1.toLocalDate(), date2.toLocalDate()).days if (daysOld > IMPORT_AGE_NOT_YET_OLD_DAYS) { - createdAt.status = PrefsStatus.WARN + createdAt.status = PrefsStatusImpl.WARN createdAt.info = rh.gs(R.string.metadata_warning_old_export, daysOld.toString()) } } catch (e: Exception) { - createdAt.status = PrefsStatus.WARN + createdAt.status = PrefsStatusImpl.WARN createdAt.info = rh.gs(R.string.metadata_warning_date_format) } } - meta[PrefsMetadataKey.AAPS_VERSION]?.let { version -> + meta[PrefsMetadataKeyImpl.AAPS_VERSION]?.let { version -> val currentAppVer = versionCheckerUtils.versionDigits(config.get().VERSION_NAME) val metadataVer = versionCheckerUtils.versionDigits(version.value) if ((currentAppVer.size >= 2) && (metadataVer.size >= 2) && (abs(currentAppVer[1] - metadataVer[1]) > 1)) { - version.status = PrefsStatus.WARN + version.status = PrefsStatusImpl.WARN version.info = rh.gs(R.string.metadata_warning_different_version) } if ((currentAppVer.isNotEmpty()) && (metadataVer.isNotEmpty()) && (currentAppVer[0] != metadataVer[0])) { - version.status = PrefsStatus.WARN + version.status = PrefsStatusImpl.WARN version.info = rh.gs(R.string.metadata_urgent_different_version) } } diff --git a/core/interfaces/src/main/java/info/nightscout/interfaces/maintenance/PrefsFormat.kt b/plugins/configuration/src/main/java/info/nightscout/configuration/maintenance/PrefsMetadataKeyImpl.kt similarity index 52% rename from core/interfaces/src/main/java/info/nightscout/interfaces/maintenance/PrefsFormat.kt rename to plugins/configuration/src/main/java/info/nightscout/configuration/maintenance/PrefsMetadataKeyImpl.kt index 4fbfa1a262..c38853de35 100644 --- a/core/interfaces/src/main/java/info/nightscout/interfaces/maintenance/PrefsFormat.kt +++ b/plugins/configuration/src/main/java/info/nightscout/configuration/maintenance/PrefsMetadataKeyImpl.kt @@ -1,14 +1,13 @@ -package info.nightscout.interfaces.maintenance +package info.nightscout.configuration.maintenance import android.content.Context -import android.os.Parcelable import androidx.annotation.DrawableRes import androidx.annotation.StringRes -import info.nightscout.interfaces.R -import kotlinx.parcelize.Parcelize -import java.io.File +import info.nightscout.configuration.R +import info.nightscout.interfaces.maintenance.PrefsFormat +import info.nightscout.interfaces.maintenance.PrefsMetadataKey -enum class PrefsMetadataKey(val key: String, @DrawableRes val icon: Int, @StringRes val label: Int) { +enum class PrefsMetadataKeyImpl(override val key: String, @DrawableRes override val icon: Int, @StringRes override val label: Int) : PrefsMetadataKey { FILE_FORMAT("format", R.drawable.ic_meta_format, R.string.metadata_label_format), CREATED_AT("created_at", R.drawable.ic_meta_date, R.string.metadata_label_created_at), @@ -35,48 +34,16 @@ enum class PrefsMetadataKey(val key: String, @DrawableRes val icon: Int, @String } - fun formatForDisplay(context: Context, value: String): String { + override fun formatForDisplay(context: Context, value: String): String { return when (this) { FILE_FORMAT -> when (value) { PrefsFormat.FORMAT_KEY_ENC -> context.getString(R.string.metadata_format_new) PrefsFormat.FORMAT_KEY_NOENC -> context.getString(R.string.metadata_format_debug) else -> context.getString(R.string.metadata_format_other) } + CREATED_AT -> value.replace("T", " ").replace("Z", " (UTC)") else -> value } } - } - -@Parcelize -data class PrefMetadata(var value: String, var status: PrefsStatus, var info: String? = null) : Parcelable - -typealias PrefMetadataMap = Map - -data class Prefs(val values: Map, var metadata: PrefMetadataMap) - -interface PrefsFormat { - companion object { - - const val FORMAT_KEY_ENC = "aaps_encrypted" - const val FORMAT_KEY_NOENC = "aaps_structured" - } - - fun savePreferences(file: File, prefs: Prefs, masterPassword: String? = null) - fun loadPreferences(file: File, masterPassword: String? = null): Prefs - fun loadMetadata(contents: String? = null): PrefMetadataMap - fun isPreferencesFile(file: File, preloadedContents: String? = null): Boolean -} - -enum class PrefsStatus(@DrawableRes val icon: Int) { - OK(R.drawable.ic_meta_ok), - WARN(R.drawable.ic_meta_warning), - ERROR(R.drawable.ic_meta_error), - UNKNOWN(R.drawable.ic_meta_error), - DISABLED(R.drawable.ic_meta_error) -} - -class PrefFileNotFoundError(message: String) : Exception(message) -class PrefIOError(message: String) : Exception(message) -class PrefFormatError(message: String) : Exception(message) diff --git a/plugins/configuration/src/main/java/info/nightscout/configuration/maintenance/activities/PrefImportListActivity.kt b/plugins/configuration/src/main/java/info/nightscout/configuration/maintenance/activities/PrefImportListActivity.kt index 8af1fd129d..9cfabb3fce 100644 --- a/plugins/configuration/src/main/java/info/nightscout/configuration/maintenance/activities/PrefImportListActivity.kt +++ b/plugins/configuration/src/main/java/info/nightscout/configuration/maintenance/activities/PrefImportListActivity.kt @@ -12,11 +12,11 @@ import info.nightscout.configuration.R import info.nightscout.configuration.databinding.MaintenanceImportListActivityBinding import info.nightscout.configuration.databinding.MaintenanceImportListItemBinding import info.nightscout.configuration.maintenance.PrefsFileContract +import info.nightscout.configuration.maintenance.PrefsMetadataKeyImpl import info.nightscout.core.ui.activities.TranslatedDaggerAppCompatActivity import info.nightscout.interfaces.maintenance.PrefFileListProvider import info.nightscout.interfaces.maintenance.PrefsFile -import info.nightscout.interfaces.maintenance.PrefsMetadataKey -import info.nightscout.interfaces.maintenance.PrefsStatus +import info.nightscout.interfaces.maintenance.PrefsStatusImpl import info.nightscout.shared.interfaces.ResourceHelper import javax.inject.Inject @@ -82,23 +82,23 @@ class PrefImportListActivity : TranslatedDaggerAppCompatActivity() { metaDateTimeIcon.visibility = View.VISIBLE metaAppVersion.visibility = View.VISIBLE - prefFile.metadata[PrefsMetadataKey.AAPS_FLAVOUR]?.let { + prefFile.metadata[PrefsMetadataKeyImpl.AAPS_FLAVOUR]?.let { metaVariantFormat.text = it.value - val colorAttr = if (it.status == PrefsStatus.OK) info.nightscout.core.ui.R.attr.metadataTextOkColor else info.nightscout.core.ui.R.attr.metadataTextWarningColor + val colorAttr = if (it.status == PrefsStatusImpl.OK) info.nightscout.core.ui.R.attr.metadataTextOkColor else info.nightscout.core.ui.R.attr.metadataTextWarningColor metaVariantFormat.setTextColor(rh.gac(metaVariantFormat.context, colorAttr)) } - prefFile.metadata[PrefsMetadataKey.CREATED_AT]?.let { + prefFile.metadata[PrefsMetadataKeyImpl.CREATED_AT]?.let { metaDateTime.text = prefFileListProvider.formatExportedAgo(it.value) } - prefFile.metadata[PrefsMetadataKey.AAPS_VERSION]?.let { + prefFile.metadata[PrefsMetadataKeyImpl.AAPS_VERSION]?.let { metaAppVersion.text = it.value - val colorAttr = if (it.status == PrefsStatus.OK) info.nightscout.core.ui.R.attr.metadataTextOkColor else info.nightscout.core.ui.R.attr.metadataTextWarningColor + val colorAttr = if (it.status == PrefsStatusImpl.OK) info.nightscout.core.ui.R.attr.metadataTextOkColor else info.nightscout.core.ui.R.attr.metadataTextWarningColor metaAppVersion.setTextColor(rh.gac(metaVariantFormat.context, colorAttr)) } - prefFile.metadata[PrefsMetadataKey.DEVICE_NAME]?.let { + prefFile.metadata[PrefsMetadataKeyImpl.DEVICE_NAME]?.let { metaDeviceName.text = it.value } diff --git a/plugins/configuration/src/main/java/info/nightscout/configuration/maintenance/dialogs/PrefImportSummaryDialog.kt b/plugins/configuration/src/main/java/info/nightscout/configuration/maintenance/dialogs/PrefImportSummaryDialog.kt index e6e1f5010f..d35161898a 100644 --- a/plugins/configuration/src/main/java/info/nightscout/configuration/maintenance/dialogs/PrefImportSummaryDialog.kt +++ b/plugins/configuration/src/main/java/info/nightscout/configuration/maintenance/dialogs/PrefImportSummaryDialog.kt @@ -20,7 +20,7 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder import info.nightscout.configuration.R import info.nightscout.core.ui.toast.ToastUtils import info.nightscout.interfaces.maintenance.Prefs -import info.nightscout.interfaces.maintenance.PrefsStatus +import info.nightscout.interfaces.maintenance.PrefsStatusImpl import info.nightscout.shared.extensions.runOnUiThread import java.util.LinkedList @@ -57,8 +57,8 @@ object PrefImportSummaryDialog { (rowLayout.findViewById(R.id.summary_icon) as ImageView).setImageResource(metaKey.icon) (rowLayout.findViewById(R.id.status_icon) as ImageView).setImageResource(metaEntry.status.icon) - if (metaEntry.status == PrefsStatus.WARN) label.setTextColor(themedCtx.getColor(info.nightscout.interfaces.R.color.metadataTextWarning)) - else if (metaEntry.status == PrefsStatus.ERROR) label.setTextColor(themedCtx.getColor(info.nightscout.interfaces.R.color.metadataTextError)) + if (metaEntry.status == PrefsStatusImpl.WARN) label.setTextColor(themedCtx.getColor(info.nightscout.interfaces.R.color.metadataTextWarning)) + else if (metaEntry.status == PrefsStatusImpl.ERROR) label.setTextColor(themedCtx.getColor(info.nightscout.interfaces.R.color.metadataTextError)) if (metaEntry.info != null) { details.add("${context.getString(metaKey.label)}: ${metaEntry.value}
${metaEntry.info}") @@ -66,9 +66,9 @@ object PrefImportSummaryDialog { rowLayout.setOnClickListener { val msg = "[${context.getString(metaKey.label)}] ${metaEntry.info}" when (metaEntry.status) { - PrefsStatus.WARN -> ToastUtils.Long.warnToast(context, msg) - PrefsStatus.ERROR -> ToastUtils.Long.errorToast(context, msg) - else -> ToastUtils.Long.infoToast(context, msg) + PrefsStatusImpl.WARN -> ToastUtils.Long.warnToast(context, msg) + PrefsStatusImpl.ERROR -> ToastUtils.Long.errorToast(context, msg) + else -> ToastUtils.Long.infoToast(context, msg) } } } else { diff --git a/plugins/configuration/src/main/java/info/nightscout/configuration/maintenance/formats/EncryptedPrefsFormat.kt b/plugins/configuration/src/main/java/info/nightscout/configuration/maintenance/formats/EncryptedPrefsFormat.kt index c1c9d7abab..d11cfa3a39 100644 --- a/plugins/configuration/src/main/java/info/nightscout/configuration/maintenance/formats/EncryptedPrefsFormat.kt +++ b/plugins/configuration/src/main/java/info/nightscout/configuration/maintenance/formats/EncryptedPrefsFormat.kt @@ -1,6 +1,7 @@ package info.nightscout.configuration.maintenance.formats import info.nightscout.configuration.R +import info.nightscout.configuration.maintenance.PrefsMetadataKeyImpl import info.nightscout.core.utils.CryptoUtil import info.nightscout.core.utils.hexStringToByteArray import info.nightscout.core.utils.toHex @@ -13,6 +14,7 @@ import info.nightscout.interfaces.maintenance.Prefs import info.nightscout.interfaces.maintenance.PrefsFormat import info.nightscout.interfaces.maintenance.PrefsMetadataKey import info.nightscout.interfaces.maintenance.PrefsStatus +import info.nightscout.interfaces.maintenance.PrefsStatusImpl import info.nightscout.interfaces.storage.Storage import info.nightscout.shared.interfaces.ResourceHelper import org.json.JSONException @@ -59,8 +61,8 @@ class EncryptedPrefsFormat @Inject constructor( val content = JSONObject() val meta = JSONObject() - val encStatus = prefs.metadata[PrefsMetadataKey.ENCRYPTION]?.status ?: PrefsStatus.OK - var encrypted = encStatus == PrefsStatus.OK && masterPassword != null + val encStatus = prefs.metadata[PrefsMetadataKeyImpl.ENCRYPTION]?.status ?: PrefsStatusImpl.OK + var encrypted = encStatus == PrefsStatusImpl.OK && masterPassword != null try { for ((key, value) in prefs.values.toSortedMap()) { @@ -68,14 +70,14 @@ class EncryptedPrefsFormat @Inject constructor( } for ((metaKey, metaEntry) in prefs.metadata) { - if (metaKey == PrefsMetadataKey.FILE_FORMAT) + if (metaKey == PrefsMetadataKeyImpl.FILE_FORMAT) continue - if (metaKey == PrefsMetadataKey.ENCRYPTION) + if (metaKey == PrefsMetadataKeyImpl.ENCRYPTION) continue meta.put(metaKey.key, metaEntry.value) } - container.put(PrefsMetadataKey.FILE_FORMAT.key, if (encrypted) PrefsFormat.FORMAT_KEY_ENC else PrefsFormat.FORMAT_KEY_NOENC) + container.put(PrefsMetadataKeyImpl.FILE_FORMAT.key, if (encrypted) PrefsFormat.FORMAT_KEY_ENC else PrefsFormat.FORMAT_KEY_NOENC) container.put("metadata", meta) val security = JSONObject() @@ -130,22 +132,22 @@ class EncryptedPrefsFormat @Inject constructor( val container = JSONObject(jsonBody) val metadata: MutableMap = loadMetadata(container) - if (container.has(PrefsMetadataKey.FILE_FORMAT.key) && container.has("security") && container.has("content")) { - val fileFormat = container.getString(PrefsMetadataKey.FILE_FORMAT.key) + if (container.has(PrefsMetadataKeyImpl.FILE_FORMAT.key) && container.has("security") && container.has("content")) { + val fileFormat = container.getString(PrefsMetadataKeyImpl.FILE_FORMAT.key) val security = container.getJSONObject("security") val encrypted = fileFormat == PrefsFormat.FORMAT_KEY_ENC - var secure: PrefsStatus = PrefsStatus.OK + var secure: PrefsStatus = PrefsStatusImpl.OK var decryptedOk = false var contentJsonObj: JSONObject? = null var insecurityReason = rh.gs(R.string.prefdecrypt_settings_tampered) if (security.has("file_hash")) { if (calculatedFileHash != security.getString("file_hash")) { - secure = PrefsStatus.ERROR + secure = PrefsStatusImpl.ERROR issues.add(rh.gs(R.string.prefdecrypt_issue_modified)) } } else { - secure = PrefsStatus.ERROR + secure = PrefsStatusImpl.ERROR issues.add(rh.gs(R.string.prefdecrypt_issue_missing_file_hash)) } @@ -164,38 +166,38 @@ class EncryptedPrefsFormat @Inject constructor( contentJsonObj = JSONObject(decrypted) decryptedOk = true } else { - secure = PrefsStatus.ERROR + secure = PrefsStatusImpl.ERROR issues.add(rh.gs(R.string.prefdecrypt_issue_modified)) } } catch (e: JSONException) { - secure = PrefsStatus.ERROR + secure = PrefsStatusImpl.ERROR issues.add(rh.gs(R.string.prefdecrypt_issue_parsing)) } } else { - secure = PrefsStatus.ERROR + secure = PrefsStatusImpl.ERROR issues.add(rh.gs(R.string.prefdecrypt_issue_wrong_pass)) insecurityReason = rh.gs(R.string.prefdecrypt_wrong_password) } } else { - secure = PrefsStatus.ERROR + secure = PrefsStatusImpl.ERROR issues.add(rh.gs(R.string.prefdecrypt_issue_wrong_format)) } } else { - secure = PrefsStatus.ERROR + secure = PrefsStatusImpl.ERROR issues.add(rh.gs(R.string.prefdecrypt_issue_wrong_algorithm)) } } else { - if (secure == PrefsStatus.OK) { - secure = PrefsStatus.WARN + if (secure == PrefsStatusImpl.OK) { + secure = PrefsStatusImpl.WARN } if (!(security.has("algorithm") && security.get("algorithm") == "none")) { - secure = PrefsStatus.ERROR + secure = PrefsStatusImpl.ERROR issues.add(rh.gs(R.string.prefdecrypt_issue_wrong_algorithm)) } @@ -211,12 +213,12 @@ class EncryptedPrefsFormat @Inject constructor( val issuesStr: String? = if (issues.size > 0) issues.joinToString("\n") else null val encryptionDescStr = if (encrypted) { - if (secure == PrefsStatus.OK) rh.gs(R.string.prefdecrypt_settings_secure) else insecurityReason + if (secure == PrefsStatusImpl.OK) rh.gs(R.string.prefdecrypt_settings_secure) else insecurityReason } else { - if (secure != PrefsStatus.ERROR) rh.gs(R.string.prefdecrypt_settings_unencrypted) else rh.gs(R.string.prefdecrypt_settings_tampered) + if (secure != PrefsStatusImpl.ERROR) rh.gs(R.string.prefdecrypt_settings_unencrypted) else rh.gs(R.string.prefdecrypt_settings_tampered) } - metadata[PrefsMetadataKey.ENCRYPTION] = PrefMetadata(encryptionDescStr, secure, issuesStr) + metadata[PrefsMetadataKeyImpl.ENCRYPTION] = PrefMetadata(encryptionDescStr, secure, issuesStr) } return Prefs(entries, metadata) @@ -243,22 +245,22 @@ class EncryptedPrefsFormat @Inject constructor( private fun loadMetadata(container: JSONObject): MutableMap { val metadata: MutableMap = mutableMapOf() - if (container.has(PrefsMetadataKey.FILE_FORMAT.key) && container.has("security") && container.has("content") && container.has("metadata")) { - val fileFormat = container.getString(PrefsMetadataKey.FILE_FORMAT.key) + if (container.has(PrefsMetadataKeyImpl.FILE_FORMAT.key) && container.has("security") && container.has("content") && container.has("metadata")) { + val fileFormat = container.getString(PrefsMetadataKeyImpl.FILE_FORMAT.key) if ((fileFormat != PrefsFormat.FORMAT_KEY_ENC) && (fileFormat != PrefsFormat.FORMAT_KEY_NOENC)) { - metadata[PrefsMetadataKey.FILE_FORMAT] = PrefMetadata(rh.gs(info.nightscout.interfaces.R.string.metadata_format_other), PrefsStatus.ERROR) + metadata[PrefsMetadataKeyImpl.FILE_FORMAT] = PrefMetadata(rh.gs(R.string.metadata_format_other), PrefsStatusImpl.ERROR) } else { val meta = container.getJSONObject("metadata") - metadata[PrefsMetadataKey.FILE_FORMAT] = PrefMetadata(fileFormat, PrefsStatus.OK) + metadata[PrefsMetadataKeyImpl.FILE_FORMAT] = PrefMetadata(fileFormat, PrefsStatusImpl.OK) for (key in meta.keys()) { - val metaKey = PrefsMetadataKey.fromKey(key) + val metaKey = PrefsMetadataKeyImpl.fromKey(key) if (metaKey != null) { - metadata[metaKey] = PrefMetadata(meta.getString(key), PrefsStatus.OK) + metadata[metaKey] = PrefMetadata(meta.getString(key), PrefsStatusImpl.OK) } } } } else { - metadata[PrefsMetadataKey.FILE_FORMAT] = PrefMetadata(rh.gs(R.string.prefdecrypt_wrong_json), PrefsStatus.ERROR) + metadata[PrefsMetadataKeyImpl.FILE_FORMAT] = PrefMetadata(rh.gs(R.string.prefdecrypt_wrong_json), PrefsStatusImpl.ERROR) } return metadata diff --git a/plugins/configuration/src/main/java/info/nightscout/interfaces/maintenance/PrefsFormat.kt b/plugins/configuration/src/main/java/info/nightscout/interfaces/maintenance/PrefsFormat.kt new file mode 100644 index 0000000000..41218068a3 --- /dev/null +++ b/plugins/configuration/src/main/java/info/nightscout/interfaces/maintenance/PrefsFormat.kt @@ -0,0 +1,37 @@ +package info.nightscout.interfaces.maintenance + +import androidx.annotation.DrawableRes +import info.nightscout.configuration.R +import kotlinx.parcelize.Parcelize +import java.io.File + +typealias PrefMetadataMap = Map + +data class Prefs(val values: Map, var metadata: PrefMetadataMap) + +interface PrefsFormat { + companion object { + + const val FORMAT_KEY_ENC = "aaps_encrypted" + const val FORMAT_KEY_NOENC = "aaps_structured" + } + + fun savePreferences(file: File, prefs: Prefs, masterPassword: String? = null) + fun loadPreferences(file: File, masterPassword: String? = null): Prefs + fun loadMetadata(contents: String? = null): PrefMetadataMap + fun isPreferencesFile(file: File, preloadedContents: String? = null): Boolean +} + +@Parcelize +enum class PrefsStatusImpl(@DrawableRes override val icon: Int) : PrefsStatus { + + OK(R.drawable.ic_meta_ok), + WARN(R.drawable.ic_meta_warning), + ERROR(R.drawable.ic_meta_error), + UNKNOWN(R.drawable.ic_meta_error), + DISABLED(R.drawable.ic_meta_error) +} + +class PrefFileNotFoundError(message: String) : Exception(message) +class PrefIOError(message: String) : Exception(message) +class PrefFormatError(message: String) : Exception(message) diff --git a/core/interfaces/src/main/res/drawable/ic_meta_date.xml b/plugins/configuration/src/main/res/drawable/ic_meta_date.xml similarity index 100% rename from core/interfaces/src/main/res/drawable/ic_meta_date.xml rename to plugins/configuration/src/main/res/drawable/ic_meta_date.xml diff --git a/core/interfaces/src/main/res/drawable/ic_meta_encryption.xml b/plugins/configuration/src/main/res/drawable/ic_meta_encryption.xml similarity index 100% rename from core/interfaces/src/main/res/drawable/ic_meta_encryption.xml rename to plugins/configuration/src/main/res/drawable/ic_meta_encryption.xml diff --git a/core/interfaces/src/main/res/drawable/ic_meta_error.xml b/plugins/configuration/src/main/res/drawable/ic_meta_error.xml similarity index 100% rename from core/interfaces/src/main/res/drawable/ic_meta_error.xml rename to plugins/configuration/src/main/res/drawable/ic_meta_error.xml diff --git a/core/interfaces/src/main/res/drawable/ic_meta_flavour.xml b/plugins/configuration/src/main/res/drawable/ic_meta_flavour.xml similarity index 100% rename from core/interfaces/src/main/res/drawable/ic_meta_flavour.xml rename to plugins/configuration/src/main/res/drawable/ic_meta_flavour.xml diff --git a/core/interfaces/src/main/res/drawable/ic_meta_format.xml b/plugins/configuration/src/main/res/drawable/ic_meta_format.xml similarity index 100% rename from core/interfaces/src/main/res/drawable/ic_meta_format.xml rename to plugins/configuration/src/main/res/drawable/ic_meta_format.xml diff --git a/core/interfaces/src/main/res/drawable/ic_meta_model.xml b/plugins/configuration/src/main/res/drawable/ic_meta_model.xml similarity index 100% rename from core/interfaces/src/main/res/drawable/ic_meta_model.xml rename to plugins/configuration/src/main/res/drawable/ic_meta_model.xml diff --git a/core/interfaces/src/main/res/drawable/ic_meta_name.xml b/plugins/configuration/src/main/res/drawable/ic_meta_name.xml similarity index 100% rename from core/interfaces/src/main/res/drawable/ic_meta_name.xml rename to plugins/configuration/src/main/res/drawable/ic_meta_name.xml diff --git a/core/interfaces/src/main/res/drawable/ic_meta_ok.xml b/plugins/configuration/src/main/res/drawable/ic_meta_ok.xml similarity index 100% rename from core/interfaces/src/main/res/drawable/ic_meta_ok.xml rename to plugins/configuration/src/main/res/drawable/ic_meta_ok.xml diff --git a/core/interfaces/src/main/res/drawable/ic_meta_version.xml b/plugins/configuration/src/main/res/drawable/ic_meta_version.xml similarity index 100% rename from core/interfaces/src/main/res/drawable/ic_meta_version.xml rename to plugins/configuration/src/main/res/drawable/ic_meta_version.xml diff --git a/core/interfaces/src/main/res/drawable/ic_meta_warning.xml b/plugins/configuration/src/main/res/drawable/ic_meta_warning.xml similarity index 100% rename from core/interfaces/src/main/res/drawable/ic_meta_warning.xml rename to plugins/configuration/src/main/res/drawable/ic_meta_warning.xml diff --git a/plugins/configuration/src/main/res/values/strings.xml b/plugins/configuration/src/main/res/values/strings.xml index b66f4f8039..a87c290175 100644 --- a/plugins/configuration/src/main/res/values/strings.xml +++ b/plugins/configuration/src/main/res/values/strings.xml @@ -170,4 +170,16 @@ Please reboot your phone or restart AAPS from the System Settings \notherwise Android APS will not have logging (important to track and verify that the algorithms are working correctly)! + + File format + Created at + AAPS Version + Build Variant + Exporting device patient name + Exporting device model + File encryption + New encrypted format + New debug format (unencrypted) + Unknown export format +
\ No newline at end of file diff --git a/ui/src/main/java/info/nightscout/ui/activities/fragments/TreatmentsUserEntryFragment.kt b/ui/src/main/java/info/nightscout/ui/activities/fragments/TreatmentsUserEntryFragment.kt index 6b797c5b42..03c0265a4b 100644 --- a/ui/src/main/java/info/nightscout/ui/activities/fragments/TreatmentsUserEntryFragment.kt +++ b/ui/src/main/java/info/nightscout/ui/activities/fragments/TreatmentsUserEntryFragment.kt @@ -120,7 +120,7 @@ class TreatmentsUserEntryFragment : DaggerFragment(), MenuProvider { _binding = null } - inner class UserEntryAdapter internal constructor(var entries: List) : RecyclerView.Adapter() { + inner class UserEntryAdapter internal constructor(private var entries: List) : RecyclerView.Adapter() { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): UserEntryViewHolder { val view: View = LayoutInflater.from(parent.context).inflate(R.layout.treatments_user_entry_item, parent, false)