Commit graph

14 commits

Author SHA1 Message Date
d078db7288 POI overlay on maps: circular contrasting icons + category filter (offline)
Points of interest (cafe, shops, water, toilets, bank/ATM, bus, shelter,
viewpoint, ...) as circular contrasting badges (emoji in a white/dark circle,
readable on light and dark tiles) — not pins. A 📍 control toggles the layer
and opens a per-category filter (checkboxes, remembered). Markers are culled to
the visible bounds and shown from zoom 13 (cap 500/view), on the recording,
track-detail and roads maps.

Data is bundled and fully offline: frontend/data/pois.json ([{la,lo,c,n}], 358KB,
5662 POIs) fetched once from Overpass for ~100km around region (the whole
bbox returned in one query; adaptive subdivision was ready if it had truncated).

Verified functionally on device: 124 badges rendered in view at z16 over
region with correct bounds/category culling; the live visual could not be
screenshotted (the WebView surface is black under CDP). frontend/data + poi.js.
2026-09-09 16:51:58 +03:00
f7b45d98f0 Product catalog cleanup (no-badge unused) + order-independent search
- searchProducts: order-independent token AND (every whitespace word must appear
  in name, any order), ranked full-substring > prefix > length. Fixes needing to
  type words in the name's order.
- Cleanup of unlabeled junk (health-diet/ashan/fast-food, null source): keep-list
  = magnit,5ka,ion,kdv,manual,recipe_import,gridnev. DB.cleanupUnlabeledProducts
  deletes non-keep AND unused (food_log/recipe_ingredients protected); Settings
  button 'Очистить продукты без магазина' with a counted appConfirm.
- Seed products_seed.db cleaned: 24443 -> 13008 (non-keep removed), seed_meta
  version 10 -> 11, VACUUM (13.5MB -> 8.9MB). So future imports don't re-add junk.
  On-device 11207 unused non-keep will be removed via the button (24 eaten stay).
2026-08-25 18:23:51 +03:00
50ec5c21f8 Health-diet.ru products (24K), GPS session safety, build.sh upload fix
Products:
- health-diet.ru scraper (Tampermonkey) + import script
- 11469 products with 37 nutrients, Dodo 258, McDonalds 619, KFC 361, Ashan 2000
- Rust import_seed_products: dynamic column list, auto-create missing columns
- Seed version bumped to 10

GPS session safety:
- Separate gps_points_{ts}.jsonl per session, deleted only after DB save
- Toast on DB errors, NaN guard in finishGpsSession

Other:
- build.sh: router/VPS upload only with -u flag
- Orientation buttons bottom-right, weather via Yandex Pogoda
2026-06-28 23:17:51 +03:00
19282ded78 Sensors, walk limits, GPS fixes, water UI, manual routes, Gridnev products, OTA router
GPS altitude: accel-based glitch filter (accel=0 + speed = GPS drift), altitude
  jump >100m filter, timestamp sanity (>24h = remove). Per-point Crr from accel
  vibration (smooth/mixed/gravel). Gap interpolation on map with dashed lines
  when accel confirms movement. Walk/run separate speed limits (configurable).
  Adaptive GPS accuracy (auto x2 when signal bad). Dead reckoning points when
  GPS silent but accel shows movement. Locale.US fix for sensor JSON.

Sensors: accelerometer + gyroscope in GpsRecorderService (RMS, max, pitch, yaw).
  Columns in gps_points. Dynamic addGpsPoint INSERT (safe if columns missing).

Manual routes: draw on map by tapping points, elevation from past tracks +
  open-meteo API, realistic timestamps by activity speed. Manual sessions
  skip glitch filtering on recalculate. Speed from GPS.config not hardcoded.

Water tracking: water_pct field in product add/edit forms, searchProducts
  returns water_pct, "ml" label for liquids, recipe water from ingredients.

BMR: moving average weight (7 days), fixed charts using dailyBase not raw bmr.

BLE: ble_clear_hr on stop, recovery toast, serde alias for ts/timestamp.

Products: 217 Gridnev products (bakery, desserts, bread, ready meals).
  Magnit scraper fix (NUXT_DATA name/value pairs, not indices). Supplements
  addSupplement with all 41 columns. Nutrient fallback RDI includes omega/EPA/DHA.

Export/import: custom products + recipes + supplements in single JSON bundle.
  Export all or single product. Dedup on import by name_lower + source.

OTA: router upload (LAN, always), VPS upload (-u flag). Kotlin checks router
  first (2s timeout), then VPS. Update URL from update_info.json.

Session detail: renderToken prevents stale setTimeout callbacks after recalculate.
WAL disabled (PRAGMA journal_mode=DELETE).
2026-06-18 22:54:45 +03:00
0136b8ae0e Dedup products, fix labels, fix track comparison, seed v9
1. Deduplicate products: 13482 -> 8325 in seed DB. JS migration
   deduplicates app DB on launch: reassigns food_log and
   recipe_ingredients to kept product before deleting dupes.

2. MICRO_FIELDS: full chemical names + alternatives for all nutrients.
   "B3 / PP / ниацин", "B9 / фолиевая", "Кальций / Ca" etc.

3. Track comparison: newer track always compared against older.
   Green = newer faster (progress), Red = newer slower (regression).
   Removed separate cyan dashed track — only colored segments.
   Order of selection doesn't matter — date determines which is newer.

4. Source badges in search: source column was already in SELECT,
   badges render via sourceBadge(p.source) in prod card.

5. Gap threshold already cosmetic-only (confirmed, no changes needed).

Seed DB v9, VACUUM'd, indexed.
2026-05-30 18:09:16 +03:00
44dfa0b88a Add name_lower index: seed import 56s -> 0.09s (600x faster)
ATTACH UPDATE with correlated subqueries on name_lower was doing
full table scans on 13000 rows. 56 seconds on desktop, 2-5 min
on phone. User saw "загрузка..." for minutes on every launch.

Fix: CREATE INDEX on name_lower in both main and seed DBs before
the UPDATE. Also pre-built index in seed DB file.

Benchmarked: 56.5s -> 0.09s on desktop. Phone should be <1s.
2026-05-30 16:24:47 +03:00
2df5908fca Fix product save: add name_lower, product-only micro fields, strawberry
Root cause: addProduct INSERT didn't include name_lower column.
Search uses WHERE name_lower LIKE — products with NULL name_lower
never found. User entered 20 min of strawberry data for nothing.

Fixes:
- addProduct: includes name_lower = name.toLowerCase()
- Added phosphorus_mg and carotene_mcg to addProduct INSERT
- PRODUCT_MICRO_FIELDS: subset of MICRO_FIELDS for product forms
  (excludes supplement-only fields: omega, EPA/DHA, fish oil etc.)
- showAddProductModal and showEditProductModal use PRODUCT_MICRO_FIELDS
- Rust: removed stale inserted+=1 line
- Seed DB v8: added "Клубника свежая" (alias for "Земляника садовая")
2026-05-30 15:33:59 +03:00
3789747729 Edit product from search card, fix Ayutinskiy bread kcal
Product editing:
- "Ред." button on expanded product card
- showEditProductModal: edit name, KBJU, all micronutrients
- Updates product in DB directly, refreshes search

Bread fix:
- "Хлеб Тостовый пшеничный Аютинский 280г" was 268 in Magnit data
- Package says 243 kcal/100g — corrected in seed DB
- Seed version 7

Users can now fix any wrong KBJU directly from the product card
without re-importing or editing the seed DB manually.
2026-05-29 22:01:52 +03:00
4d97ba607b Always copy seed DB from assets, VACUUM seed to reclaim space
Size comparison was unreliable — SQLite reuses free pages internally,
so adding products didn't change file size. New seed never copied.
Now: always overwrite on every launch (~8MB, <1 sec).
VACUUM reduced seed from 8.5MB to 8.2MB.
2026-05-29 15:38:10 +03:00
de5cfd5c21 Manual KBJU input, omega-3/6/9, product micronutrients, nutrient strip expand
1. Manual food entry: added B/Zh/U fields. Creates custom product in DB
   with user-provided KBJU, then logs it. Fixed addProduct lastInsertId.

2. Omega 3-6-9: columns in supplements, in supplement totals query,
   in MICRO_FIELDS form (34 fields total now).

3. Product card micronutrients: searchProducts now fetches all micro
   columns. renderProdDetails shows nutrient chips (sorted by deficiency)
   when product is expanded.

4. Supplement form: added B5, B7, chromium, manganese, molybdenum,
   iodine, phosphorus, omega-3/6/9, silicon, vanadium, lutein, lycopene.

5. Nutrient strip: tap to expand/collapse. Collapsed = 1 row (36px).
   Tap = toggle full view showing all nutrients.

6. Seed DB v6: added "Тесто для чебуреков 500г" (261 kcal, 7.1/3.8/48.2).
2026-05-29 14:47:09 +03:00
18738dc0aa Clean up nutrients_guessed: removed 222 false positives
Removed guessed flag + micronutrients from:
- Pet food, cosmetics, cleaning products (25)
- Chips, crackers, snacks (44)
- Chocolate, candy, cakes, waffles, bars (42)
- Cookies/biscuits (23, kept liver "печень")
- Pelmeni, sausages, kolbasa, kotlety (43)
- Baby food purees, ready meals, baked goods (45)

Kept: dairy (yogurt, kefir, tvorog, milk, smetana, slivki),
eggs, grains, vegetables, fruits, raw meats, fish, oils.
1398 legitimately guessed products remain. Seed version 5.
2026-05-23 18:10:00 +03:00
3e5333cec6 Recipes, nutrients_guessed, seed import fixes, search improvements
Recipes:
- Cooking methods table + 6 presets (boiling, frying, steaming etc.)
- Recipe editor with live KBJU calculation including cooking loss
- Recipe detail view, log-to-diary, ingredient search
- Split food log into "Products" and "Dishes" sections
- Products screen sub-tabs: Продукты / Рецепты

Nutrient enrichment:
- 1620 store products enriched with ION micronutrients (guessed flag)
- Purple tint on guessed food entries, * on daily kcal total
- Seed DB v4 with nutrients_guessed column

Seed import fixes:
- Rust: always refresh seed DB from bundled assets on launch
- Rust: check app_config_dir for main DB (plugin-sql stores there on desktop)
- Rust: ATTACH-based UPDATE to sync nutrients_guessed for existing products
- Rust: read all 27 columns including micronutrients
- Rust: emit seed_progress events + indeterminate progress bar animation
- JS: boot screen with status labels during migrations/import
- JS: nutrients_guessed column created in JS migration as safety net

Search:
- Results sorted by starts-with-query first, then by name length
- Default limit raised to 200
- Modal search results scroll without max-height cap

Bug fixes:
- product_id=0 for custom recipe ingredients (NOT NULL constraint)
- getRecipe JOIN for cooking_method_name
- calcTotals applies cooking loss from selected method
- Ingredient modal targets last overlay (not parent)
- select elements dark theme (color-scheme: dark)
- renderToday wrapped in try/catch
2026-05-21 00:06:50 +03:00
0032c309b7 Seed DB: +5ka (3103) +ION (1078) with micronutrients, GPS fixes, UI improvements
Products:
- 5ka scraper: recursive category BFS, 3103 products imported
- ION scraper (web.ion.ru): fetch-based, 1111 products with full vitamins/minerals
- Seed DB now 13480 products (magnit 8627, 5ka 3103, ion 1078, kdv 672)
- 13 micronutrient columns added: Na, K, Ca, Mg, P, Fe, vit A/B1/B2/B3/C/E, carotene

GPS fixes:
- computeStats sorts points by seq/ts before calculating (fixes wrong elevation/kcal)
- Trail restore on recording screen sorts points
- Old tracks with NULL seq repaired via migration (db.js)
- Activity type saved to localStorage, restored on GPS screen

UI:
- Track points invisible but tappable (popup with time/alt/speed)
- Charts: pointer-events:none on canvas when minimized (page scrolls)
- Navigation history stack (20 entries), back gesture doesn't close app
- Session list sort: added id DESC tiebreaker
2026-05-19 23:53:49 +03:00
2ca2181e09 Seed products DB + Settings screen + build fixes
Products seed: 9299 products bundled in products_seed.db, Kotlin
copies from assets to filesDir on Android, Rust imports into main
DB on first launch with version check for future updates.

Settings: profile button, offline toggle, GPS permission, app info
with git hash and build date from build.rs.

Build: version synced to Cargo.toml, unified import (GPX/FTB by
extension), chart zoom Ctrl+scroll only, scroll wheel zoom disabled
on detail map.
2026-05-14 17:35:29 +03:00