Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 59 additions & 1 deletion Strand/Resources/Localizable.xcstrings
Original file line number Diff line number Diff line change
Expand Up @@ -161701,6 +161701,64 @@
}
}
},
"This export contains raw biometric frames, strap console text, and the connection log. Identifiers are redacted automatically. Share it only if you are comfortable with that.": {
"localizations": {
"de": {
"stringUnit": {
"state": "translated",
"value": "Dieser Export enthält biometrische Rohdaten, Konsolentext des Armbands und das Verbindungsprotokoll. Kennungen werden automatisch geschwärzt. Teile ihn nur, wenn du damit einverstanden bist."
}
},
"es": {
"stringUnit": {
"state": "translated",
"value": "Esta exportación contiene tramas biométricas sin procesar, texto de la consola de la pulsera y el registro de conexión. Los identificadores se ocultan automáticamente. Compártela solo si te sientes cómodo haciéndolo."
}
},
"fr": {
"stringUnit": {
"state": "translated",
"value": "Cette exportation contient des trames biométriques brutes, le texte de la console du bracelet et le journal de connexion. Les identifiants sont automatiquement masqués. Ne la partagez que si cela vous convient."
}
},
"it": {
"stringUnit": {
"state": "translated",
"value": "Questa esportazione contiene frame biometrici grezzi, testo della console del bracciale e il registro di connessione. Gli identificatori vengono oscurati automaticamente. Condividila solo se ti senti a tuo agio."
}
},
"pt-PT": {
"stringUnit": {
"state": "translated",
"value": "Esta exportação contém tramas biométricas em bruto, texto da consola da bracelete e o registo de ligação. Os identificadores são ocultados automaticamente. Partilha-a apenas se estiveres confortável com isso."
}
},
"ru": {
"stringUnit": {
"state": "translated",
"value": "Этот экспорт содержит необработанные биометрические кадры, текст консоли браслета и журнал подключения. Идентификаторы автоматически скрываются. Делитесь им, только если вам это комфортно."
}
},
"zh-Hans": {
"stringUnit": {
"state": "translated",
"value": "此导出包含原始生物识别数据帧、手环控制台文本和连接日志。标识符会自动隐去。请仅在你对此感到放心时分享。"
}
},
"zh-Hant": {
"stringUnit": {
"state": "translated",
"value": "此匯出包含原始生物辨識資料幀、手環主控台文字和連線記錄。識別碼會自動隱去。請僅在你對此感到放心時分享。"
}
},
"pl": {
"stringUnit": {
"state": "translated",
"value": "Ten eksport zawiera surowe ramki danych biometrycznych, tekst konsoli opaski i dziennik połączenia. Identyfikatory są automatycznie ukrywane. Udostępnij go tylko, jeśli czujesz się z tym komfortowo."
}
}
}
},
"This is exactly what your report will contain. Nothing leaves %@ until you tap Share.": {
"localizations": {
"de": {
Expand Down Expand Up @@ -212449,4 +212507,4 @@
} }
},
"version": "1.0"
}
}
20 changes: 16 additions & 4 deletions Strand/Screens/SettingsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,7 @@ struct SettingsView: View {
/// sheets (see the `present(activityItems:)` #455 comment). Same disable-while-busy guard as
/// `rawCsvBusy` above.
@State private var rawAndLogBusy = false
@State private var showRawExportConfirm = false

/// Passive WHOOP 5/MG optical experiment: the picker writes local timestamp markers into the
/// durable deep-buffer JSONL. It never calls a BLE write path.
Expand Down Expand Up @@ -383,6 +384,12 @@ struct SettingsView: View {
} message: {
Text("This restarts the roughly 4-night build-up for Charge and your HRV baseline. Your history stays. Use it if a bad first week, like wearing it while sick, set your baseline off.")
}
.confirmationDialog("Review before sharing", isPresented: $showRawExportConfirm, titleVisibility: .visible) {
Button("Export") { exportRawAndLog() }
Button("Cancel", role: .cancel) { }
} message: {
Text("This export contains raw biometric frames, strap console text, and the connection log. Identifiers are redacted automatically. Share it only if you are comfortable with that.")
}
// #174: the switch going OFF is the moment to offer the undo. Declining leaves the flags set and
// says so — which is still an improvement on the old behaviour, where the same tap silently left
// them set with no indication either way.
Expand Down Expand Up @@ -2303,7 +2310,7 @@ struct SettingsView: View {
// and the strap log together (timestamped, same minute) so a protocol-mapping issue
// arrives with the frames AND the context that produced them.
Button {
exportRawAndLog()
showRawExportConfirm = true
} label: {
if rawAndLogBusy {
HStack(spacing: NoopMetrics.space1 + 2) {
Expand Down Expand Up @@ -2545,10 +2552,15 @@ struct SettingsView: View {
showBackupAlert = true
return
}
var entries = [
FileExport.BundleEntry(name: "report.txt", data: Data(live.exportableLogText().utf8)),
FileExport.BundleEntry(name: "raw-capture.jsonl", data: (try? Data(contentsOf: capture)) ?? Data()),
]
entries = entries.filter { !$0.data.isEmpty }
let redacted = TestBundleAssembler.redactEntries(entries)
let (capped, _) = TestBundleAssembler.capEntries(redacted)
let stamp = FileExport.timestamp()
await FileExport.exportPair(
file: capture, fileSuggestedName: "noop-raw-capture-\(stamp).json",
text: live.exportableLogText(), textSuggestedName: "noop-strap-log-\(stamp).txt")
await FileExport.exportBundle(entries: capped, suggestedName: "noop-export-\(stamp).zip")
}
}

Expand Down
5 changes: 4 additions & 1 deletion android/app/src/main/java/com/noop/ui/LogExport.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import android.widget.Toast
import androidx.core.content.FileProvider
import com.noop.BuildConfig
import com.noop.ble.PuffinExperiment
import com.noop.testcentre.TestBundleAssembler
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.io.File
Expand Down Expand Up @@ -494,8 +495,10 @@ object LogExport {
if (!hasCapture) {
Toast.makeText(context, noCaptureMsg(context, whoop5Connected, encryptedBond, sharingLog = true), Toast.LENGTH_LONG).show()
}
val redacted = TestBundleAssembler.redactEntries(entries)
val (capped, _) = TestBundleAssembler.capEntries(redacted)
val name = "noop-export-${timestamp()}.zip"
exportBundle(context, entries, name)
exportBundle(context, capped, name)
}.onFailure {
Toast.makeText(context, "Couldn't export the pair: ${it.message}", Toast.LENGTH_LONG).show()
}
Expand Down
47 changes: 35 additions & 12 deletions android/app/src/main/java/com/noop/ui/TestCentreScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ fun TestCentreScreen(vm: AppViewModel, onOpenGroundTruthCollector: () -> Unit =
val ecgVariant by vm.ble.whoop5VariantFlow.collectAsStateWithLifecycle()
var rawCaptureBusy by remember { mutableStateOf(false) }
var rawAndLogBusy by remember { mutableStateOf(false) }
var showRawExportConfirm by remember { mutableStateOf(false) }

// A report awaiting the mandatory review-before-share gate (spec section 12). Non-null shows the
// review dialog; confirming runs TestReportFlow.run.
Expand Down Expand Up @@ -361,23 +362,45 @@ fun TestCentreScreen(vm: AppViewModel, onOpenGroundTruthCollector: () -> Unit =
kind = NoopButtonKind.Secondary,
fullWidth = true,
enabled = !rawAndLogBusy,
onClick = {
rawAndLogBusy = true
scope.launch {
try {
LogExport.shareRawAndLog(
context, vm.ble.exportLogText(), live.whoop5Detected, live.encryptedBond,
)
} finally {
rawAndLogBusy = false
}
}
},
onClick = { showRawExportConfirm = true },
)
}
}
}

if (showRawExportConfirm) {
AlertDialog(
onDismissRequest = { showRawExportConfirm = false },
title = { Text(stringResource(R.string.l10n_test_centre_screen_review_before_sharing_d7050383)) },
text = { Text(stringResource(R.string.raw_diag_export_review_body)) },
confirmButton = {
TextButton(onClick = {
showRawExportConfirm = false
rawAndLogBusy = true
scope.launch {
try {
LogExport.shareRawAndLog(
context,
vm.ble.exportLogText(),
live.whoop5Detected,
live.encryptedBond,
)
} finally {
rawAndLogBusy = false
}
}
}) {
Text(stringResource(R.string.l10n_test_centre_screen_export_f3e4fadb))
}
},
dismissButton = {
TextButton(onClick = { showRawExportConfirm = false }) {
Text(stringResource(R.string.l10n_test_centre_screen_cancel_77dfd213))
}
},
)
}

// --- Section 3: Export and auto-export ---
ExportCard(
vm = vm,
Expand Down
1 change: 1 addition & 0 deletions android/app/src/main/res/values-de/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -964,6 +964,7 @@
<string name="l10n_test_centre_screen_report_a_bug_with_my_log_5101ee49">Fehler mit meinem Log melden</string>
<string name="l10n_test_centre_screen_report_ee45c303">Bericht</string>
<string name="l10n_test_centre_screen_review_before_sharing_d7050383">Vor dem Teilen prüfen</string>
<string name="raw_diag_export_review_body">Dieser Export enthält biometrische Rohdaten, Konsolentext des Armbands und das Verbindungsprotokoll. Kennungen werden automatisch geschwärzt. Teile ihn nur, wenn du damit einverstanden bist.</string>
<string name="l10n_test_centre_screen_share_09ca55ca">Teilen</string>
<string name="l10n_test_centre_screen_share_strap_log_for_bug_reports_b9802500">Share strap log (für bug-reports)</string>
<string name="l10n_test_centre_screen_test_centre_37b36828">Testzentrum</string>
Expand Down
1 change: 1 addition & 0 deletions android/app/src/main/res/values-es/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -764,6 +764,7 @@
<string name="l10n_test_centre_screen_report_a_bug_with_my_log_5101ee49">Reportar un error con mi registro</string>
<string name="l10n_test_centre_screen_report_ee45c303">Informe</string>
<string name="l10n_test_centre_screen_review_before_sharing_d7050383">Revisa antes de compartir</string>
<string name="raw_diag_export_review_body">Esta exportación contiene tramas biométricas sin procesar, texto de la consola de la pulsera y el registro de conexión. Los identificadores se ocultan automáticamente. Compártela solo si te sientes cómodo haciéndolo.</string>
<string name="l10n_test_centre_screen_share_09ca55ca">Compartir</string>
<string name="l10n_test_centre_screen_share_strap_log_for_bug_reports_b9802500">Compartir tronco de correa (para informes de fallos)</string>
<string name="l10n_test_centre_screen_test_centre_37b36828">Centro de pruebas</string>
Expand Down
1 change: 1 addition & 0 deletions android/app/src/main/res/values-fr/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -782,6 +782,7 @@
<string name="l10n_test_centre_screen_report_a_bug_with_my_log_5101ee49">Signaler un bug avec mon journal</string>
<string name="l10n_test_centre_screen_report_ee45c303">Signaler</string>
<string name="l10n_test_centre_screen_review_before_sharing_d7050383">Vérifier avant de partager</string>
<string name="raw_diag_export_review_body">Cette exportation contient des trames biométriques brutes, le texte de la console du bracelet et le journal de connexion. Les identifiants sont automatiquement masqués. Ne la partagez que si cela vous convient.</string>
<string name="l10n_test_centre_screen_share_09ca55ca">Partager</string>
<string name="l10n_test_centre_screen_share_strap_log_for_bug_reports_b9802500">Partager le journal du bracelet (pour les rapports de bogue)</string>
<string name="l10n_test_centre_screen_test_centre_37b36828">Centre de test</string>
Expand Down
1 change: 1 addition & 0 deletions android/app/src/main/res/values-pl/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -915,6 +915,7 @@
<string name="l10n_test_centre_screen_report_a_bug_with_my_log_5101ee49">Zgłoś błąd w moim logu</string>
<string name="l10n_test_centre_screen_report_ee45c303">Raport</string>
<string name="l10n_test_centre_screen_review_before_sharing_d7050383">Przejrzyj przed udostępnieniem</string>
<string name="raw_diag_export_review_body">Ten eksport zawiera surowe ramki danych biometrycznych, tekst konsoli opaski i dziennik połączenia. Identyfikatory są automatycznie ukrywane. Udostępnij go tylko, jeśli czujesz się z tym komfortowo.</string>
<string name="l10n_test_centre_screen_share_09ca55ca">Udział</string>
<string name="l10n_test_centre_screen_share_strap_log_for_bug_reports_b9802500">Udostępnij dziennik paska (w przypadku raportów o błędach)</string>
<string name="l10n_test_centre_screen_test_centre_37b36828">Centrum Testowe</string>
Expand Down
1 change: 1 addition & 0 deletions android/app/src/main/res/values-pt-rPT/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -929,6 +929,7 @@
<string name="l10n_test_centre_screen_report_a_bug_with_my_log_5101ee49">Reportar um erro com o meu registo</string>
<string name="l10n_test_centre_screen_report_ee45c303">Relatório</string>
<string name="l10n_test_centre_screen_review_before_sharing_d7050383">Reveja antes de partilhar</string>
<string name="raw_diag_export_review_body">Esta exportação contém tramas biométricas em bruto, texto da consola da bracelete e o registo de ligação. Os identificadores são ocultados automaticamente. Partilha-a apenas se estiveres confortável com isso.</string>
<string name="l10n_test_centre_screen_share_09ca55ca">Partilhar</string>
<string name="l10n_test_centre_screen_share_strap_log_for_bug_reports_b9802500">Partilhar o registo da bracelete (para relatórios de erros)</string>
<string name="l10n_test_centre_screen_test_centre_37b36828">Centro de testes</string>
Expand Down
1 change: 1 addition & 0 deletions android/app/src/main/res/values-ru/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -959,6 +959,7 @@
<string name="l10n_test_centre_screen_report_a_bug_with_my_log_5101ee49">Сообщить об ошибке, приложив журнал</string>
<string name="l10n_test_centre_screen_report_ee45c303">Отчёт</string>
<string name="l10n_test_centre_screen_review_before_sharing_d7050383">Проверьте перед отправкой</string>
<string name="raw_diag_export_review_body">Этот экспорт содержит необработанные биометрические кадры, текст консоли браслета и журнал подключения. Идентификаторы автоматически скрываются. Делитесь им, только если вам это комфортно.</string>
<string name="l10n_test_centre_screen_share_09ca55ca">Поделиться</string>
<string name="l10n_test_centre_screen_share_strap_log_for_bug_reports_b9802500">Поделиться журналом браслета (для отчётов об ошибках)</string>
<string name="l10n_test_centre_screen_test_centre_37b36828">Тестовый центр</string>
Expand Down
1 change: 1 addition & 0 deletions android/app/src/main/res/values-zh/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -907,6 +907,7 @@
<string name="l10n_test_centre_screen_report_a_bug_with_my_log_5101ee49">附带日志报告 Bug</string>
<string name="l10n_test_centre_screen_report_ee45c303">报告</string>
<string name="l10n_test_centre_screen_review_before_sharing_d7050383">在分享前先预览</string>
<string name="raw_diag_export_review_body">此导出包含原始生物识别数据帧、手环控制台文本和连接日志。标识符会自动隐去。请仅在你对此感到放心时分享。</string>
<string name="l10n_test_centre_screen_share_09ca55ca">分享 / 发送</string>
<string name="l10n_test_centre_screen_share_strap_log_for_bug_reports_b9802500">分享手环连接日志 (用于排查 Bug)</string>
<string name="l10n_test_centre_screen_test_centre_37b36828">测试与极客中心</string>
Expand Down
1 change: 1 addition & 0 deletions android/app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1056,6 +1056,7 @@
<string name="l10n_test_centre_screen_report_a_bug_with_my_log_5101ee49">Report a bug with my log</string>
<string name="l10n_test_centre_screen_report_ee45c303">Report</string>
<string name="l10n_test_centre_screen_review_before_sharing_d7050383">Review before sharing</string>
<string name="raw_diag_export_review_body">This export contains raw biometric frames, strap console text, and the connection log. Identifiers are redacted automatically. Share it only if you are comfortable with that.</string>
<string name="l10n_test_centre_screen_share_09ca55ca">Share</string>
<string name="l10n_test_centre_screen_share_strap_log_for_bug_reports_b9802500">Share strap log (for bug reports)</string>
<string name="l10n_test_centre_screen_test_centre_37b36828">Test Centre</string>
Expand Down