diff --git a/app-wear-shared/shared/src/main/java/info/nightscout/rx/weardata/CustomWatchfaceFormat.kt b/app-wear-shared/shared/src/main/java/info/nightscout/rx/weardata/CustomWatchfaceFormat.kt index f245b7d8bd..8fb98bdd38 100644 --- a/app-wear-shared/shared/src/main/java/info/nightscout/rx/weardata/CustomWatchfaceFormat.kt +++ b/app-wear-shared/shared/src/main/java/info/nightscout/rx/weardata/CustomWatchfaceFormat.kt @@ -96,8 +96,21 @@ enum class CustomWatchfaceMetadataKey(val key: String, @StringRes val label: Int CWF_CREATED_AT("created_at", R.string.metadata_label_watchface_created_at), CWF_VERSION("cwf_version", R.string.metadata_label_plugin_version), CWF_AUTHOR_VERSION("author_version", R.string.metadata_label_watchface_name_version), - CWF_COMMENT("comment", R.string.metadata_label_watchface_comment); // label not planed to be used for CWF_COMMENT - + CWF_COMMENT("comment", R.string.metadata_label_watchface_comment), // label not planed to be used for CWF_COMMENT + CWF_AUTHORIZATION("cwf_authorization", R.string.metadata_label_watchface_authorization), + CWF_PREF_AAPS_DETAILED_IOB("key_wear_detailediob", R.string.metadata_label_watchface_pref), + CWF_PREF_AAPS_DETAILED_DELTA("key_wear_detailed_delta", R.string.metadata_label_watchface_pref), + CWF_PREF_AAPS_BGI("key_wear_showbgi", R.string.metadata_label_watchface_pref), + CWF_PREF_WATCH_SHOW_IOB("key_show_iob", R.string.metadata_label_watchface_pref), + CWF_PREF_WATCH_SHOW_COB("key_show_cob", R.string.metadata_label_watchface_pref), + CWF_PREF_WATCH_SHOW_DELTA("key_show_delta", R.string.metadata_label_watchface_pref), + CWF_PREF_WATCH_SHOW_AVG_DELTA("key_show_avg_delta", R.string.metadata_label_watchface_pref), + CWF_PREF_WATCH_SHOW_UPLOADER_BATTERY("key_show_uploader_battery", R.string.metadata_label_watchface_pref), + CWF_PREF_WATCH_SHOW_RIG_BATTERY("key_show_rig_battery", R.string.metadata_label_watchface_pref), + CWF_PREF_WATCH_SHOW_TEMP_BASAL("key_show_temp_basal", R.string.metadata_label_watchface_pref), + CWF_PREF_WATCH_SHOW_DIRECTION("key_show_direction", R.string.metadata_label_watchface_pref), + CWF_PREF_WATCH_SHOW_AGO("key_show_ago", R.string.metadata_label_watchface_pref), + CWF_PREF_WATCH_SHOW_BG("key_show_bg", R.string.metadata_label_watchface_pref); companion object { fun fromKey(key: String): CustomWatchfaceMetadataKey? = values().firstOrNull { it.key == key } @@ -110,7 +123,7 @@ class ZipWatchfaceFormat { const val CUSTOM_WF_EXTENTION = ".zip" const val CUSTOM_JSON_FILE = "CustomWatchface.json" - fun loadCustomWatchface(cwfFile: File): CustomWatchfaceData? { + fun loadCustomWatchface(cwfFile: File, authorization: Boolean): CustomWatchfaceData? { var json = JSONObject() var metadata: CustomWatchfaceMetadataMap = mutableMapOf() val drawableDatas: CustomWatchfaceDrawableDataMap = mutableMapOf() @@ -135,6 +148,7 @@ class ZipWatchfaceFormat { json = JSONObject(jsonString) metadata = loadMetadata(json) metadata[CustomWatchfaceMetadataKey.CWF_FILENAME] = cwfFile.name + metadata[CustomWatchfaceMetadataKey.CWF_AUTHORIZATION] = authorization.toString() } else { val customWatchfaceDrawableDataKey = CustomWatchfaceDrawableDataKey.fromFileName(entryName) val drawableFormat = DrawableFormat.fromFileName(entryName) diff --git a/app-wear-shared/shared/src/main/res/values/strings.xml b/app-wear-shared/shared/src/main/res/values/strings.xml index fc45439638..2aa54ab4c3 100644 --- a/app-wear-shared/shared/src/main/res/values/strings.xml +++ b/app-wear-shared/shared/src/main/res/values/strings.xml @@ -47,6 +47,8 @@ Plugin version: %1$s Name: %1$s (%2$s) %1$s + %1$s + %1$s Default watchface, you can click on EXPORT WATCHFACE button to generate a template Default Watchface diff --git a/core/utils/src/main/res/values/keys.xml b/core/utils/src/main/res/values/keys.xml index 0698dc1ff8..682b40f85d 100644 --- a/core/utils/src/main/res/values/keys.xml +++ b/core/utils/src/main/res/values/keys.xml @@ -115,6 +115,7 @@ wearwizard_trend wearwizard_cob wearwizard_iob + wear_custom_watchface_autorization ObjectivesbgIsAvailableInNS ObjectivespumpStatusIsAvailableInNS statuslights_cage_warning 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 8c546c0bd1..64d8979f7c 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 @@ -20,6 +20,7 @@ import info.nightscout.interfaces.versionChecker.VersionCheckerUtils import info.nightscout.rx.weardata.CustomWatchfaceData import info.nightscout.rx.weardata.ZipWatchfaceFormat import info.nightscout.shared.interfaces.ResourceHelper +import info.nightscout.shared.sharedPreferences.SP import org.joda.time.DateTime import org.joda.time.Days import org.joda.time.Hours @@ -38,6 +39,7 @@ class PrefFileListProviderImpl @Inject constructor( private val encryptedPrefsFormat: EncryptedPrefsFormat, private val storage: Storage, private val versionCheckerUtils: VersionCheckerUtils, + private val sp: SP, context: Context ) : PrefFileListProvider { private val path = File(Environment.getExternalStorageDirectory().toString()) @@ -92,11 +94,11 @@ class PrefFileListProviderImpl @Inject constructor( override fun listCustomWatchfaceFiles(): MutableList { val customWatchfaceFiles = mutableListOf() - + val customAwtchfaceAuthorization = sp.getBoolean(info.nightscout.core.utils.R.string.key_wear_custom_watchface_autorization, false) // searching dedicated dir, only for new CWF format exportsPath.walk().filter { it.isFile && it.name.endsWith(ZipWatchfaceFormat.CUSTOM_WF_EXTENTION) }.forEach { file -> // Here loadCustomWatchface will unzip, check and load CustomWatchface - ZipWatchfaceFormat.loadCustomWatchface(file)?.also { customWatchface -> + ZipWatchfaceFormat.loadCustomWatchface(file, customAwtchfaceAuthorization)?.also { customWatchface -> customWatchfaceFiles.add(customWatchface) } } diff --git a/plugins/main/src/main/java/info/nightscout/plugins/general/wear/WearFragment.kt b/plugins/main/src/main/java/info/nightscout/plugins/general/wear/WearFragment.kt index 3d043707e2..ad4c705f36 100644 --- a/plugins/main/src/main/java/info/nightscout/plugins/general/wear/WearFragment.kt +++ b/plugins/main/src/main/java/info/nightscout/plugins/general/wear/WearFragment.kt @@ -4,6 +4,7 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.annotation.StringRes import dagger.android.support.DaggerFragment import info.nightscout.core.ui.toast.ToastUtils import info.nightscout.core.utils.fabric.FabricPrivacy @@ -12,7 +13,6 @@ import info.nightscout.plugins.R import info.nightscout.plugins.databinding.WearFragmentBinding import info.nightscout.rx.AapsSchedulers import info.nightscout.rx.bus.RxBus -import info.nightscout.rx.events.EventMobileDataToWear import info.nightscout.rx.events.EventMobileToWear import info.nightscout.rx.events.EventWearUpdateGui import info.nightscout.rx.logging.AAPSLogger @@ -105,6 +105,7 @@ class WearFragment : DaggerFragment() { private fun updateGui() { _binding ?: return wearPlugin.savedCustomWatchface?.let { + wearPlugin.checkCustomWatchfacePreferences() binding.customName.text = rh.gs(R.string.wear_custom_watchface, it.metadata[CustomWatchfaceMetadataKey.CWF_NAME]) binding.coverChart.setImageDrawable(it.drawableDatas[CustomWatchfaceDrawableDataKey.CUSTOM_WATCHFACE]?.toDrawable(resources)) } ?:apply { @@ -118,4 +119,11 @@ class WearFragment : DaggerFragment() { private fun loadCustom(cwf: CustomWatchfaceData) { wearPlugin.savedCustomWatchface = cwf } + + // This class containt mapping between keys used within json of Custom Watchface and preferences + enum class PrefMap(val key: String, @StringRes val prefKey: Int) { + DETAILED_IOB(CustomWatchfaceMetadataKey.CWF_PREF_AAPS_DETAILED_IOB.key, info.nightscout.core.utils.R.string.key_wear_detailediob), + CWF_PREF_AAPS_DETAILED_DELTA(CustomWatchfaceMetadataKey.CWF_PREF_AAPS_DETAILED_DELTA.key, info.nightscout.core.utils.R.string.key_wear_detailed_delta), + CWF_PREF_AAPS_BGI(CustomWatchfaceMetadataKey.CWF_PREF_AAPS_BGI.key, info.nightscout.core.utils.R.string.key_wear_showbgi) + } } \ No newline at end of file diff --git a/plugins/main/src/main/java/info/nightscout/plugins/general/wear/WearPlugin.kt b/plugins/main/src/main/java/info/nightscout/plugins/general/wear/WearPlugin.kt index bc7ecf84a6..5b4e1e797f 100644 --- a/plugins/main/src/main/java/info/nightscout/plugins/general/wear/WearPlugin.kt +++ b/plugins/main/src/main/java/info/nightscout/plugins/general/wear/WearPlugin.kt @@ -14,12 +14,14 @@ import info.nightscout.rx.bus.RxBus import info.nightscout.rx.events.EventAutosensCalculationFinished import info.nightscout.rx.events.EventDismissBolusProgressIfRunning import info.nightscout.rx.events.EventLoopUpdateGui +import info.nightscout.rx.events.EventMobileDataToWear import info.nightscout.rx.events.EventMobileToWear import info.nightscout.rx.events.EventOverviewBolusProgress import info.nightscout.rx.events.EventPreferenceChange import info.nightscout.rx.events.EventWearUpdateGui import info.nightscout.rx.logging.AAPSLogger import info.nightscout.rx.weardata.CustomWatchfaceData +import info.nightscout.rx.weardata.CustomWatchfaceMetadataKey import info.nightscout.rx.weardata.EventData import info.nightscout.shared.interfaces.ResourceHelper import info.nightscout.shared.sharedPreferences.SP @@ -83,7 +85,10 @@ class WearPlugin @Inject constructor( disposable += rxBus .toObservable(EventPreferenceChange::class.java) .observeOn(aapsSchedulers.io) - .subscribe({ dataHandlerMobile.resendData("EventPreferenceChange") }, fabricPrivacy::logException) + .subscribe({ + dataHandlerMobile.resendData("EventPreferenceChange") + checkCustomWatchfacePreferences() + }, fabricPrivacy::logException) disposable += rxBus .toObservable(EventAutosensCalculationFinished::class.java) .observeOn(aapsSchedulers.io) @@ -95,7 +100,31 @@ class WearPlugin @Inject constructor( disposable += rxBus .toObservable(EventWearUpdateGui::class.java) .observeOn(aapsSchedulers.main) - .subscribe({ it.customWatchfaceData?.let { cwf -> if (!it.exportFile) savedCustomWatchface = cwf } }, fabricPrivacy::logException) + .subscribe({ + it.customWatchfaceData?.let { cwf -> + if (!it.exportFile) { + savedCustomWatchface = cwf + checkCustomWatchfacePreferences() + } + } + }, fabricPrivacy::logException) + } + + fun checkCustomWatchfacePreferences() { + savedCustomWatchface?.let { cwf -> + val cwf_authorization = sp.getBoolean(info.nightscout.core.utils.R.string.key_wear_custom_watchface_autorization, false) + if (cwf_authorization != cwf.metadata[CustomWatchfaceMetadataKey.CWF_AUTHORIZATION]?.toBooleanStrictOrNull()) { + // resend new customWatchface to Watch with updated authorization for preferences update + val newCwf = cwf.copy() + newCwf.metadata[CustomWatchfaceMetadataKey.CWF_AUTHORIZATION] = sp.getBoolean(info.nightscout.core.utils.R.string.key_wear_custom_watchface_autorization, false).toString() + rxBus.send(EventMobileDataToWear(EventData.ActionSetCustomWatchface(newCwf))) + } + if (cwf_authorization) { + WearFragment.PrefMap.values().forEach { pref -> + cwf.metadata[CustomWatchfaceMetadataKey.fromKey(pref.key)]?.toBooleanStrictOrNull()?.let { sp.putBoolean(pref.prefKey, it) } + } + } + } } override fun onStop() { diff --git a/plugins/main/src/main/res/values/strings.xml b/plugins/main/src/main/res/values/strings.xml index 69dae93b81..0c5bbd43b5 100644 --- a/plugins/main/src/main/res/values/strings.xml +++ b/plugins/main/src/main/res/values/strings.xml @@ -361,6 +361,9 @@ Show SMB on the watch like a standard bolus. Show the predictions on the watchface. Predictions + Custom Watchface Settings + Custom Watchface Authorization + Authorize loaded Custom Watchface to modify AAPS and Watch settings according to the watchface design Custom Watchface: %1$s Load Watchface Send Watchface diff --git a/plugins/main/src/main/res/xml/pref_wear.xml b/plugins/main/src/main/res/xml/pref_wear.xml index d2857d0349..cbbd152443 100644 --- a/plugins/main/src/main/res/xml/pref_wear.xml +++ b/plugins/main/src/main/res/xml/pref_wear.xml @@ -78,6 +78,17 @@ + + + + + + diff --git a/wear/src/main/java/info/nightscout/androidaps/watchfaces/CustomWatchface.kt b/wear/src/main/java/info/nightscout/androidaps/watchfaces/CustomWatchface.kt index 416ed94890..bbfce2c5f4 100644 --- a/wear/src/main/java/info/nightscout/androidaps/watchfaces/CustomWatchface.kt +++ b/wear/src/main/java/info/nightscout/androidaps/watchfaces/CustomWatchface.kt @@ -37,6 +37,7 @@ import info.nightscout.rx.weardata.CustomWatchfaceData import info.nightscout.rx.weardata.CustomWatchfaceDrawableDataKey import info.nightscout.rx.weardata.CustomWatchfaceDrawableDataMap import info.nightscout.rx.weardata.CustomWatchfaceMetadataKey +import info.nightscout.rx.weardata.CustomWatchfaceMetadataMap import info.nightscout.rx.weardata.DrawableData import info.nightscout.rx.weardata.DrawableFormat import info.nightscout.rx.weardata.EventData @@ -140,6 +141,7 @@ class CustomWatchface : BaseWatchFace() { private fun setWatchfaceStyle() { val customWatchface = persistence.readCustomWatchface() ?: persistence.readCustomWatchface(true) customWatchface?.let { + updatePref(it.customWatchfaceData.metadata) try { val json = JSONObject(it.customWatchfaceData.json) val drawableDataMap = it.customWatchfaceData.drawableDatas @@ -231,6 +233,17 @@ class CustomWatchface : BaseWatchFace() { } } + private fun updatePref(metadata: CustomWatchfaceMetadataMap) { + val cwf_authorization = metadata[CustomWatchfaceMetadataKey.CWF_AUTHORIZATION]?.toBooleanStrictOrNull() + cwf_authorization?.let { authorization -> + if (authorization) { + PrefMap.values().forEach { pref -> + metadata[CustomWatchfaceMetadataKey.fromKey(pref.key)]?.toBooleanStrictOrNull()?.let { sp.putBoolean(pref.prefKey, it) } + } + } + } + } + private fun defaultWatchface(): EventData.ActionSetCustomWatchface { val metadata = JSONObject() .put(CustomWatchfaceMetadataKey.CWF_NAME.key, getString(info.nightscout.shared.R.string.wear_default_watchface)) @@ -476,4 +489,18 @@ class CustomWatchface : BaseWatchFace() { } } + // This class containt mapping between keys used within json of Custom Watchface and preferences + private enum class PrefMap(val key: String, @StringRes val prefKey: Int) { + SHOW_IOB(CustomWatchfaceMetadataKey.CWF_PREF_WATCH_SHOW_IOB.key, R.string.key_show_iob), + SHOW_COB(CustomWatchfaceMetadataKey.CWF_PREF_WATCH_SHOW_COB.key, R.string.key_show_cob), + SHOW_DELTA(CustomWatchfaceMetadataKey.CWF_PREF_WATCH_SHOW_DELTA.key, R.string.key_show_delta), + SHOW_AVG_DELTA(CustomWatchfaceMetadataKey.CWF_PREF_WATCH_SHOW_AVG_DELTA.key, R.string.key_show_avg_delta), + SHOW_UPLOADER_BATTERY(CustomWatchfaceMetadataKey.CWF_PREF_WATCH_SHOW_UPLOADER_BATTERY.key, R.string.key_show_uploader_battery), + SHOW_RIG_BATTERY(CustomWatchfaceMetadataKey.CWF_PREF_WATCH_SHOW_RIG_BATTERY.key, R.string.key_show_rig_battery), + SHOW_TEMP_BASAL(CustomWatchfaceMetadataKey.CWF_PREF_WATCH_SHOW_TEMP_BASAL.key, R.string.key_show_temp_basal), + SHOW_DIRECTION(CustomWatchfaceMetadataKey.CWF_PREF_WATCH_SHOW_DIRECTION.key, R.string.key_show_direction), + SHOW_AGO(CustomWatchfaceMetadataKey.CWF_PREF_WATCH_SHOW_AGO.key, R.string.key_show_ago), + SHOW_BG(CustomWatchfaceMetadataKey.CWF_PREF_WATCH_SHOW_BG.key, R.string.key_show_bg) + } + }