v1.1.2
Patch release. Ten user-visible bug fixes and the latest AI model presets. Community reports + fixes from @backmind on most of these.
Added
- Latest AI models in the picker. Claude Opus 5 and Claude Fable 5 join the existing Claude Opus 4.8; Sonnet 5 relabeled. Google Gemini 3.x and OpenAI GPT-5.6 added as presets. Existing saved selections keep working.
Fixed
- The Login and Profile pages no longer render raw i18n keys as UI copy (#33).
en.jsondeclared theloginandprofiletop-level sections twice;JSON.parsesilently keeps only the last (biometric-only) block, dropping 21 login keys and 34 profile keys at runtime. Both sections now hold every key in one block. Also renamed two Settings sidebartitleKeys that pointed at non-existent keys and were rendering raw: AI Assistant now resolves viasettings.trace.sectionand Backup & Restore viasettings.backup.section. Diagnosed by @backmind. - Re-importing an exercise catalog no longer duplicates every row (#34). Every seeder used
INSERT OR IGNOREagainst a table with no UNIQUE constraint, so importing free-db (873 rows), Wger, or ExerciseDB a second time silently doubled the whole library. A one-time boot migration merges duplicates (picks the lowest-id row as survivor, folds non-null user edits from duplicates onto it, rewritesexercise_idreferences inside the JSON blobs inworkout_log/workout_templates/coach_prescriptionsso past workouts + templates + coach prescriptions keep pointing at the right exercise, then deletes the duplicates), free-db now populatesexternal_id, and a partial UNIQUE index locks in the fix. Full-backup restore force-runs the dedupe pass so a backup taken during the bug can't resurrect duplicates. Diagnosed by @backmind. - The All range on Statistics no longer hides body measurements taken before your first workout (#36). The body-weight chart bounded its query by the earliest workout date, but weigh-ins are independent of whether you trained that day. The All range now starts from the same
2000-01-01floor the code already falls back to when there are no workouts. - Logging a cardio session with a distance or a heart rate no longer fails (#41). Both fields are
<input type="number">, so the bound value became a number once you typed in them andnullonce you cleared them; the save path called.trim()on them as if they were still the empty string the form starts with, and threw. Both fields now test for emptiness rather than assuming a string. - Quick-log cardio templates now show up (#43).
GET /api/cardio/templateswas registered belowGET /api/cardio/:date, and Express matches in registration order, so the request was answered by the date handler withtemplatesread as a date. Feature has now worked since it was added. Pinning two sessions of the same activity also no longer gives you two identical chips. - Pre-caching exercise media for offline use no longer fails with "Exercise not found" (#44).
GET /api/exercises/media-urlswas registered belowGET /api/exercises/:idand hit the id handler. Moved above. - Confirmation dialogs with two long button labels no longer overflow the dialog card (#39).
.btncarrieswhite-space: nowrap, so a flex item can never shrink below its one-line text width. Action row now wraps. - The body stats sheet no longer shows its units in capitals (#42). Field labels are uppercased by CSS, which took the unit along with the name and produced
WEIGHT (KG),WAIST (CM). Unit symbols are case-sensitive:kgis kilograms,KGis not a unit. The symbol now opts out of the transform. - Weight placeholders in the workout editor and the plate calculator now follow the kg/lb setting. Both hard-coded pound examples (
e.g. 135,e.g. 225) regardless of preference. - The rest field in the workout editor now reads
REST (s)instead ofREST (S).Sis siemens; seconds iss. - Pull-to-refresh no longer fires mid-page on editor screens. The gesture gated on
window.scrollY, but editor pages use their own scroll container. It now walks to the nearest actually-scrolling ancestor and gates on that.
services:
lifttrace:
image: ghcr.io/traceapps/lifttrace:latest
# …