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 14ed7df026..f245b7d8bd 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 @@ -17,11 +17,13 @@ import java.util.zip.ZipEntry import java.util.zip.ZipInputStream import java.util.zip.ZipOutputStream -val CUSTOM_VERSION = "0.5" +val CUSTOM_VERSION = "0.7" enum class CustomWatchfaceDrawableDataKey(val key: String, @DrawableRes val icon: Int?, val fileName: String) { UNKNOWN("unknown", null, "Unknown"), CUSTOM_WATCHFACE("customWatchface", R.drawable.watchface_custom, "CustomWatchface"), BACKGROUND("background", R.drawable.background, "Background"), + BACKGROUND_HIGH("background", R.drawable.background, "BackgroundHigh"), + BACKGROUND_LOW("background", R.drawable.background, "BackgroundLow"), COVERCHART("cover_chart", null, "CoverChart"), COVERPLATE("cover_plate", R.drawable.simplified_dial, "CoverPlate"), HOURHAND("hour_hand", R.drawable.hour_hand, "HourHand"), 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 64a386379e..3d043707e2 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 @@ -68,8 +68,7 @@ class WearFragment : DaggerFragment() { updateGui() } binding.exportCustom.setOnClickListener { - wearPlugin.savedCustomWatchface?.let { importExportPrefs.exportCustomWatchface(it) } - ?: apply { rxBus.send(EventMobileToWear(EventData.ActionrequestCustomWatchface(true)))} + rxBus.send(EventMobileToWear(EventData.ActionrequestCustomWatchface(true))) } } @@ -79,10 +78,12 @@ class WearFragment : DaggerFragment() { .toObservable(EventWearUpdateGui::class.java) .observeOn(aapsSchedulers.main) .subscribe({ - it.customWatchfaceData?.let { loadCustom(it) } if (it.exportFile) ToastUtils.okToast(activity, rh.gs(R.string.wear_new_custom_watchface_exported)) - updateGui() + else { + it.customWatchfaceData?.let { loadCustom(it) } + updateGui() + } }, fabricPrivacy::logException) if (wearPlugin.savedCustomWatchface == null) rxBus.send(EventMobileToWear(EventData.ActionrequestCustomWatchface(false))) 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 731290df49..bc7ecf84a6 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 @@ -95,7 +95,7 @@ class WearPlugin @Inject constructor( disposable += rxBus .toObservable(EventWearUpdateGui::class.java) .observeOn(aapsSchedulers.main) - .subscribe({ it.customWatchfaceData?.let { cwf -> savedCustomWatchface = cwf } }, fabricPrivacy::logException) + .subscribe({ it.customWatchfaceData?.let { cwf -> if (!it.exportFile) savedCustomWatchface = cwf } }, fabricPrivacy::logException) } override fun onStop() { diff --git a/plugins/main/src/main/res/values/strings.xml b/plugins/main/src/main/res/values/strings.xml index 0cb11d304e..69dae93b81 100644 --- a/plugins/main/src/main/res/values/strings.xml +++ b/plugins/main/src/main/res/values/strings.xml @@ -364,8 +364,8 @@ Custom Watchface: %1$s Load Watchface Send Watchface - Export Watchface - Custom watchface exported + Export template + Custom watchface template exported Resend All Data Open Settings on Wear diff --git a/wear/src/main/java/info/nightscout/androidaps/comm/DataHandlerWear.kt b/wear/src/main/java/info/nightscout/androidaps/comm/DataHandlerWear.kt index fb16c6a5e6..6a1c07a3f8 100644 --- a/wear/src/main/java/info/nightscout/androidaps/comm/DataHandlerWear.kt +++ b/wear/src/main/java/info/nightscout/androidaps/comm/DataHandlerWear.kt @@ -204,8 +204,8 @@ class DataHandlerWear @Inject constructor( .toObservable(EventData.ActionrequestCustomWatchface::class.java) .observeOn(aapsSchedulers.io) .subscribe { eventData -> - aapsLogger.debug(LTag.WEAR, "Custom Watchface requested from ${eventData.sourceNodeId}") - persistence.readCustomWatchface()?.let { + aapsLogger.debug(LTag.WEAR, "Custom Watchface requested from ${eventData.sourceNodeId} export ${eventData.exportFile}") + persistence.readCustomWatchface(eventData.exportFile)?.let { rxBus.send(EventWearDataToMobile(EventData.ActionGetCustomWatchface(it, eventData.exportFile))) } } 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 7e025bbcc4..416ed94890 100644 --- a/wear/src/main/java/info/nightscout/androidaps/watchfaces/CustomWatchface.kt +++ b/wear/src/main/java/info/nightscout/androidaps/watchfaces/CustomWatchface.kt @@ -2,6 +2,7 @@ package info.nightscout.androidaps.watchfaces +import android.annotation.SuppressLint import android.app.ActionBar.LayoutParams import android.content.Context import android.graphics.Color @@ -81,9 +82,10 @@ class CustomWatchface : BaseWatchFace() { .build() } + @SuppressLint("UseCompatLoadingForDrawables") override fun setDataFields() { super.setDataFields() - binding.direction2.setImageDrawable(resources.getDrawable(TrendArrow.icon(singleBg.slopeArrow))) + binding.direction2.setImageDrawable(this.resources.getDrawable(TrendArrow.icon(singleBg.slopeArrow))) // rotate the second hand. binding.secondHand.rotation = TimeOfDay().secondOfMinute * 6f // rotate the minute hand. @@ -119,11 +121,14 @@ class CustomWatchface : BaseWatchFace() { } override fun setSecond() { - binding.time.text = "${dateUtil.hourString()}:${dateUtil.minuteString()}" + if (showSecond) ":${dateUtil.secondString()}" else "" + binding.time.text = if (showSecond) + getString(R.string.hour_minute_second, dateUtil.hourString(), dateUtil.minuteString(), dateUtil.secondString()) + else + getString(R.string.hour_minute, dateUtil.hourString(), dateUtil.minuteString()) + //binding.time.text = "${dateUtil.hourString()}:${dateUtil.minuteString()}" + if (showSecond) ":${dateUtil.secondString()}" else "" binding.second.text = dateUtil.secondString() // rotate the second hand. binding.secondHand.rotation = TimeOfDay().secondOfMinute * 6f - //aapsLogger.debug("XXXXX SetSecond $watchModeString") } override fun updateSecondVisibility() { @@ -131,6 +136,7 @@ class CustomWatchface : BaseWatchFace() { binding.secondHand.visibility = showSecond.toVisibility() } + @SuppressLint("UseCompatLoadingForDrawables") private fun setWatchfaceStyle() { val customWatchface = persistence.readCustomWatchface() ?: persistence.readCustomWatchface(true) customWatchface?.let { @@ -154,46 +160,56 @@ class CustomWatchface : BaseWatchFace() { -1L -> lowColor else -> midColor } + val backGroundDrawable = when (singleBg.sgvLevel) { + 1L -> drawableDataMap[CustomWatchfaceDrawableDataKey.BACKGROUND_HIGH]?.toDrawable(resources) ?: drawableDataMap[CustomWatchfaceDrawableDataKey.BACKGROUND]?.toDrawable(resources) + 0L -> drawableDataMap[CustomWatchfaceDrawableDataKey.BACKGROUND]?.toDrawable(resources) + -1L -> drawableDataMap[CustomWatchfaceDrawableDataKey.BACKGROUND_LOW]?.toDrawable(resources) ?: drawableDataMap[CustomWatchfaceDrawableDataKey.BACKGROUND]?.toDrawable(resources) + else -> drawableDataMap[CustomWatchfaceDrawableDataKey.BACKGROUND]?.toDrawable(resources) + } binding.mainLayout.forEach { view -> CustomViews.fromId(view.id)?.let { id -> if (json.has(id.key)) { - var viewjson = json.getJSONObject(id.key) - var wrapContent = LayoutParams.WRAP_CONTENT - val width = if (viewjson.has("width")) (viewjson.getInt("width") * zoomFactor).toInt() else wrapContent - val height = if (viewjson.has("height")) (viewjson.getInt("height") * zoomFactor).toInt() else wrapContent - var params = FrameLayout.LayoutParams(width, height) - params.topMargin = if (viewjson.has("topmargin")) (viewjson.getInt("topmargin") * zoomFactor).toInt() else 0 - params.leftMargin = if (viewjson.has("leftmargin")) (viewjson.getInt("leftmargin") * zoomFactor).toInt() else 0 - view.setLayoutParams(params) - view.visibility = if (viewjson.has("visibility")) setVisibility(viewjson.getString("visibility"), id.visibility(sp)) else View.GONE + val viewJson = json.getJSONObject(id.key) + val wrapContent = LayoutParams.WRAP_CONTENT + val width = if (viewJson.has("width")) (viewJson.getInt("width") * zoomFactor).toInt() else wrapContent + val height = if (viewJson.has("height")) (viewJson.getInt("height") * zoomFactor).toInt() else wrapContent + val params = FrameLayout.LayoutParams(width, height) + params.topMargin = if (viewJson.has("topmargin")) (viewJson.getInt("topmargin") * zoomFactor).toInt() else 0 + params.leftMargin = if (viewJson.has("leftmargin")) (viewJson.getInt("leftmargin") * zoomFactor).toInt() else 0 + view.layoutParams = params + view.visibility = if (viewJson.has("visibility")) setVisibility(viewJson.getString("visibility"), id.visibility(sp)) else View.GONE if (view is TextView) { - view.rotation = if (viewjson.has("rotation")) viewjson.getInt("rotation").toFloat() else 0F - view.setTextSize(TypedValue.COMPLEX_UNIT_PX, ((if (viewjson.has("textsize")) viewjson.getInt("textsize") else 22) * zoomFactor).toFloat()) - view.gravity = GravityMap.gravity(if (viewjson.has("gravity")) viewjson.getString("gravity") else GravityMap.CENTER.key) + view.rotation = if (viewJson.has("rotation")) viewJson.getInt("rotation").toFloat() else 0F + view.setTextSize(TypedValue.COMPLEX_UNIT_PX, ((if (viewJson.has("textsize")) viewJson.getInt("textsize") else 22) * zoomFactor).toFloat()) + view.gravity = GravityMap.gravity(if (viewJson.has("gravity")) viewJson.getString("gravity") else GravityMap.CENTER.key) view.setTypeface( - FontMap.font(if (viewjson.has("font")) viewjson.getString("font") else FontMap.DEFAULT.key), - StyleMap.style(if (viewjson.has("fontStyle")) viewjson.getString("fontStyle") else StyleMap.NORMAL.key) + FontMap.font(if (viewJson.has("font")) viewJson.getString("font") else FontMap.DEFAULT.key), + StyleMap.style(if (viewJson.has("fontStyle")) viewJson.getString("fontStyle") else StyleMap.NORMAL.key) ) - if (viewjson.has("fontColor")) - view.setTextColor(getColor(viewjson.getString("fontColor"))) + if (viewJson.has("fontColor")) + view.setTextColor(getColor(viewJson.getString("fontColor"))) - if (viewjson.has("textvalue")) - view.text = viewjson.getString("textvalue") + if (viewJson.has("textvalue")) + view.text = viewJson.getString("textvalue") } if (view is ImageView) { view.clearColorFilter() - drawableDataMap[CustomWatchfaceDrawableDataKey.fromKey(id.key)]?.toDrawable(resources)?.also { - if (viewjson.has("color")) - it.colorFilter = changeDrawableColor(getColor(viewjson.getString("color"))) + val drawable = if (id.key == CustomWatchfaceDrawableDataKey.BACKGROUND.key) + backGroundDrawable + else + drawableDataMap[CustomWatchfaceDrawableDataKey.fromKey(id.key)]?.toDrawable(resources) + drawable?.let { + if (viewJson.has("color")) + it.colorFilter = changeDrawableColor(getColor(viewJson.getString("color"))) else it.clearColorFilter() view.setImageDrawable(it) } ?: apply { view.setImageDrawable(CustomWatchfaceDrawableDataKey.fromKey(id.key).icon?.let { context.getDrawable(it) }) - if (viewjson.has("color")) - view.setColorFilter(getColor(viewjson.getString("color"))) + if (viewJson.has("color")) + view.setColorFilter(getColor(viewJson.getString("color"))) else view.clearColorFilter() } @@ -315,23 +331,19 @@ class CustomWatchface : BaseWatchFace() { else -> "gone" } - fun getResourceByteArray(resourceId: Int): ByteArray? { + private fun getResourceByteArray(resourceId: Int): ByteArray? { val inputStream = resources.openRawResource(resourceId) val byteArrayOutputStream = ByteArrayOutputStream() - try { - val buffer = ByteArray(1024) - var count: Int - while (inputStream.read(buffer).also { count = it } != -1) { - byteArrayOutputStream.write(buffer, 0, count) - } - byteArrayOutputStream.close() - inputStream.close() - - return byteArrayOutputStream.toByteArray() - } catch (e: Exception) { + val buffer = ByteArray(1024) + var count: Int + while (inputStream.read(buffer).also { count = it } != -1) { + byteArrayOutputStream.write(buffer, 0, count) } - return null + byteArrayOutputStream.close() + inputStream.close() + + return byteArrayOutputStream.toByteArray() } private fun changeDrawableColor(color: Int): ColorFilter { @@ -351,16 +363,11 @@ class CustomWatchface : BaseWatchFace() { return ColorMatrixColorFilter(colorMatrix) } - private fun getColor(color: String): Int { + private fun getColor(color: String): Int = if (color == "bgColor") - return bgColor + bgColor else - return try { - Color.parseColor(color) - } catch (e: Exception) { - Color.GRAY - } - } + try { Color.parseColor(color) } catch (e: Exception) { Color.GRAY } private enum class CustomViews(val key: String, @IdRes val id: Int, @StringRes val pref: Int?) { @@ -369,6 +376,8 @@ class CustomWatchface : BaseWatchFace() { COVER_CHART(CustomWatchfaceDrawableDataKey.COVERCHART.key, R.id.cover_chart, null), FREETEXT1("freetext1", R.id.freetext1, null), FREETEXT2("freetext2", R.id.freetext2, null), + FREETEXT3("freetext3", R.id.freetext3, null), + FREETEXT4("freetext4", R.id.freetext4, null), IOB1("iob1", R.id.iob1, R.string.key_show_iob), IOB2("iob2", R.id.iob2, R.string.key_show_iob), COB1("cob1", R.id.cob1, R.string.key_show_cob), @@ -398,7 +407,6 @@ class CustomWatchface : BaseWatchFace() { companion object { - fun fromKey(key: String): CustomViews? = values().firstOrNull { it.key == key } fun fromId(id: Int): CustomViews? = values().firstOrNull { it.id == id } } @@ -443,13 +451,12 @@ class CustomWatchface : BaseWatchFace() { DEFAULT_BOLD("default-bold", Typeface.DEFAULT_BOLD, null), MONOSPACE("monospace", Typeface.MONOSPACE, null), SERIF("serif", Typeface.SERIF, null), - ROBOTO_CONDENSED_BOLD("roboto-condensed-bold", Typeface.DEFAULT, R.font.roboto_condensed_bold), - ROBOTO_CONDENSED_LIGHT("roboto-condensed-light", Typeface.DEFAULT, R.font.roboto_condensed_light), - ROBOTO_CONDENSED_REGULAR("roboto-condensed-regular", Typeface.DEFAULT, R.font.roboto_condensed_regular), - ROBOTO_SLAB_LIGHT("roboto-slab-light", Typeface.DEFAULT, R.font.roboto_slab_light); + ROBOTO_CONDENSED_BOLD("roboto_condensed_bold", Typeface.DEFAULT, R.font.roboto_condensed_bold), + ROBOTO_CONDENSED_LIGHT("roboto_condensed_light", Typeface.DEFAULT, R.font.roboto_condensed_light), + ROBOTO_CONDENSED_REGULAR("roboto_condensed_regular", Typeface.DEFAULT, R.font.roboto_condensed_regular), + ROBOTO_SLAB_LIGHT("roboto_slab_light", Typeface.DEFAULT, R.font.roboto_slab_light); companion object { - fun init(context: Context) = values().forEach { it.font = it.fontRessources?.let { font -> ResourcesCompat.getFont(context, font) } ?: it.font } fun font(key: String) = values().firstOrNull { it.key == key }?.font ?: DEFAULT.font fun key() = DEFAULT.key diff --git a/wear/src/main/res/layout/activity_custom.xml b/wear/src/main/res/layout/activity_custom.xml index 01d2a8dab1..805f26da39 100644 --- a/wear/src/main/res/layout/activity_custom.xml +++ b/wear/src/main/res/layout/activity_custom.xml @@ -56,6 +56,28 @@ android:visibility="gone" android:textColor="@color/light_grey" /> + + + + w d h + %1$s:%2$s + %1$s:%2$s:%3$s old !old! !err!