From b1d515e68cf8d445c482b9fc0146d64a6493fdf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joris=20Pelgr=C3=B6m?= Date: Fri, 2 Feb 2024 21:38:21 +0100 Subject: [PATCH 1/2] Add option to update camera & template tile 'on view' - Use the tile enter callback to request an update to the tile once it enters the view. Considering that this callback exists it's probably safe to assume an update that is requested in this callback won't be throttled (at least it appears to work during testing). - Minor edit to the refresh interval picker to ensure strings that are more than one line look a bit nicer. --- .../wear/views/SettingsWearTemplateTile.kt | 2 +- .../android/util/IntervalToString.kt | 1 + common/src/main/res/values/strings.xml | 1 + .../home/views/RefreshIntervalPickerView.kt | 10 +++++-- .../companion/android/tiles/CameraTile.kt | 29 +++++++++++++++++-- .../companion/android/tiles/TemplateTile.kt | 28 ++++++++++++++++-- 6 files changed, 62 insertions(+), 9 deletions(-) diff --git a/app/src/full/java/io/homeassistant/companion/android/settings/wear/views/SettingsWearTemplateTile.kt b/app/src/full/java/io/homeassistant/companion/android/settings/wear/views/SettingsWearTemplateTile.kt index 08adc3ac35a..73542dcfc43 100644 --- a/app/src/full/java/io/homeassistant/companion/android/settings/wear/views/SettingsWearTemplateTile.kt +++ b/app/src/full/java/io/homeassistant/companion/android/settings/wear/views/SettingsWearTemplateTile.kt @@ -88,7 +88,7 @@ fun SettingsWearTemplateTile( expanded = dropdownExpanded, onDismissRequest = { dropdownExpanded = false } ) { - val options = listOf(0, 60, 2 * 60, 5 * 60, 10 * 60, 15 * 60, 30 * 60, 60 * 60, 2 * 60 * 60, 5 * 60 * 60, 10 * 60 * 60, 24 * 60 * 60) + val options = listOf(0, 1, 60, 2 * 60, 5 * 60, 10 * 60, 15 * 60, 30 * 60, 60 * 60, 2 * 60 * 60, 5 * 60 * 60, 10 * 60 * 60, 24 * 60 * 60) for (option in options) { DropdownMenuItem(onClick = { onRefreshIntervalChanged(option) diff --git a/common/src/main/java/io/homeassistant/companion/android/util/IntervalToString.kt b/common/src/main/java/io/homeassistant/companion/android/util/IntervalToString.kt index 74ed1a59d7b..3f998ff97a8 100644 --- a/common/src/main/java/io/homeassistant/companion/android/util/IntervalToString.kt +++ b/common/src/main/java/io/homeassistant/companion/android/util/IntervalToString.kt @@ -6,6 +6,7 @@ import io.homeassistant.companion.android.common.R fun intervalToString(context: Context, interval: Int): String { return when { interval == 0 -> context.getString(R.string.interval_manual) + interval == 1 -> context.getString(R.string.interval_on_view) interval >= 60 * 60 -> context.resources.getQuantityString(R.plurals.interval_hours, interval / 60 / 60, interval / 60 / 60) interval >= 60 -> context.resources.getQuantityString(R.plurals.interval_minutes, interval / 60, interval / 60) else -> context.resources.getQuantityString(R.plurals.interval_seconds, interval, interval) diff --git a/common/src/main/res/values/strings.xml b/common/src/main/res/values/strings.xml index 867c125a662..6963b00b1ef 100644 --- a/common/src/main/res/values/strings.xml +++ b/common/src/main/res/values/strings.xml @@ -317,6 +317,7 @@ %d second %d seconds + On view Do not lock screen when dashboard is active Keep screen on Allow pinch-to-zoom gesture to zoom app window diff --git a/wear/src/main/java/io/homeassistant/companion/android/home/views/RefreshIntervalPickerView.kt b/wear/src/main/java/io/homeassistant/companion/android/home/views/RefreshIntervalPickerView.kt index e0986536bdf..991b5650fc8 100644 --- a/wear/src/main/java/io/homeassistant/companion/android/home/views/RefreshIntervalPickerView.kt +++ b/wear/src/main/java/io/homeassistant/companion/android/home/views/RefreshIntervalPickerView.kt @@ -15,6 +15,8 @@ import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.wear.compose.material.ListHeader @@ -43,7 +45,8 @@ fun RefreshIntervalPickerView( currentInterval: Int, onSelectInterval: (Int) -> Unit ) { - val options = listOf(0, 60, 2 * 60, 5 * 60, 10 * 60, 15 * 60, 30 * 60, 60 * 60, 2 * 60 * 60, 5 * 60 * 60, 10 * 60 * 60, 24 * 60 * 60) + // Refresh interval options: never, when viewed, every x time + val options = listOf(0, 1, 60, 2 * 60, 5 * 60, 10 * 60, 15 * 60, 30 * 60, 60 * 60, 2 * 60 * 60, 5 * 60 * 60, 10 * 60 * 60, 24 * 60 * 60) val initialIndex = options.indexOf(currentInterval) val state = rememberPickerState( initialNumberOfOptions = options.size, @@ -76,7 +79,10 @@ fun RefreshIntervalPickerView( fontSize = MaterialTheme.typography.displayMedium.fontSize.value.dp.toSp() // Ignore text scaling ) }, - color = wearColorScheme.primary + color = wearColorScheme.primary, + textAlign = TextAlign.Center, // In case of overflow, minimize weird layout behavior + overflow = TextOverflow.Ellipsis, + maxLines = 2 ) } FilledIconButton( diff --git a/wear/src/main/java/io/homeassistant/companion/android/tiles/CameraTile.kt b/wear/src/main/java/io/homeassistant/companion/android/tiles/CameraTile.kt index 4de307d62f0..e6fe401f1e2 100644 --- a/wear/src/main/java/io/homeassistant/companion/android/tiles/CameraTile.kt +++ b/wear/src/main/java/io/homeassistant/companion/android/tiles/CameraTile.kt @@ -28,6 +28,7 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job import kotlinx.coroutines.cancel import kotlinx.coroutines.guava.future +import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking import kotlinx.coroutines.withContext import okhttp3.OkHttpClient @@ -70,12 +71,15 @@ class CameraTile : TileService() { if (requestParams.currentState.lastClickableId == MODIFIER_CLICK_REFRESH) { if (wearPrefsRepository.getWearHapticFeedback()) hapticClick(applicationContext) } + val freshness = when { + (tileConfig?.refreshInterval != null && tileConfig.refreshInterval!! <= 1) -> 0 + tileConfig?.refreshInterval != null -> tileConfig.refreshInterval!! + else -> DEFAULT_REFRESH_INTERVAL + } Tile.Builder() .setResourcesVersion("$TAG$tileId.${System.currentTimeMillis()}") - .setFreshnessIntervalMillis( - TimeUnit.SECONDS.toMillis(tileConfig?.refreshInterval ?: DEFAULT_REFRESH_INTERVAL) - ) + .setFreshnessIntervalMillis(TimeUnit.SECONDS.toMillis(freshness)) .setTileTimeline( if (serverManager.isRegistered()) { timeline( @@ -202,6 +206,25 @@ class CameraTile : TileService() { } } + override fun onTileEnterEvent(requestParams: EventBuilders.TileEnterEvent) { + serviceScope.launch { + val tileId = requestParams.tileId + val tileConfig = AppDatabase.getInstance(this@CameraTile) + .cameraTileDao() + .get(tileId) + tileConfig?.refreshInterval?.let { + if (it >= 1) { + try { + getUpdater(this@CameraTile) + .requestUpdate(io.homeassistant.companion.android.tiles.CameraTile::class.java) + } catch (e: Exception) { + Log.w(TAG, "Unable to request tile update on enter", e) + } + } + } + } + } + override fun onDestroy() { super.onDestroy() serviceScope.cancel() diff --git a/wear/src/main/java/io/homeassistant/companion/android/tiles/TemplateTile.kt b/wear/src/main/java/io/homeassistant/companion/android/tiles/TemplateTile.kt index 8e638f710ee..4387797fcaf 100644 --- a/wear/src/main/java/io/homeassistant/companion/android/tiles/TemplateTile.kt +++ b/wear/src/main/java/io/homeassistant/companion/android/tiles/TemplateTile.kt @@ -35,6 +35,7 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job import kotlinx.coroutines.guava.future +import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking import kotlinx.coroutines.withContext import javax.inject.Inject @@ -42,6 +43,11 @@ import io.homeassistant.companion.android.common.R as commonR @AndroidEntryPoint class TemplateTile : TileService() { + + companion object { + private const val TAG = "TemplateTile" + } + private val serviceJob = Job() private val serviceScope = CoroutineScope(Dispatchers.IO + serviceJob) @@ -59,12 +65,14 @@ class TemplateTile : TileService() { val tileId = requestParams.tileId val templateTileConfig = getTemplateTileConfig(tileId) + val freshness = when { + templateTileConfig.refreshInterval <= 1 -> 0 + else -> templateTileConfig.refreshInterval + } Tile.Builder() .setResourcesVersion("1") - .setFreshnessIntervalMillis( - templateTileConfig.refreshInterval.toLong() * 1_000 - ) + .setFreshnessIntervalMillis(freshness.toLong() * 1_000) .setTileTimeline( if (serverManager.isRegistered()) { timeline(templateTileConfig) @@ -122,6 +130,20 @@ class TemplateTile : TileService() { } } + override fun onTileEnterEvent(requestParams: EventBuilders.TileEnterEvent) { + serviceScope.launch { + val tileId = requestParams.tileId + val templateTileConfig = getTemplateTileConfig(tileId) + if (templateTileConfig.refreshInterval >= 1) { + try { + getUpdater(this@TemplateTile).requestUpdate(TemplateTile::class.java) + } catch (e: Exception) { + Log.w(TAG, "Unable to request tile update on enter", e) + } + } + } + } + override fun onDestroy() { super.onDestroy() // Cleans up the coroutine From 6c591f0a6f818a5c0ae9886af7048b31ed819937 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joris=20Pelgr=C3=B6m?= Date: Fri, 2 Feb 2024 21:41:53 +0100 Subject: [PATCH 2/2] on view -> in view --- .../io/homeassistant/companion/android/util/IntervalToString.kt | 2 +- common/src/main/res/values/strings.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/common/src/main/java/io/homeassistant/companion/android/util/IntervalToString.kt b/common/src/main/java/io/homeassistant/companion/android/util/IntervalToString.kt index 3f998ff97a8..e3e3b2e840b 100644 --- a/common/src/main/java/io/homeassistant/companion/android/util/IntervalToString.kt +++ b/common/src/main/java/io/homeassistant/companion/android/util/IntervalToString.kt @@ -6,7 +6,7 @@ import io.homeassistant.companion.android.common.R fun intervalToString(context: Context, interval: Int): String { return when { interval == 0 -> context.getString(R.string.interval_manual) - interval == 1 -> context.getString(R.string.interval_on_view) + interval == 1 -> context.getString(R.string.interval_in_view) interval >= 60 * 60 -> context.resources.getQuantityString(R.plurals.interval_hours, interval / 60 / 60, interval / 60 / 60) interval >= 60 -> context.resources.getQuantityString(R.plurals.interval_minutes, interval / 60, interval / 60) else -> context.resources.getQuantityString(R.plurals.interval_seconds, interval, interval) diff --git a/common/src/main/res/values/strings.xml b/common/src/main/res/values/strings.xml index 6963b00b1ef..b41229291fd 100644 --- a/common/src/main/res/values/strings.xml +++ b/common/src/main/res/values/strings.xml @@ -317,7 +317,7 @@ %d second %d seconds - On view + In view Do not lock screen when dashboard is active Keep screen on Allow pinch-to-zoom gesture to zoom app window