diff --git a/messages/de.json b/messages/de.json index 1d1ba962d..025a470ec 100644 --- a/messages/de.json +++ b/messages/de.json @@ -4006,6 +4006,7 @@ "import": { "heading": "Import", "description": "Importiere Daten aus einem Apple-Health-Export oder einer JSON-Datei. Bereits vorhandene Einträge werden übersprungen, ein erneuter Import ist also unbedenklich.", + "charCount": "{used} / {max} Zeichen", "appleHealth": { "title": "Apple Health", "description": "Lade die export.zip aus der Health-App auf dem iPhone hoch (Profil → Alle Gesundheitsdaten exportieren).", diff --git a/messages/en.json b/messages/en.json index 3a8b08b12..b66c2383d 100644 --- a/messages/en.json +++ b/messages/en.json @@ -4006,6 +4006,7 @@ "import": { "heading": "Import", "description": "Bring data into HealthLog from an Apple Health export, a JSON file, or a CSV. Imports skip rows that already exist, so re-running one is safe.", + "charCount": "{used} / {max} characters", "appleHealth": { "title": "Apple Health", "description": "Upload the export.zip from the Health app on iPhone (Profile → Export All Health Data).", diff --git a/messages/es.json b/messages/es.json index 210c603ad..2c51a68b8 100644 --- a/messages/es.json +++ b/messages/es.json @@ -4006,6 +4006,7 @@ "import": { "heading": "Importar", "description": "Importa datos a HealthLog desde una exportación de Apple Health o un archivo JSON. La importación omite las filas que ya existen, así que repetirla es seguro.", + "charCount": "{used} / {max} caracteres", "appleHealth": { "title": "Apple Health", "description": "Sube el archivo export.zip de la app Salud del iPhone (Perfil → Exportar todos los datos de salud).", diff --git a/messages/fr.json b/messages/fr.json index e73f56d89..72f2d8a54 100644 --- a/messages/fr.json +++ b/messages/fr.json @@ -4006,6 +4006,7 @@ "import": { "heading": "Import", "description": "Importez des données dans HealthLog depuis un export Apple Santé ou un fichier JSON. L'import ignore les lignes déjà présentes : le relancer est sans risque.", + "charCount": "{used} / {max} caractères", "appleHealth": { "title": "Apple Santé", "description": "Importez le fichier export.zip de l'app Santé sur iPhone (Profil → Exporter toutes les données de santé).", diff --git a/messages/it.json b/messages/it.json index 5e20abdb5..73ca38434 100644 --- a/messages/it.json +++ b/messages/it.json @@ -4006,6 +4006,7 @@ "import": { "heading": "Importa", "description": "Importa dati in HealthLog da un'esportazione di Apple Salute o da un file JSON. L'importazione salta le righe già presenti, quindi ripeterla è sicuro.", + "charCount": "{used} / {max} caratteri", "appleHealth": { "title": "Apple Salute", "description": "Carica il file export.zip dall'app Salute su iPhone (Profilo → Esporta tutti i dati sanitari).", diff --git a/messages/pl.json b/messages/pl.json index f62178eb5..8270e74a9 100644 --- a/messages/pl.json +++ b/messages/pl.json @@ -4006,6 +4006,7 @@ "import": { "heading": "Import", "description": "Zaimportuj dane do HealthLog z eksportu Apple Health lub pliku JSON. Import pomija wiersze, które już istnieją, więc ponowne uruchomienie jest bezpieczne.", + "charCount": "{used} / {max} znaków", "appleHealth": { "title": "Apple Health", "description": "Prześlij plik export.zip z aplikacji Zdrowie na iPhonie (Profil → Eksportuj wszystkie dane zdrowotne).", diff --git a/src/components/settings/import-panel.tsx b/src/components/settings/import-panel.tsx index c87efaee1..879237ceb 100644 --- a/src/components/settings/import-panel.tsx +++ b/src/components/settings/import-panel.tsx @@ -48,6 +48,13 @@ import { cn } from "@/lib/utils"; import { apiFetchRaw, apiGet } from "@/lib/api/api-fetch"; import { CSV_EXAMPLE_COLUMNS } from "@/lib/import/csv-measurements"; +/** + * Upper bound for the paste textareas, mirroring the 16 MB server-side body + * ceiling on `/api/import` and `/api/import/csv`. Caps an accidental over-paste + * before it ever reaches the route and feeds the live character counter. + */ +const MAX_PASTE_CHARS = 16 * 1024 * 1024; + // ─────────────────────────── Section wrapper ─────────────────────────── export function ImportPanel() { @@ -537,10 +544,17 @@ function JsonImportCard() { value={text} onChange={(e) => setText(e.target.value)} rows={5} + maxLength={MAX_PASTE_CHARS} spellCheck={false} placeholder='{"measurements":[…],"moodEntries":[…]}' className="font-mono text-xs" /> +
+ {t("settings.sections.export.import.charCount", { + used: text.length, + max: MAX_PASTE_CHARS, + })} +
setText(e.target.value)} rows={5} + maxLength={MAX_PASTE_CHARS} spellCheck={false} placeholder="type,value,unit,measuredAt,…" className="font-mono text-xs" /> ++ {t("settings.sections.export.import.charCount", { + used: text.length, + max: MAX_PASTE_CHARS, + })} +
void send(true)} data-testid="import-csv-preview" > + {busy && ( +