From 9a8ef042308533ef9f50bb3aa4ab3968a57ddf8b Mon Sep 17 00:00:00 2001 From: 4aiman Date: Sat, 24 Oct 2026 01:29:30 +0300 Subject: [PATCH] =?UTF-8?q?Hydration:=20water=20intake=20from=20the=20food?= =?UTF-8?q?=20log,=20drop=20the=20"+=D0=B2=D0=BE=D0=B4=D0=B0"=20button?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Intake is what you already log (liquids count via water_pct), so there is nothing to tap mid-ride and no guessing an amount. At session start JS seeds the native deficit from the food log — need-so-far for the time of day minus logged intake — via set_hydration_config(start_deficit_ml); the service then accrues sweat on top. Removes the +вода button, hydration_drink and water_drink.txt. --- PROJECT_MAP.md | 2 +- README.md | 2 +- .../2026-10-24_hydration-reminder.md | 19 ++++---- frontend/js/db.js | 14 ------ frontend/js/main.js | 43 ++++++++++--------- src-tauri/Cargo.lock | 2 +- src-tauri/Cargo.toml | 2 +- .../src/main/java/dev/baldav/app/Hydration.kt | 30 +++++-------- src-tauri/src/lib.rs | 26 +++-------- src-tauri/tauri.conf.json | 2 +- 10 files changed, 56 insertions(+), 86 deletions(-) diff --git a/PROJECT_MAP.md b/PROJECT_MAP.md index 7fef30d..7ae9e02 100644 --- a/PROJECT_MAP.md +++ b/PROJECT_MAP.md @@ -53,7 +53,7 @@ |------|-------|------------| | `MainActivity.kt` | ~300 | FileObserver IPC, seed DB, safe insets, SAF, BLE commands, OTA check | | `GpsRecorderService.kt` | ~530 | Foreground service GPS, WakeLock, JSONL (один файл на сессию до Стоп, идемпотентный onStartCommand при START_STICKY-перезапуске ОС; `bindSessionIfPending()` дописывает id сессии в имя файла `_s` по `gps_session.txt`), 50Hz акселерометр/гироскоп, dead reckoning, raw sensor files. Тикает `Hydration` каждые 10с | -| `Hydration.kt` | ~110 | Уровневое напоминание пить (синглтон на процесс, дедуп GPS+HR сервисов). `reset()` при старте сессии, `tick()` копит потребность (`sweatMlPerHour`), минус выпитое из `water_drink.txt`; сигнал (ALARM-канал) + вибро + уведомление при дефиците >= `alertMl`, повтор через `reAlertMin`. Конфиг `hydration.json`. Rust: `set_hydration_config`, `hydration_drink(ml)` | +| `Hydration.kt` | ~110 | Уровневое напоминание пить (синглтон на процесс, дедуп GPS+HR сервисов). `reset()` при старте сессии -> `tick()` сидит стартовый дефицит `startDeficitMl` (JS считает из лога: норма ко времени минус выпитое) + копит пот (`sweatMlPerHour`); сигнал (ALARM-канал) + вибро + уведомление при дефиците >= `alertMl`, повтор `reAlertMin`. Конфиг `hydration.json`. Вода - из залогированной жидкости, без кнопки. Rust: `set_hydration_config`. JS: `seedHydrationDeficit()` на старте записи | | `BleHrService.kt` | ~390 | Foreground service BLE HR, FitPro protocol, GATT queue, scan/connect. START_NOT_STICKY; скан не нашёл адрес -> stopSelf (не держит радио). Подключение инициируется ТОЛЬКО вручную (кнопка в настройках), не при старте записи. Выключение BT в любой момент не роняет app: единый `handler` (все postDelayed, снимаются разом), `BroadcastReceiver` на `ACTION_STATE_CHANGED` -> на STATE_OFF чистая остановка (disconnect+stopSelf), все нативные BLE-вызовы (scan/stopScan/connectGatt/writeCharacteristic/discoverServices) в try/catch. Каждый замер ЧСС дописывается в `ble_hr_log.jsonl` (append) прямо в сервисе — запись истории переживает гаснущий экран (JS-поллинг в фоне заморожен Android); воркаут при остановке пересобирает сэмплы из этого лога (`GPS._readHrLogSamples`), а не из JS-массива. Авто-реконнект: обрыв УЖЕ установленного соединения (connectedOnce) переподключается через скан (до 3 попыток, 8с), сброс бюджета при успехе; если скан не нашёл ремень или это stopping (ACTION_STOP/BT-off/onDestroy) - stopSelf, не долбится в отсутствующий/не запущенный вручную ремень. Наработка ремня: `accrueUptime`/`writeUptimeFile` копят время реальной отдачи ЧСС (только промежутки без разрывов) + шаги заряда в `strap_uptime.json` (персистентно, не чистится per-session, flush ~20с и при обрыве) | | `generated/*.kt` | ~1100 | Tauri-сгенерированные: WebView, IPC, permissions | diff --git a/README.md b/README.md index 50755c6..fecea16 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ - **Дистанция на разрывах GPS** — на «слепых» участках (интервал между фиксами > `gapThresholdSec`) путь считается по скорости (speed×dt, с ограничением по макс. скорости), а не прямой хордой — иначе разрывы занижают/искажают длину. Телепорт-скачки без временного разрыва отбрасываются. Расчёт зависит только от времени и скорости, поэтому live-счётчик, «Стоп» и пересчёт дают одинаковую длину. Порог `gapThresholdSec` настраивается; при изменении и пересчёте применяется сразу. - **Тренировки** — приседания (подходы x повторения), скакалка, растяжки, бассейн (дистанция). Автоматический расчёт ккал по MET и весу. - **Нутриенты** — 37 микронутриентов (витамины, минералы, жирные кислоты, женьшень, ресвератрол, CoQ10). Нормы РСП/АУП (РФ/ЕС/США). Фармакокинетика — запасы в организме по полураспаду. -- **Трекинг жидкости** — water_pct в продуктах, прогресс-бар, настраиваемая норма. На тренировке (велозаезд/VR) - уровневое напоминание пить: нативный сервис копит потребность в воде (пот) за время активности, кнопка «+вода» на записи гасит отставание; громкий сигнал на канале будильника (пробивает громкость) только когда отстаёшь сверх порога. Молчит, пока успеваешь пить. +- **Трекинг жидкости** — water_pct в продуктах, прогресс-бар, настраиваемая норма. На тренировке (велозаезд/VR) - уровневое напоминание пить: на старте приложение берёт твой водный баланс из лога (норма ко времени дня минус выпитое, посчитанное из залогированной жидкости), дальше нативный сервис копит потребность (пот) за активность; громкий сигнал на канале будильника (пробивает громкость) только когда отстаёшь сверх порога. Вода - из того, что логируешь, отдельной кнопки нет. - **Графики** — скорость, высота, ЧСС тренировки с зумом и pan. Тренд веса. Донат макронутриентов. Баланс ккал (приход/расход). - **OTA обновления** — проверка BUILD_NUMBER на роутере (LAN) или VPS, скачивание через браузер. - **Ручные маршруты** — рисование трека на карте тапами, elevation из прошлых треков или open-meteo API. diff --git a/docs/session-logs/2026-10-24_hydration-reminder.md b/docs/session-logs/2026-10-24_hydration-reminder.md index e4b2a10..8866a58 100644 --- a/docs/session-logs/2026-10-24_hydration-reminder.md +++ b/docs/session-logs/2026-10-24_hydration-reminder.md @@ -5,20 +5,23 @@ уровневая модель: во время активности копится потребность в воде (пот), кнопка «+вода» гасит отставание; громкий сигнал только когда дефицит превышает порог. -## Реализация +## Реализация (финал) - `Hydration.kt` (новый) - синглтон на процесс (оба сервиса в одном процессе -> дедуп, нет двойных - бипов на заезде с ремнём). `tick()` копит `sweatMlPerHour` за время, вычитает выпитое из - `water_drink.txt`, сигналит (ToneGenerator STREAM_ALARM - пробивает громкость + вибро + - уведомление) при дефиците >= `alertMl`, повтор через `reAlertMin`. Конфиг `hydration.json`. + бипов на заезде с ремнём). `reset()` при старте сессии -> `tick()` сидит стартовый дефицит + `startDeficitMl` и копит `sweatMlPerHour`; сигнал (ToneGenerator STREAM_ALARM - пробивает + громкость + вибро + уведомление) при дефиците >= `alertMl`, повтор `reAlertMin`. Конфиг `hydration.json`. - `GpsRecorderService.kt` (велозаезд) и `BleHrService.kt` (VR) тикают `Hydration` (reset при старте). -- Rust: `set_hydration_config(enabled, alert_ml, sweat_ml_per_hour, re_alert_min)`, - `hydration_drink(ml)` (пишет в `water_drink.txt`, оба пути корня). Манифест: VIBRATE. -- JS: настройка в профиле (вкл, сигнал при отставании мл, +вода за нажатие мл); кнопка «+вода» на - экране записи -> `hydration_drink` + `DB.logWaterDrink` (ищет 100%-воду, идёт в дневной итог). +- Rust: `set_hydration_config(enabled, alert_ml, sweat_ml_per_hour, re_alert_min, start_deficit_ml)`. + Манифест: VIBRATE. +- JS: настройка в профиле (вкл, сигнал при отставании мл); `seedHydrationDeficit()` на старте записи + считает стартовый дефицит из ЛОГА (норма ко времени дня минус выпитое из `getDailyWaterMl`). + Вода берётся из залогированной жидкости, отдельной кнопки НЕТ. ## Эволюция (несколько итераций по уточнениям) - Сначала привязал к HR-сервису (VR). Исправлено: главное - велик, значит GPS-сервис. - Сначала фиксированный интервал. Исправлено: не таймер, а УРОВЕНЬ (дефицит), молчит пока пьёшь. +- Сначала кнопка «+вода» + ручной слив. Исправлено: вода из потребления (лога), кнопка не нужна - + пользователь не знает, сколько и чего вводить; стартовый дефицит считается из дневного water_pct. ## Статус Собрано (0.1.519), JS/Rust/Kotlin компилируются. Залито на роутер diff --git a/frontend/js/db.js b/frontend/js/db.js index 9199cbc..eda3781 100644 --- a/frontend/js/db.js +++ b/frontend/js/db.js @@ -507,20 +507,6 @@ async function deleteFoodEntry(id) { await execute("DELETE FROM food_log WHERE id = ?1", [id]); } -// Quick "+вода": log a plain-water drink so the daily water total/bar reflects it. Finds a -// ~100% water product at runtime (no hardcoded id). The hydration deficit is handled separately -// (Rust hydration_drink -> native service). Returns true if it could log to the daily total. -async function logWaterDrink(ml) { - const now = new Date(); - const date = now.toISOString().slice(0, 10); - const time = now.toTimeString().slice(0, 5); - const rows = await select("SELECT id FROM products WHERE water_pct >= 99 ORDER BY water_pct DESC LIMIT 1"); - if (!rows.length) return false; - await addFoodEntry(date, time, rows[0].id, ml, "вода", null, null); - return true; -} -window.DB.logWaterDrink = logWaterDrink; - // --------------------------------------------------------------------------- // Activity log // --------------------------------------------------------------------------- diff --git a/frontend/js/main.js b/frontend/js/main.js index 8cbe71a..f96fd1a 100644 --- a/frontend/js/main.js +++ b/frontend/js/main.js @@ -2783,6 +2783,26 @@ let gpsMap = null; let gpsTrailLine = null; let gpsMarker = null; +// At session start, seed the native hydration deficit from the FOOD LOG: how far behind on water +// you are for the time of day (need-so-far minus logged intake). During the session the native +// service adds sweat on top. Intake comes from what you log, not a button. +async function seedHydrationDeficit() { + if (localStorage.getItem("baldav_hydr_on") !== "1") return; + try { + let target = parseInt(state.profile?.daily_water_ml) || 2000; + let now = new Date(); + let nowMin = now.getHours() * 60 + now.getMinutes(); + let wakeStart = 7 * 60, wakeEnd = 23 * 60; // assume waking 07:00–23:00 + let frac = Math.max(0, Math.min(1, (nowMin - wakeStart) / (wakeEnd - wakeStart))); + let needSoFar = target * frac; + let intake = await DB.getDailyWaterMl(now.toISOString().slice(0, 10)); + let startDeficit = Math.max(0, Math.min(5000, Math.round(needSoFar - intake))); + let alertMl = parseInt(localStorage.getItem("baldav_hydr_alert")) || 600; + await window.__TAURI__.core.invoke("set_hydration_config", + { enabled: true, alertMl, sweatMlPerHour: 600, reAlertMin: 15, startDeficitMl: startDeficit }); + } catch (e) { console.error("seedHydration", e); } +} + async function renderGpsScreen(container) { // Check Bluetooth state if BLE device is paired let bleAddr = await DB.getProfileValue("ble_device_addr"); @@ -2897,6 +2917,7 @@ async function renderGpsScreen(container) { heightCm: parseFloat(state.profile?.height_cm) || 178, } : null; await GPS.startRecording(type, wkg, hrProfile); + seedHydrationDeficit(); renderScreen("recording"); } }; @@ -4976,21 +4997,6 @@ async function renderRecordingInline(container) { darkBtn.onclick = () => toggleDarkMap(); btnWrap.appendChild(darkBtn); - // +вода: записать выпитое — гасит отставание (сигнал гидратации замолкает) и идёт в дневной итог. - let waterBtn = document.createElement("button"); - waterBtn.className = "rec-map-btn rec-water-btn"; - waterBtn.textContent = "💧"; - waterBtn.title = "Записать воду"; - waterBtn.onclick = async () => { - let ml = parseInt(localStorage.getItem("baldav_hydr_drink")) || 500; - try { await window.__TAURI__.core.invoke("hydration_drink", { ml }); } catch (e) { console.error("drink", e); } - try { await DB.logWaterDrink(ml); } catch (e) { console.error("logWater", e); } - showToast(`+${ml} мл воды`); - waterBtn.classList.add("active"); - setTimeout(() => waterBtn.classList.remove("active"), 800); - }; - btnWrap.appendChild(waterBtn); - // Nogo: mark the current spot impassable while riding (the planner + on-the-fly reroute // will avoid it). Shows existing nogo circles too. let recNogoLayer = null; @@ -8203,9 +8209,8 @@ function showProfileModal() { Следить за питьём на тренировке -
Во время заезда/VR копится потребность в воде (пот). Молчит, пока успеваешь пить; громкий сигнал (канал будильника, пробивает громкость) - только когда отстаёшь. Кнопка «+вода» на записи гасит отставание.
+
Во время заезда/VR копится потребность в воде (пот), а выпитое берётся из того, что ты логируешь в баланс (жидкость по water_pct). Молчит, пока успеваешь пить; громкий сигнал (канал будильника, пробивает громкость) - только когда отстаёшь сверх порога.
- `, async overlay => { let weight = parseFloat(overlay.querySelector("#m-weight").value) || null; @@ -8225,11 +8230,9 @@ function showProfileModal() { await DB.setProfileValue("daily_water_ml", waterNorm); let hydrOn = !!overlay.querySelector("#m-hydr-on")?.checked; let hydrAlert = Math.min(3000, Math.max(100, parseInt(overlay.querySelector("#m-hydr-alert")?.value) || 600)); - let hydrDrink = Math.min(2000, Math.max(50, parseInt(overlay.querySelector("#m-hydr-drink")?.value) || 500)); localStorage.setItem("baldav_hydr_on", hydrOn ? "1" : "0"); localStorage.setItem("baldav_hydr_alert", String(hydrAlert)); - localStorage.setItem("baldav_hydr_drink", String(hydrDrink)); - try { await window.__TAURI__.core.invoke("set_hydration_config", { enabled: hydrOn, alertMl: hydrAlert, sweatMlPerHour: 600, reAlertMin: 15 }); } catch (e) { console.error("hydration cfg", e); } + try { await window.__TAURI__.core.invoke("set_hydration_config", { enabled: hydrOn, alertMl: hydrAlert, sweatMlPerHour: 600, reAlertMin: 15, startDeficitMl: 0 }); } catch (e) { console.error("hydration cfg", e); } state.profile = { ...state.profile, weight_kg: weight ? weight : state.profile.weight_kg, diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index cf49b3e..fd12a41 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -139,7 +139,7 @@ checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "baldav" -version = "0.1.519" +version = "0.1.520" dependencies = [ "base64 0.22.1", "btleplug", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 159bea9..ff7b647 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "baldav" -version = "0.1.519" +version = "0.1.520" edition = "2021" [lib] diff --git a/src-tauri/gen/android/app/src/main/java/dev/baldav/app/Hydration.kt b/src-tauri/gen/android/app/src/main/java/dev/baldav/app/Hydration.kt index b2ae5f8..c56839b 100644 --- a/src-tauri/gen/android/app/src/main/java/dev/baldav/app/Hydration.kt +++ b/src-tauri/gen/android/app/src/main/java/dev/baldav/app/Hydration.kt @@ -23,7 +23,9 @@ import org.json.JSONObject object Hydration { private const val TAG = "Hydration" private const val CH = "baldav_hydration" - private var accruedMl = 0.0 // need accrued since session start, minus what was drunk + private var accruedMl = 0.0 // running water deficit: start-of-session shortfall + sweat + private var startDeficitMl = 0.0 // how far behind you were at session start (from the food log) + private var pendingStart = false // apply startDeficitMl on the first tick after reset() private var lastTickMs = 0L private var lastBeepMs = 0L private var lastCfgMs = 0L @@ -41,37 +43,27 @@ object Hydration { sweatMlPerMin = j.optInt("sweatMlPerHour", 600).coerceIn(60, 2000) / 60.0 alertMl = j.optInt("alertMl", 600).coerceIn(100, 3000).toDouble() reAlertMs = j.optInt("reAlertMin", 15).coerceIn(2, 120) * 60_000L + startDeficitMl = j.optInt("startDeficitMl", 0).coerceIn(0, 5000).toDouble() } else enabled = false } catch (e: Exception) { Log.e(TAG, "cfg: ${e.message}"); enabled = false } } - // Call at session start: clear the deficit so a fresh ride/workout starts from zero. - fun reset() { accruedMl = 0.0; lastTickMs = 0L; lastBeepMs = 0L } + // Call at session start: next tick re-reads the config and seeds the deficit from the food log. + fun reset() { lastTickMs = 0L; lastBeepMs = 0L; pendingStart = true } - // "+вода" writes the drunk ml here (Rust hydration_drink); subtract and consume. - private fun drainDrinks(ctx: Context) { - try { - val f = File(ctx.filesDir.parentFile ?: ctx.filesDir, "water_drink.txt") - if (f.exists()) { - val ml = f.readText().trim().toDoubleOrNull() ?: 0.0 - f.delete() - accruedMl -= ml - if (accruedMl < 0) accruedMl = 0.0 - } - } catch (e: Exception) { Log.e(TAG, "drink: ${e.message}") } - } - - // Call often (every 10-30 s) from any running service. Accrues need, honours drinks, beeps only - // when behind. At most one beep per re-alert window across all callers (process-wide singleton). + // Call often (every 10-30 s) from any running service. Deficit = start-of-session shortfall (from + // logged intake vs need-so-far) + accrued sweat. Beeps only when behind, at most once per re-alert + // window across all callers (process-wide singleton). Water intake comes from what you log, not a + // button — nothing to tap mid-ride; you top up and log it as usual, next session re-seeds. fun tick(ctx: Context, handler: Handler) { val now = System.currentTimeMillis() if (now - lastCfgMs > 30_000L) { readCfg(ctx); lastCfgMs = now } if (!enabled) return + if (pendingStart) { accruedMl = startDeficitMl; pendingStart = false } if (lastTickMs == 0L) { lastTickMs = now; return } val dtMin = (now - lastTickMs) / 60_000.0 lastTickMs = now accruedMl += sweatMlPerMin * dtMin - drainDrinks(ctx) if (accruedMl >= alertMl && now - lastBeepMs >= reAlertMs) { lastBeepMs = now beep(handler); vibrate(ctx); notify(ctx, accruedMl.toInt()) diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index ae1c68b..719a001 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -498,32 +498,18 @@ fn gps_service_command(app: tauri::AppHandle, cmd: String) -> Result Result { +fn set_hydration_config(app: tauri::AppHandle, enabled: bool, alert_ml: u32, sweat_ml_per_hour: u32, re_alert_min: u32, start_deficit_ml: u32) -> Result { let json = format!( - "{{\"enabled\":{},\"alertMl\":{},\"sweatMlPerHour\":{},\"reAlertMin\":{}}}", - enabled, alert_ml.clamp(100, 3000), sweat_ml_per_hour.clamp(60, 2000), re_alert_min.clamp(2, 120) + "{{\"enabled\":{},\"alertMl\":{},\"sweatMlPerHour\":{},\"reAlertMin\":{},\"startDeficitMl\":{}}}", + enabled, alert_ml.clamp(100, 3000), sweat_ml_per_hour.clamp(60, 2000), re_alert_min.clamp(2, 120), start_deficit_ml.clamp(0, 5000) ); write_app_root_file(&app, "hydration.json", &json); Ok(json) } -// "+вода": add drunk ml to water_drink.txt (read-add-write), which the Hydration singleton consumes -// on its next tick to reduce the deficit. Lands in both candidate app-root paths so Kotlin finds it. -#[tauri::command] -fn hydration_drink(app: tauri::AppHandle, ml: u32) -> Result { - // Read the current pending amount from the explicit app root (= Kotlin filesDir.parentFile), - // the same file the Hydration singleton deletes, so the running total stays consistent. - let explicit_root = app.path().app_data_dir().ok() - .and_then(|d| d.parent().and_then(|p| p.parent()).map(|p| p.to_path_buf())); - let cur: f64 = explicit_root.as_ref() - .and_then(|r| std::fs::read_to_string(r.join("water_drink.txt")).ok()) - .and_then(|s| s.trim().parse().ok()).unwrap_or(0.0); - let total = cur + ml as f64; - write_app_root_file(&app, "water_drink.txt", &format!("{}", total)); - Ok(format!("{}", total)) -} - // Write a small file to the app root — both where native_root resolves and the explicit // app_data_dir/../.. (= Kotlin filesDir.parentFile) — so the Kotlin side always finds it. fn write_app_root_file(app: &tauri::AppHandle, name: &str, contents: &str) { @@ -1222,7 +1208,7 @@ pub fn run() { .add_migrations("sqlite:baldav.db", migrations) .build(), ) - .invoke_handler(tauri::generate_handler![get_safe_insets, import_seed_products, import_tiles, download_file, get_points_filename, delete_points_file, gps_set_session_id, list_points_files, read_points_file, pick_file_open, get_picked_file, debug_native_paths, rebuild_roads, get_road_points, get_ride_graph, get_app_info, gps_service_command, set_hydration_config, hydration_drink, gps_service_read_points, brouter_route, brouter_download_tile, brouter_download_status, brouter_list_tiles, save_file, export_image, read_file_base64, export_db, import_db, restart_app, get_update_info, http_request, chzn_http, ble::ble_scan, ble::ble_scan_results, ble::ble_connect, ble::ble_disconnect, ble::ble_get_hr, ble::ble_is_connected, ble::ble_check_bluetooth, ble::ble_save_device, ble::ble_clear_hr, ble::ble_read_hr_log, ble::ble_read_strap_uptime, ble::ble_reset_strap_uptime, ble::ble_request_enable, read_state_file]) + .invoke_handler(tauri::generate_handler![get_safe_insets, import_seed_products, import_tiles, download_file, get_points_filename, delete_points_file, gps_set_session_id, list_points_files, read_points_file, pick_file_open, get_picked_file, debug_native_paths, rebuild_roads, get_road_points, get_ride_graph, get_app_info, gps_service_command, set_hydration_config, gps_service_read_points, brouter_route, brouter_download_tile, brouter_download_status, brouter_list_tiles, save_file, export_image, read_file_base64, export_db, import_db, restart_app, get_update_info, http_request, chzn_http, ble::ble_scan, ble::ble_scan_results, ble::ble_connect, ble::ble_disconnect, ble::ble_get_hr, ble::ble_is_connected, ble::ble_check_bluetooth, ble::ble_save_device, ble::ble_clear_hr, ble::ble_read_hr_log, ble::ble_read_strap_uptime, ble::ble_reset_strap_uptime, ble::ble_request_enable, read_state_file]) .run(tauri::generate_context!()) .expect("error while running tauri application"); } diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index d8914fb..a28d3e8 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -1,7 +1,7 @@ { "$schema": "https://raw.githubusercontent.com/nicegui/tauri-v2/refs/heads/main/tooling/cli/schema.json", "productName": "BalDav", - "version": "0.1.519", + "version": "0.1.520", "identifier": "dev.baldav.app", "build": { "frontendDist": "../frontend"