Skip to content
Merged
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
29 changes: 27 additions & 2 deletions lib/data/nutrition_store.dart
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,17 @@ class NutritionDb {
);
}

/// Rewrite an existing entry in place: same id, same `created_at`, so it
/// keeps its place in [recent] and a CSV export still shows when it was
/// first logged. Totals and averages are rolled up from the table on every
/// read, so an edit lands exactly as a delete-then-add would. Same
/// [FoodEntry.sanitised] guard as [put].
static Future<void> update(Database db, FoodEntry e) async {
final row = e.sanitised.toRow(DateTime.now().millisecondsSinceEpoch)
..remove('created_at');
await db.update('food_entry', row, where: 'id = ?', whereArgs: [e.id]);
}

static Future<void> delete(Database db, String id) =>
db.delete('food_entry', where: 'id = ?', whereArgs: [id]);

Expand Down Expand Up @@ -510,12 +521,26 @@ class NutritionDb {
/// The last distinct things eaten, newest first. This is what makes a repeat
/// entry a two-second job, and it is why there is no need for a "favourites"
/// concept on top.
static Future<List<FoodEntry>> recent(Database db, {int limit = 12}) async {
///
/// [query] narrows it to labels containing that text, over the WHOLE
/// history rather than the last few — the search on the log sheet.
static Future<List<FoodEntry>> recent(
Database db, {
int limit = 12,
String query = '',
}) async {
final q = query.trim();
final rows = await db.rawQuery(
'SELECT * FROM food_entry WHERE id IN '
'(SELECT MAX(id) FROM food_entry GROUP BY label) '
"${q.isEmpty ? '' : r"AND label LIKE ? ESCAPE '\' "}"
'ORDER BY created_at DESC LIMIT ?',
[limit],
[
// `%` and `_` are literal text in a food name, not wildcards.
if (q.isNotEmpty)
'%${q.replaceAllMapped(RegExp(r'[\\%_]'), (m) => '\\${m[0]}')}%',
limit,
],
);
return [for (final r in rows) FoodEntry.fromRow(r)];
}
Expand Down
12 changes: 11 additions & 1 deletion lib/l10n/app_de.arb
Original file line number Diff line number Diff line change
Expand Up @@ -2607,5 +2607,15 @@
"dataBackupFolderSub": "Wähle, wo neue Sicherungen gespeichert werden. Vorhandene Sicherungen bleiben an ihrem bisherigen Ort",
"dataBackupFolderUseDefault": "Standardordner verwenden",
"dataBackupFolderSaved": "Sicherungsordner gespeichert.",
"dataBackupFolderRetry": "Versuche es mit Jetzt sichern erneut oder wähle einen anderen Ordner"
"dataBackupFolderRetry": "Versuche es mit Jetzt sichern erneut oder wähle einen anderen Ordner",
"logFoodEditTitle": "Eintrag bearbeiten",
"logFoodDateLabel": "Datum",
"logFoodTimeLabel": "Uhrzeit",
"logFoodSearchLabel": "Deine Lebensmittel durchsuchen",
"logFoodSearchHint": "Alles, was du erfasst hast",
"logFoodSearchNoMatch": "Nichts, was du erfasst hast, passt dazu.",
"logFoodRemoveEntry": "Eintrag entfernen",
"nutritionProteinToday": "Protein heute",
"nutritionProteinToGo": "Noch {grams} g",
"nutritionTargetReached": "Ziel erreicht"
}
45 changes: 45 additions & 0 deletions lib/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -14527,6 +14527,51 @@
}
}
},
"logFoodEditTitle": "Edit this entry",
"@logFoodEditTitle": {
"description": "Log food sheet: title when editing an existing entry"
},
"logFoodDateLabel": "Date",
"@logFoodDateLabel": {
"description": "Log food sheet: row label for the day the food was eaten"
},
"logFoodTimeLabel": "Time",
"@logFoodTimeLabel": {
"description": "Log food sheet: row label for the time the food was eaten"
},
"logFoodSearchLabel": "Search your foods",
"@logFoodSearchLabel": {
"description": "Log food sheet: label of the search field over past foods"
},
"logFoodSearchHint": "Anything you have logged",
"@logFoodSearchHint": {
"description": "Log food sheet: hint in the search field over past foods"
},
"logFoodSearchNoMatch": "Nothing you have logged matches that.",
"@logFoodSearchNoMatch": {
"description": "Log food sheet: shown when the search over past foods finds nothing"
},
"logFoodRemoveEntry": "Remove this entry",
"@logFoodRemoveEntry": {
"description": "Log food sheet: button that removes the entry being edited"
},
"nutritionProteinToday": "Protein today",
"@nutritionProteinToday": {
"description": "Nutrition Today tab: label of the protein-versus-target card"
},
"nutritionProteinToGo": "{grams} g to go",
"@nutritionProteinToGo": {
"description": "Nutrition Today tab: grams of protein still needed to reach the target",
"placeholders": {
"grams": {
"type": "int"
}
}
},
"nutritionTargetReached": "Target reached",
"@nutritionTargetReached": {
"description": "Nutrition Today tab: protein target met or exceeded"
},
"dayTimelineZoomNoHr": "No heart rate in this stretch",
"@dayTimelineZoomNoHr": {"description": "Shown in place of the zoomed day chart when the chosen window has no heart rate."},
"dayTimelineZoomPerMinute": "1-minute averages. Drag the handles to zoom; two hours or less shows every second while it is still kept.",
Expand Down
12 changes: 11 additions & 1 deletion lib/l10n/app_es.arb
Original file line number Diff line number Diff line change
Expand Up @@ -2517,5 +2517,15 @@
"dataBackupFolderSub": "Elige dónde guardar las nuevas copias. Las copias existentes permanecen donde están",
"dataBackupFolderUseDefault": "Usar carpeta predeterminada",
"dataBackupFolderSaved": "Carpeta de copias guardada.",
"dataBackupFolderRetry": "Reintenta con Crear copia ahora o elige otra carpeta"
"dataBackupFolderRetry": "Reintenta con Crear copia ahora o elige otra carpeta",
"logFoodEditTitle": "Editar esta entrada",
"logFoodDateLabel": "Fecha",
"logFoodTimeLabel": "Hora",
"logFoodSearchLabel": "Busca tus alimentos",
"logFoodSearchHint": "Cualquier cosa que hayas registrado",
"logFoodSearchNoMatch": "Nada de lo que has registrado coincide.",
"logFoodRemoveEntry": "Eliminar esta entrada",
"nutritionProteinToday": "Proteína de hoy",
"nutritionProteinToGo": "Faltan {grams} g",
"nutritionTargetReached": "Objetivo alcanzado"
}
12 changes: 11 additions & 1 deletion lib/l10n/app_fr.arb
Original file line number Diff line number Diff line change
Expand Up @@ -2488,5 +2488,15 @@
"dataBackupFolderSub": "Choisissez où enregistrer les nouvelles sauvegardes. Les sauvegardes existantes restent à leur emplacement",
"dataBackupFolderUseDefault": "Utiliser le dossier par défaut",
"dataBackupFolderSaved": "Dossier de sauvegarde enregistré.",
"dataBackupFolderRetry": "Réessayez avec Sauvegarder maintenant ou choisissez un autre dossier"
"dataBackupFolderRetry": "Réessayez avec Sauvegarder maintenant ou choisissez un autre dossier",
"logFoodEditTitle": "Modifier cette entrée",
"logFoodDateLabel": "Date",
"logFoodTimeLabel": "Heure",
"logFoodSearchLabel": "Rechercher vos aliments",
"logFoodSearchHint": "Tout ce que vous avez noté",
"logFoodSearchNoMatch": "Rien de ce que vous avez noté ne correspond.",
"logFoodRemoveEntry": "Supprimer cette entrée",
"nutritionProteinToday": "Protéines aujourd’hui",
"nutritionProteinToGo": "Encore {grams} g",
"nutritionTargetReached": "Objectif atteint"
}
12 changes: 11 additions & 1 deletion lib/l10n/app_hi.arb
Original file line number Diff line number Diff line change
Expand Up @@ -2488,5 +2488,15 @@
"dataBackupFolderSub": "चुनें कि नए बैकअप कहाँ सहेजे जाएँ। पुराने बैकअप अपनी जगह पर रहेंगे",
"dataBackupFolderUseDefault": "डिफ़ॉल्ट फ़ोल्डर इस्तेमाल करें",
"dataBackupFolderSaved": "बैकअप फ़ोल्डर सहेजा गया।",
"dataBackupFolderRetry": "अभी बैकअप लें से फिर कोशिश करें या दूसरा फ़ोल्डर चुनें"
"dataBackupFolderRetry": "अभी बैकअप लें से फिर कोशिश करें या दूसरा फ़ोल्डर चुनें",
"logFoodEditTitle": "यह एंट्री बदलें",
"logFoodDateLabel": "तारीख",
"logFoodTimeLabel": "समय",
"logFoodSearchLabel": "अपने खाने खोजें",
"logFoodSearchHint": "जो कुछ भी आपने दर्ज किया है",
"logFoodSearchNoMatch": "आपकी दर्ज की गई चीज़ों में कुछ नहीं मिला।",
"logFoodRemoveEntry": "यह एंट्री हटाएँ",
"nutritionProteinToday": "आज का प्रोटीन",
"nutritionProteinToGo": "{grams} g बाकी",
"nutritionTargetReached": "लक्ष्य पूरा"
}
17 changes: 17 additions & 0 deletions lib/l10n/app_ru.arb
Original file line number Diff line number Diff line change
Expand Up @@ -6835,6 +6835,23 @@
"investigateRmssdNightly": "RMSSD, ночной (среднее по 5-минутным окнам)",
"investigateRmssdStored": "RMSSD, ночной (прежняя оценка)",
"devicesOuraWriteRefused": "Не удалось отправить команду кольцу. Попробуйте синхронизировать ещё раз.",
"logFoodEditTitle": "Изменить запись",
"logFoodDateLabel": "Дата",
"logFoodTimeLabel": "Время",
"logFoodSearchLabel": "Поиск по вашей еде",
"logFoodSearchHint": "Всё, что вы записывали",
"logFoodSearchNoMatch": "Среди ваших записей ничего не нашлось.",
"logFoodRemoveEntry": "Удалить запись",
"nutritionProteinToday": "Белок сегодня",
"nutritionProteinToGo": "Осталось {grams} г",
"@nutritionProteinToGo": {
"placeholders": {
"grams": {
"type": "int"
}
}
},
"nutritionTargetReached": "Цель достигнута",
"dayTimelineZoomNoHr": "На этом отрезке нет данных о пульсе",
"dayTimelineZoomPerMinute": "Средние за минуту. Потяните ползунки, чтобы приблизить; при окне до двух часов показывается каждая секунда, пока она хранится.",
"dayTimelineZoomPerMinuteOnly": "Средние за минуту. Посекундные данные для этого отрезка уже не хранятся.",
Expand Down
12 changes: 11 additions & 1 deletion lib/l10n/app_zh.arb
Original file line number Diff line number Diff line change
Expand Up @@ -2488,5 +2488,15 @@
"dataBackupFolderSub": "选择新备份的保存位置。现有备份仍保留在原位置",
"dataBackupFolderUseDefault": "使用默认文件夹",
"dataBackupFolderSaved": "已保存备份文件夹。",
"dataBackupFolderRetry": "点击立即备份重试,或选择其他文件夹"
"dataBackupFolderRetry": "点击立即备份重试,或选择其他文件夹",
"logFoodEditTitle": "编辑这条记录",
"logFoodDateLabel": "日期",
"logFoodTimeLabel": "时间",
"logFoodSearchLabel": "搜索你的食物",
"logFoodSearchHint": "你记录过的任何食物",
"logFoodSearchNoMatch": "你的记录里没有匹配的内容。",
"logFoodRemoveEntry": "删除这条记录",
"nutritionProteinToday": "今日蛋白质",
"nutritionProteinToGo": "还差 {grams} 克",
"nutritionTargetReached": "已达目标"
}
Loading
Loading