From 52007c67ecc4d4ff333847bec4646da7486538cd Mon Sep 17 00:00:00 2001 From: kavemang <66108693+kavemang@users.noreply.github.com> Date: Sat, 3 Oct 2026 03:13:01 -0500 Subject: [PATCH] fix(today): explain Start session availability in customization Refs #2327 --- Strand/Resources/Localizable.xcstrings | 1 + Strand/Screens/TodayCustomizationSheet.swift | 2 ++ .../src/main/java/com/noop/ui/TodayScreen.kt | 22 ++++++++++++++++--- .../app/src/main/res/values-de/strings.xml | 1 + .../app/src/main/res/values-es/strings.xml | 1 + .../app/src/main/res/values-fr/strings.xml | 1 + .../app/src/main/res/values-it/strings.xml | 1 + .../app/src/main/res/values-pl/strings.xml | 1 + .../src/main/res/values-pt-rPT/strings.xml | 1 + .../app/src/main/res/values-ru/strings.xml | 1 + .../app/src/main/res/values-zh/strings.xml | 1 + android/app/src/main/res/values/strings.xml | 1 + 12 files changed, 31 insertions(+), 3 deletions(-) diff --git a/Strand/Resources/Localizable.xcstrings b/Strand/Resources/Localizable.xcstrings index eebdd2c8c4..0bc8941dfe 100644 --- a/Strand/Resources/Localizable.xcstrings +++ b/Strand/Resources/Localizable.xcstrings @@ -2,6 +2,7 @@ "sourceLanguage": "en", "strings": { "Skips sessions that overlap a saved or imported workout, including workouts from Apple Health.": {"localizations": {"en": {"stringUnit": {"state": "translated", "value": "Skips sessions that overlap a saved or imported workout, including workouts from Apple Health."}}, "de": {"stringUnit": {"state": "translated", "value": "Überspringt Einheiten, die sich mit einem gespeicherten oder importierten Training überschneiden, auch mit Trainings aus Apple Health."}}, "es": {"stringUnit": {"state": "translated", "value": "Omite las sesiones que se solapan con un entrenamiento guardado o importado, incluidos los de Apple Health."}}, "fr": {"stringUnit": {"state": "translated", "value": "Ignore les séances qui chevauchent un entraînement enregistré ou importé, y compris ceux provenant d’Apple Health."}}, "it": {"stringUnit": {"state": "translated", "value": "Ignora le sessioni che si sovrappongono a un allenamento salvato o importato, inclusi quelli di Apple Health."}}, "pl": {"stringUnit": {"state": "translated", "value": "Pomija sesje nakładające się na zapisany lub zaimportowany trening, w tym treningi z Apple Health."}}, "pt-PT": {"stringUnit": {"state": "translated", "value": "Ignora sessões que se sobrepõem a um treino guardado ou importado, incluindo treinos do Apple Health."}}, "ru": {"stringUnit": {"state": "translated", "value": "Пропускает занятия, которые пересекаются с сохранённой или импортированной тренировкой, включая тренировки из Apple Health."}}, "zh-Hans": {"stringUnit": {"state": "translated", "value": "跳过与已保存或导入的训练时间重叠的活动,包括来自 Apple Health 的训练。"}}, "zh-Hant": {"stringUnit": {"state": "translated", "value": "略過與已儲存或匯入的訓練時間重疊的活動,包括來自 Apple Health 的訓練。"}}}}, + "Requires Live Sessions to be enabled in Settings.": {"localizations": {"en": {"stringUnit": {"state": "translated", "value": "Requires Live Sessions to be enabled in Settings."}}, "de": {"stringUnit": {"state": "translated", "value": "Erfordert aktivierte Live Sessions in den Einstellungen."}}, "es": {"stringUnit": {"state": "translated", "value": "Requiere activar Live Sessions en Ajustes."}}, "fr": {"stringUnit": {"state": "translated", "value": "Nécessite d’activer les sessions en direct dans Réglages."}}, "it": {"stringUnit": {"state": "translated", "value": "Richiede l’attivazione delle sessioni in diretta nelle Impostazioni."}}, "pl": {"stringUnit": {"state": "translated", "value": "Wymaga włączenia sesji na żywo w Ustawieniach."}}, "pt-PT": {"stringUnit": {"state": "translated", "value": "Requer que as sessões em direto estejam ativadas nas Definições."}}, "ru": {"stringUnit": {"state": "translated", "value": "Требует включения сессий в реальном времени в Настройках."}}, "zh-Hans": {"stringUnit": {"state": "translated", "value": "需要在设置中启用 Live Sessions 实时记录。"}}, "zh-Hant": {"stringUnit": {"state": "translated", "value": "需要在設定中啟用 Live Sessions 即時記錄。"}}}}, "Sleep result updated": {"localizations": {"en": {"stringUnit": {"state": "translated", "value": "Sleep result updated"}}, "de": {"stringUnit": {"state": "translated", "value": "Schlafergebnis aktualisiert"}}, "es": {"stringUnit": {"state": "translated", "value": "Resultado del sueño actualizado"}}, "fr": {"stringUnit": {"state": "translated", "value": "Résultat du sommeil mis à jour"}}, "it": {"stringUnit": {"state": "translated", "value": "Risultato del sonno aggiornato"}}, "pl": {"stringUnit": {"state": "translated", "value": "Zaktualizowano wynik snu"}}, "pt-PT": {"stringUnit": {"state": "translated", "value": "Resultado do sono atualizado"}}, "ru": {"stringUnit": {"state": "translated", "value": "Результат сна обновлён"}}, "zh-Hans": {"stringUnit": {"state": "translated", "value": "睡眠结果已更新"}}, "zh-Hant": {"stringUnit": {"state": "translated", "value": "睡眠結果已更新"}}}}, "This night's sleep times or total asleep changed by at least five minutes.": {"localizations": {"en": {"stringUnit": {"state": "translated", "value": "This night's sleep times or total asleep changed by at least five minutes."}}, "de": {"stringUnit": {"state": "translated", "value": "Die Schlafzeiten oder die Gesamtschlafdauer dieser Nacht haben sich um mindestens fünf Minuten geändert."}}, "es": {"stringUnit": {"state": "translated", "value": "Las horas de sueño o el tiempo total dormido de esta noche cambiaron al menos cinco minutos."}}, "fr": {"stringUnit": {"state": "translated", "value": "Les horaires de sommeil ou la durée totale de sommeil de cette nuit ont changé d’au moins cinq minutes."}}, "it": {"stringUnit": {"state": "translated", "value": "Gli orari del sonno o il tempo totale dormito di questa notte sono cambiati di almeno cinque minuti."}}, "pl": {"stringUnit": {"state": "translated", "value": "Godziny snu lub łączny czas snu tej nocy zmieniły się o co najmniej pięć minut."}}, "pt-PT": {"stringUnit": {"state": "translated", "value": "Os horários de sono ou o tempo total de sono desta noite mudaram pelo menos cinco minutos."}}, "ru": {"stringUnit": {"state": "translated", "value": "Время засыпания, пробуждения или общая продолжительность сна этой ночи изменились как минимум на пять минут."}}, "zh-Hans": {"stringUnit": {"state": "translated", "value": "这晚的入睡时间、醒来时间或总睡眠时长变化了至少五分钟。"}}, "zh-Hant": {"stringUnit": {"state": "translated", "value": "這晚的入睡時間、醒來時間或總睡眠時長變化了至少五分鐘。"}}}}, diff --git a/Strand/Screens/TodayCustomizationSheet.swift b/Strand/Screens/TodayCustomizationSheet.swift index 1c3c0ea449..b970906bd4 100644 --- a/Strand/Screens/TodayCustomizationSheet.swift +++ b/Strand/Screens/TodayCustomizationSheet.swift @@ -281,6 +281,8 @@ private struct TodaySectionsCustomizationPage: View { private func subtitle(for section: TodaySection) -> String? { switch section { + case .liveSession: + return String(localized: "Requires Live Sessions to be enabled in Settings.") case .keyMetrics: return String(localized: "\(keyMetricCount) metrics shown") case .yourCards: diff --git a/android/app/src/main/java/com/noop/ui/TodayScreen.kt b/android/app/src/main/java/com/noop/ui/TodayScreen.kt index 13e7e1d93f..15e2978b67 100644 --- a/android/app/src/main/java/com/noop/ui/TodayScreen.kt +++ b/android/app/src/main/java/com/noop/ui/TodayScreen.kt @@ -4750,6 +4750,16 @@ private fun intStringGrouped(v: Double): String { // MARK: - Shared Shown / Hidden editor rows +@Composable +private fun VisibilityItemLabel(title: String, subtitle: String?, color: Color, modifier: Modifier) { + Column(modifier = modifier, verticalArrangement = Arrangement.spacedBy(Metrics.space2)) { + Text(title, style = NoopType.body, color = color) + if (subtitle != null) { + Text(subtitle, style = NoopType.caption, color = Palette.textSecondary) + } + } +} + /** * The common editor body used by Today sections, Key Metrics and Your Cards. Items are never deleted: * remove moves one from Shown to Hidden, add restores it at the end of Shown, and the arrow controls use @@ -4770,6 +4780,7 @@ internal fun EditableVisibilityRows( // a user browses by origin. null (Today sections, Key Metrics, Your Cards) keeps the flat list. The // Shown list stays flat — it is the user's own cross-origin order. Twin of the Swift EditableLayoutList. hiddenGroup: ((T) -> String)? = null, + itemSubtitle: @Composable (T) -> String? = { null }, ) { val minShown = if (allowEmpty) 0 else 1 Column( @@ -4784,7 +4795,7 @@ internal fun EditableVisibilityRows( modifier = Modifier.fillMaxWidth().padding(vertical = Metrics.space6), verticalAlignment = Alignment.CenterVertically, ) { - Text(title, style = NoopType.body, color = Palette.textPrimary, modifier = Modifier.weight(1f)) + VisibilityItemLabel(title, itemSubtitle(item), Palette.textPrimary, Modifier.weight(1f)) IconButton( onClick = { if (index > 0) shown.add(index - 1, shown.removeAt(index)) @@ -4861,7 +4872,7 @@ internal fun EditableVisibilityRows( modifier = Modifier.fillMaxWidth().padding(vertical = Metrics.space6), verticalAlignment = Alignment.CenterVertically, ) { - Text(title, style = NoopType.body, color = Palette.textTertiary, modifier = Modifier.weight(1f)) + VisibilityItemLabel(title, itemSubtitle(item), Palette.textTertiary, Modifier.weight(1f)) IconButton( onClick = { hidden.remove(item); shown.add(item) }, modifier = Modifier.size(Metrics.iconButton), @@ -4886,7 +4897,7 @@ internal fun EditableVisibilityRows( modifier = Modifier.fillMaxWidth().padding(vertical = Metrics.space6), verticalAlignment = Alignment.CenterVertically, ) { - Text(title, style = NoopType.body, color = Palette.textTertiary, modifier = Modifier.weight(1f)) + VisibilityItemLabel(title, itemSubtitle(item), Palette.textTertiary, Modifier.weight(1f)) IconButton( onClick = { shown.add(hidden.removeAt(index)) }, modifier = Modifier.size(Metrics.iconButton), @@ -5268,6 +5279,11 @@ private fun TodayLayoutEditorDialog( shown = shown, hidden = hidden, itemTitle = { uiString(it.titleRes) }, + itemSubtitle = { + if (it == TodaySection.LIVE_SESSION) { + stringResource(R.string.today_customize_live_session_availability) + } else null + }, ) // #today-hosted-cards: hand-off to the editor that chooses WHICH Trends/Sleep cards the diff --git a/android/app/src/main/res/values-de/strings.xml b/android/app/src/main/res/values-de/strings.xml index df276e52b8..df230a49dc 100644 --- a/android/app/src/main/res/values-de/strings.xml +++ b/android/app/src/main/res/values-de/strings.xml @@ -2869,4 +2869,5 @@ EKG-Aufzeichnung starten EKG-Aufzeichnung stoppen Auf diesem Strap läuft möglicherweise noch eine Aufzeichnung. Das Ergebnis steht im Strap-Log. + Erscheint heute, wenn Live Sessions in den Einstellungen aktiviert sind oder eine Session aktiv ist. diff --git a/android/app/src/main/res/values-es/strings.xml b/android/app/src/main/res/values-es/strings.xml index f825e62309..fe52bf2aad 100644 --- a/android/app/src/main/res/values-es/strings.xml +++ b/android/app/src/main/res/values-es/strings.xml @@ -2856,4 +2856,5 @@ Iniciar captura de ECG Detener captura de ECG Puede que siga activa una captura en esta correa. El veredicto se registra en el strap log. + Aparece hoy si Live Sessions está activado en Ajustes o hay una sesión activa. diff --git a/android/app/src/main/res/values-fr/strings.xml b/android/app/src/main/res/values-fr/strings.xml index 8f0ef31f84..760c09e1bb 100644 --- a/android/app/src/main/res/values-fr/strings.xml +++ b/android/app/src/main/res/values-fr/strings.xml @@ -2855,4 +2855,5 @@ Démarrer la capture ECG Arrêter la capture ECG Une capture est peut-être encore active sur ce bracelet. Le verdict est écrit dans le strap log. + Apparaît aujourd’hui si les sessions en direct sont activées dans Paramètres ou si une session est active. diff --git a/android/app/src/main/res/values-it/strings.xml b/android/app/src/main/res/values-it/strings.xml index 5b9afb5529..23d8d8efcb 100644 --- a/android/app/src/main/res/values-it/strings.xml +++ b/android/app/src/main/res/values-it/strings.xml @@ -2824,4 +2824,5 @@ Avvia acquisizione ECG Interrompi acquisizione ECG Una acquisizione potrebbe essere ancora attiva su questo strap. Il verdetto va nello strap log. + Compare oggi se le sessioni in diretta sono attivate nelle Impostazioni o una sessione è attiva. diff --git a/android/app/src/main/res/values-pl/strings.xml b/android/app/src/main/res/values-pl/strings.xml index c1511697fc..9ae0325356 100644 --- a/android/app/src/main/res/values-pl/strings.xml +++ b/android/app/src/main/res/values-pl/strings.xml @@ -2872,4 +2872,5 @@ Rozpocznij zapis EKG Zatrzymaj zapis EKG Na tym pasku może nadal trwać zapis. Werdykt trafia do strap log. + Pojawia się dzisiaj, gdy sesje na żywo są włączone w Ustawieniach lub trwa sesja. diff --git a/android/app/src/main/res/values-pt-rPT/strings.xml b/android/app/src/main/res/values-pt-rPT/strings.xml index 3fa2753aa0..e685e8062c 100644 --- a/android/app/src/main/res/values-pt-rPT/strings.xml +++ b/android/app/src/main/res/values-pt-rPT/strings.xml @@ -2848,4 +2848,5 @@ Iniciar captura de ECG Parar captura de ECG Pode ainda estar a decorrer uma captura nesta pulseira. O veredicto vai para o strap log. + Aparece hoje quando as sessões em direto estão ativadas nas Definições ou existe uma sessão ativa. diff --git a/android/app/src/main/res/values-ru/strings.xml b/android/app/src/main/res/values-ru/strings.xml index 31bba6665b..32ad1fb86a 100644 --- a/android/app/src/main/res/values-ru/strings.xml +++ b/android/app/src/main/res/values-ru/strings.xml @@ -2751,4 +2751,5 @@ Начать запись ЭКГ Остановить запись ЭКГ На этом ремешке запись может всё ещё идти. Результат попадёт в strap log. + Появляется сегодня, если сессии в реальном времени включены в Настройках или сеанс уже активен. diff --git a/android/app/src/main/res/values-zh/strings.xml b/android/app/src/main/res/values-zh/strings.xml index 7aabe08ed1..edfb136454 100644 --- a/android/app/src/main/res/values-zh/strings.xml +++ b/android/app/src/main/res/values-zh/strings.xml @@ -2826,4 +2826,5 @@ 开始心电图采集 停止心电图采集 此腕带上可能仍在采集。结论会写入 strap log。 + 在设置中启用Live Sessions 实时记录或有正在进行的训练时,今天会显示此部分。 diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml index 1f783441e2..8811da02c4 100644 --- a/android/app/src/main/res/values/strings.xml +++ b/android/app/src/main/res/values/strings.xml @@ -2885,4 +2885,5 @@ Start ECG capture Stop ECG capture A capture may still be running on this strap. The verdict goes to the strap log. + Appears today when Live Sessions is enabled in Settings or a session is active.