From aa85b4f17313b825649fbc6ad1b222bf69b8e9ee Mon Sep 17 00:00:00 2001 From: Philoul Date: Sat, 9 Sep 2023 19:11:49 +0200 Subject: [PATCH] Wear CWF Refactor to allow more flexibility in additional resources --- .../rx/weardata/CustomWatchfaceFormat.kt | 23 +++----- .../CustomWatchfaceImportListActivity.kt | 2 +- .../plugins/general/wear/WearFragment.kt | 2 +- .../wear/activities/CwfInfosActivity.kt | 2 +- .../androidaps/watchfaces/CustomWatchface.kt | 56 +++++++++---------- 5 files changed, 38 insertions(+), 47 deletions(-) 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 35a30a9f7f..6b104b1355 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 @@ -50,11 +50,7 @@ enum class ResFileMap(val fileName: String) { ARROW_FLAT("ArrowFlat"), ARROW_FORTY_FIVE_DOWN("Arrow45Down"), ARROW_SINGLE_DOWN("ArrowSingleDown"), - ARROW_DOUBLE_DOWN("ArrowDoubleDown"), - FONT1("Font1"), - FONT2("Font2"), - FONT3("Font3"), - FONT4("Font4"); + ARROW_DOUBLE_DOWN("ArrowDoubleDown"); companion object { @@ -134,7 +130,7 @@ data class ResData(val value: ByteArray, val format: ResFormat) { } } -typealias CwfResDataMap = MutableMap +typealias CwfResDataMap = MutableMap typealias CwfMetadataMap = MutableMap @Serializable @@ -259,11 +255,7 @@ enum class JsonKeyValues(val key: String, val jsonKey: JsonKeys) { BOLD("bold", JsonKeys.FONTSTYLE), BOLD_ITALIC("bold_italic", JsonKeys.FONTSTYLE), ITALIC("italic", JsonKeys.FONTSTYLE), - BGCOLOR("bgColor", JsonKeys.COLOR), - FONT1("font1", JsonKeys.FONTCOLOR), - FONT2("font2", JsonKeys.FONTCOLOR), - FONT3("font3", JsonKeys.FONTCOLOR), - FONT4("font4", JsonKeys.FONTCOLOR) + BGCOLOR("bgColor", JsonKeys.COLOR) } enum class ViewType(@StringRes val comment: Int?) { @@ -309,14 +301,15 @@ class ZipWatchfaceFormat { val cwfResFileMap = ResFileMap.fromFileName(entryName) val drawableFormat = ResFormat.fromFileName(entryName) if (cwfResFileMap != ResFileMap.UNKNOWN && drawableFormat != ResFormat.UNKNOWN) { - resDatas[cwfResFileMap] = ResData(byteArrayOutputStream.toByteArray(), drawableFormat) - } + resDatas[cwfResFileMap.fileName] = ResData(byteArrayOutputStream.toByteArray(), drawableFormat) + } else if (drawableFormat != ResFormat.UNKNOWN) + resDatas[entryName.substringBeforeLast(".")] = ResData(byteArrayOutputStream.toByteArray(), drawableFormat) } zipEntry = zipInputStream.nextEntry } // Valid CWF file must contains a valid json file with a name within metadata and a custom watchface image - return if (metadata.containsKey(CwfMetadataKey.CWF_NAME) && resDatas.containsKey(ResFileMap.CUSTOM_WATCHFACE)) + return if (metadata.containsKey(CwfMetadataKey.CWF_NAME) && resDatas.containsKey(ResFileMap.CUSTOM_WATCHFACE.fileName)) CwfData(json.toString(4), metadata, resDatas) else null @@ -338,7 +331,7 @@ class ZipWatchfaceFormat { zipOutputStream.closeEntry() for (resData in customWatchface.resDatas) { - val fileEntry = ZipEntry("${resData.key.fileName}.${resData.value.format.extension}") + val fileEntry = ZipEntry("${resData.key}.${resData.value.format.extension}") zipOutputStream.putNextEntry(fileEntry) zipOutputStream.write(resData.value.value) zipOutputStream.closeEntry() diff --git a/plugins/configuration/src/main/java/info/nightscout/configuration/maintenance/activities/CustomWatchfaceImportListActivity.kt b/plugins/configuration/src/main/java/info/nightscout/configuration/maintenance/activities/CustomWatchfaceImportListActivity.kt index 5c6ad810e5..d8bc43c362 100644 --- a/plugins/configuration/src/main/java/info/nightscout/configuration/maintenance/activities/CustomWatchfaceImportListActivity.kt +++ b/plugins/configuration/src/main/java/info/nightscout/configuration/maintenance/activities/CustomWatchfaceImportListActivity.kt @@ -89,7 +89,7 @@ class CustomWatchfaceImportListActivity: TranslatedDaggerAppCompatActivity() { override fun onBindViewHolder(holder: CwfFileViewHolder, position: Int) { val customWatchfaceFile = customWatchfaceFileList[position] val metadata = customWatchfaceFile.metadata - val drawable = customWatchfaceFile.resDatas[ResFileMap.CUSTOM_WATCHFACE]?.toDrawable(resources) + val drawable = customWatchfaceFile.resDatas[ResFileMap.CUSTOM_WATCHFACE.fileName]?.toDrawable(resources) with(holder.customWatchfaceImportListItemBinding) { filelistName.text = rh.gs(info.nightscout.shared.R.string.metadata_wear_import_filename, metadata[CWF_FILENAME]) filelistName.tag = customWatchfaceFile 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 d0aebce9af..e9aa8f6987 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 @@ -111,7 +111,7 @@ class WearFragment : DaggerFragment() { wearPlugin.savedCustomWatchface?.let { wearPlugin.checkCustomWatchfacePreferences() binding.customName.text = rh.gs(R.string.wear_custom_watchface, it.metadata[CwfMetadataKey.CWF_NAME]) - binding.coverChart.setImageDrawable(it.resDatas[ResFileMap.CUSTOM_WATCHFACE]?.toDrawable(resources)) + binding.coverChart.setImageDrawable(it.resDatas[ResFileMap.CUSTOM_WATCHFACE.fileName]?.toDrawable(resources)) binding.infosCustom.visibility = View.VISIBLE } ?:apply { binding.customName.text = rh.gs(R.string.wear_custom_watchface, "") diff --git a/plugins/main/src/main/java/info/nightscout/plugins/general/wear/activities/CwfInfosActivity.kt b/plugins/main/src/main/java/info/nightscout/plugins/general/wear/activities/CwfInfosActivity.kt index 5b9404709d..ce414654ee 100644 --- a/plugins/main/src/main/java/info/nightscout/plugins/general/wear/activities/CwfInfosActivity.kt +++ b/plugins/main/src/main/java/info/nightscout/plugins/general/wear/activities/CwfInfosActivity.kt @@ -86,7 +86,7 @@ class CwfInfosActivity : TranslatedDaggerAppCompatActivity() { wearPlugin.savedCustomWatchface?.let { val cwfAuthorization = sp.getBoolean(info.nightscout.core.utils.R.string.key_wear_custom_watchface_autorization, false) val metadata = it.metadata - val drawable = it.resDatas[ResFileMap.CUSTOM_WATCHFACE]?.toDrawable(resources) + val drawable = it.resDatas[ResFileMap.CUSTOM_WATCHFACE.fileName]?.toDrawable(resources) binding.customWatchface.setImageDrawable(drawable) title = rh.gs(CwfMetadataKey.CWF_NAME.label, metadata[CwfMetadataKey.CWF_NAME]) metadata[CwfMetadataKey.CWF_AUTHOR_VERSION]?.let { authorVersion -> 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 4aab760bc1..08103d262e 100644 --- a/wear/src/main/java/info/nightscout/androidaps/watchfaces/CustomWatchface.kt +++ b/wear/src/main/java/info/nightscout/androidaps/watchfaces/CustomWatchface.kt @@ -301,7 +301,7 @@ class CustomWatchface : BaseWatchFace() { val metadataMap = ZipWatchfaceFormat.loadMetadata(json) val drawableDataMap: CwfResDataMap = mutableMapOf() getResourceByteArray(info.nightscout.shared.R.drawable.watchface_custom)?.let { - drawableDataMap[ResFileMap.CUSTOM_WATCHFACE] = ResData(it, ResFormat.PNG) + drawableDataMap[ResFileMap.CUSTOM_WATCHFACE.fileName] = ResData(it, ResFormat.PNG) } return EventData.ActionSetCustomWatchface(CwfData(json.toString(4), metadataMap, drawableDataMap)) } @@ -489,10 +489,10 @@ class CustomWatchface : BaseWatchFace() { fun drawable(resources: Resources, drawableDataMap: CwfResDataMap, sgvLevel: Long): Drawable? = customDrawable?.let { cd -> when (sgvLevel) { - 1L -> { drawableDataMap[customHigh]?.toDrawable(resources) ?: drawableDataMap[cd]?.toDrawable(resources) } - 0L -> { drawableDataMap[cd]?.toDrawable(resources) } - -1L -> { drawableDataMap[customLow]?.toDrawable(resources) ?: drawableDataMap[cd]?.toDrawable(resources) } - else -> drawableDataMap[cd]?.toDrawable(resources) + 1L -> { customHigh?.let {drawableDataMap[customHigh.fileName]}?.toDrawable(resources) ?: drawableDataMap[cd.fileName]?.toDrawable(resources) } + 0L -> { drawableDataMap[cd.fileName]?.toDrawable(resources) } + -1L -> { customLow?.let {drawableDataMap[customLow.fileName]}?.toDrawable(resources) ?: drawableDataMap[cd.fileName]?.toDrawable(resources) } + else -> drawableDataMap[cd.fileName]?.toDrawable(resources) } } } @@ -514,7 +514,7 @@ private enum class TrendArrowMap(val symbol: String, @DrawableRes val icon: Int, fun drawable(direction: String?, resources: Resources, drawableDataMap: CwfResDataMap): Drawable { val arrow = values().firstOrNull { it.symbol == direction } ?:NONE - return drawableDataMap[arrow.customDrawable]?.toDrawable(resources) ?:resources.getDrawable(arrow.icon) + return arrow.customDrawable?. let {drawableDataMap[arrow.customDrawable.fileName]}?.toDrawable(resources) ?:resources.getDrawable(arrow.icon) } } @@ -532,36 +532,34 @@ private enum class GravityMap(val key: String, val gravity: Int) { } } -private enum class FontMap(val key: String, var font: Typeface, @FontRes val fontRessources: Int?, val customFont: ResFileMap?) { - SANS_SERIF(JsonKeyValues.SANS_SERIF.key, Typeface.SANS_SERIF, null, null), - DEFAULT(JsonKeyValues.DEFAULT.key, Typeface.DEFAULT, null, null), - DEFAULT_BOLD(JsonKeyValues.DEFAULT_BOLD.key, Typeface.DEFAULT_BOLD, null, null), - MONOSPACE(JsonKeyValues.MONOSPACE.key, Typeface.MONOSPACE, null, null), - SERIF(JsonKeyValues.SERIF.key, Typeface.SERIF, null, null), - ROBOTO_CONDENSED_BOLD(JsonKeyValues.ROBOTO_CONDENSED_BOLD.key, Typeface.DEFAULT, R.font.roboto_condensed_bold, null), - ROBOTO_CONDENSED_LIGHT(JsonKeyValues.ROBOTO_CONDENSED_LIGHT.key, Typeface.DEFAULT, R.font.roboto_condensed_light, null), - ROBOTO_CONDENSED_REGULAR(JsonKeyValues.ROBOTO_CONDENSED_REGULAR.key, Typeface.DEFAULT, R.font.roboto_condensed_regular, null), - ROBOTO_SLAB_LIGHT(JsonKeyValues.ROBOTO_SLAB_LIGHT.key, Typeface.DEFAULT, R.font.roboto_slab_light, null), - FONT1(JsonKeyValues.FONT1.key, Typeface.DEFAULT, null, ResFileMap.FONT1), - FONT2(JsonKeyValues.FONT2.key, Typeface.DEFAULT, null, ResFileMap.FONT2), - FONT3(JsonKeyValues.FONT3.key, Typeface.DEFAULT, null, ResFileMap.FONT3), - FONT4(JsonKeyValues.FONT4.key, Typeface.DEFAULT, null, ResFileMap.FONT4); +private enum class FontMap(val key: String, var font: Typeface, @FontRes val fontRessources: Int?) { + SANS_SERIF(JsonKeyValues.SANS_SERIF.key, Typeface.SANS_SERIF, null), + DEFAULT(JsonKeyValues.DEFAULT.key, Typeface.DEFAULT, null), + DEFAULT_BOLD(JsonKeyValues.DEFAULT_BOLD.key, Typeface.DEFAULT_BOLD, null), + MONOSPACE(JsonKeyValues.MONOSPACE.key, Typeface.MONOSPACE, null), + SERIF(JsonKeyValues.SERIF.key, Typeface.SERIF, null), + ROBOTO_CONDENSED_BOLD(JsonKeyValues.ROBOTO_CONDENSED_BOLD.key, Typeface.DEFAULT, R.font.roboto_condensed_bold), + ROBOTO_CONDENSED_LIGHT(JsonKeyValues.ROBOTO_CONDENSED_LIGHT.key, Typeface.DEFAULT, R.font.roboto_condensed_light), + ROBOTO_CONDENSED_REGULAR(JsonKeyValues.ROBOTO_CONDENSED_REGULAR.key, Typeface.DEFAULT, R.font.roboto_condensed_regular), + ROBOTO_SLAB_LIGHT(JsonKeyValues.ROBOTO_SLAB_LIGHT.key, Typeface.DEFAULT, R.font.roboto_slab_light); companion object { - fun init(context: Context, resDataMap: CwfResDataMap) = values().forEach { fontMap -> - fontMap.customFont?.let { customFont -> - fontMap.font = Typeface.DEFAULT - resDataMap[customFont]?.toTypeface()?.let { resData -> - fontMap.font = resData - } - } ?: run { - fontMap.font = fontMap.fontRessources?.let { fontResource -> + private val customFonts = mutableMapOf() + fun init(context: Context, resDataMap: CwfResDataMap) { + values().forEach { fontMap -> + customFonts[fontMap.key.lowercase()] = fontMap.fontRessources?.let { fontResource -> ResourcesCompat.getFont(context, fontResource) } ?: fontMap.font } + resDataMap.filter { (_, resData) -> + resData.format == ResFormat.TTF + }.forEach { (key, resData) -> + customFonts[key.lowercase()] = resData.toTypeface() ?:Typeface.DEFAULT + } } - fun font(key: String) = values().firstOrNull { it.key == key }?.font ?: DEFAULT.font + + fun font(key: String) = customFonts[key.lowercase()] ?: DEFAULT.font fun key() = DEFAULT.key } }