github DuarteSantos8/openGym v1.3.10

5 hours ago

A new look, a rotation for people who don't train on fixed weekdays, swipe actions, your own
accent colour, and a sync that holds on to every rep. Grab the APK below or pull the new images,
and then update the app on every device you sync. 🏋️

This one grew. The plan was a queue and a rotation; along the way the whole app got a calmer look,
swipe actions arrived, you can pick any accent colour you like, and sync was taken apart and put
back together so that no device can quietly lose your training again. Thirty-five community pull
requests from twelve contributors, fifteen issues closed, and a long night of testing behind it.
Web bundle, APK and API image.

Please update the app on every device that syncs (phone, browser tabs, the Android app). An
older phone keeps working, but only a fully updated set of devices gets all of the new safety
nets. Before you update, open each device once with internet so everything it owes the server has
arrived.

A new design

  • Settings on one screen, with search at the top, your account on a card, and everything else
    on sub-pages: Workout, Reminders, Units & language, Data & backup and friends. Nothing was taken
    away, it just has a home now. Type "rest", "swipe" or "vibrate" and you are there.
  • Plan is two tabs, Schedule and Routines. One switch between a fixed week and a rotation, a
    menu for export, print, import and starter plans, and the weekly muscle volume moved to Stats.
  • A workout screen that gets out of your way. The tab bar steps aside while you train, a
    labelled Finish, grouped ⋯ menus, a small thumbnail of the exercise, and the rest timer docked
    as one row at the bottom. Tap its clock to set the time left.
  • A rest-time wheel, iPhone style, for anything from 0:00 to 15:00, in Settings, in the new
    in-workout settings sheet and per exercise. Done without scrolling leaves your rest alone.
  • The in-workout settings sheet: rest timer, sound, vibrate, flash, screen awake, layout and
    effort without leaving the session.
  • Finish opens a small sheet: finish and save, or discard. And any set's menu can turn it into
    a warm-up set on the spot (or back).
  • One icon per idea. The shuffle icon used to mean twelve different things. Not any more.
  • New profiles start with smaller exercise animations and "weigh in before workouts" off. Your
    existing profile keeps whatever you had.

Rotation and the session queue

  • A rotation beside the fixed week (#158, #69; kurktchiev's #167 and giulioleuci's kurktchiev#1).
    A, B, C, A, ...: the next session is the next one you haven't done, whatever the weekday, so a
    missed Tuesday no longer shoves the plan around. Build the loop in Plan, reorder it, start a new
    pass whenever you like. Switching back to a fixed week asks first and leaves your weekdays as
    they were.
  • Home shows what is next, how much of the pass is done, and when the next one starts. A coach
    app that writes your week through the API is marked "Externally managed".
  • Planned vs completed weekly volume per muscle (EmilZapata, #333, #327), now on Stats, with
    each queue or rotation session counted once.

Swipe actions

  • Swipe a set left to delete it, with Undo, or right to copy it. In cards, list and compact,
    mirrored in Arabic. The last set stays put ("Keep at least one set, champ"). A timed per-side
    hold slides its left and right rows together.
  • Swipe in Plan: a routine left to delete (with Undo), right to duplicate; an exercise out of
    the routine editor or a routine out of the loop, with Undo too.
  • One switch for all of it, "Swipe actions" (Settings → Workout → Fine-tuning, or the in-workout
    settings sheet), on by default.

Your own colour

  • Any accent colour you like, from the rainbow swatch after the presets. openGym checks it
    against light and dark and nudges it until text on it stays readable. It syncs like the presets.

Safer sync, and no more lost data

This is the part we are proudest of, and the part you will hopefully never notice. Most of these
could already happen in v1.3.9:

  • Every change carries its own stamp, down to a single setting, plan day or routine field. Two
    devices editing the same routine now merge field by field instead of one copy winning whole.
  • A phone whose clock runs late no longer loses its edits and deletions.
  • A deletion stays deleted, even when another device changes something unrelated afterwards,
    and the order of your routines survives a conflict.
  • Two tabs in one browser no longer overwrite each other or the running workout, and signing
    out or switching accounts with a second tab open leaves nothing behind.
  • Signing out during a workout no longer deletes it, and signing in with a guest plan asks
    first. Anything that does not fit lands under Settings as kept changes, with "Save as a backup
    file", instead of disappearing.
  • A server that falls back to an older copy (say, from a backup) is merged with, not trusted
    blindly. A full disk or a slow answer can no longer hand a device an old state.
  • Importing a backup keeps the workout you are in the middle of, whether it replaces or merges.
  • On the server: every write is flushed to disk before openGym says "saved", a copy of the last
    good db.json is kept as db.json.bak, and the server starts from that copy if the main file
    is damaged. We killed it eighty times mid-write; every confirmed save was on disk.

Reminders and alerts

  • The missed-workout nudge (opt-in): one push on the evening of a planned day you skipped, in
    the tone you pick: Friendly, Guilt trip or Drill sergeant. It backs off after three missed days
    in a row and never bothers you on a rest day.
  • Vibrate on silent too (noname-nan, #375), Android: the end of a rest or a hold buzzes like
    an alarm even when the phone is on silent. Off by default.
  • The rest alarm on Android rings even when the notification permission dialog is still open, and
    a killed app brings its rest bar and countdown back.
  • "Rest over" rings only the device that rested (kurktchiev, #348).
  • Classic beeps (tomlongfield, #372): the quieter three-beep sound from before 1.3.9 is back as
    a choice.

More in the workout and history

  • Repeat today (Space-Hermes, #58): open a past workout in History and start it again today.
  • Pyramid sets (NtsCiccio, #367, #362): one rep target per set (12 · 8 · 6 · Max), a rest per
    set, and a "Max reps" chart in Stats.
  • Per side on timed holds (horusglez, #322): left and right each run the full hold, with a
    10-second "switch sides" pause in between.
  • Progress photos (horusglez, #361): every photo kept with a workout on one timeline, with a
    before/after slider.
  • Update routine from the session (FranciscoFavela, #336): copy an exercise's warm-ups, rest and
    note back into its routine.
  • "Last time" in days, weeks or months (xwr3, #363) instead of a date. Hover for the full one.
  • Pick your own backup folder on Android (#161), for example a sync app's folder.

Community pull requests

Thank you, all of you. This release is half yours.

Bug fixes

  • Custom exercises can be edited and deleted again, including older ones and ones from a shared
    or Coach plan (Teo230, #358; svillar, #378).
  • The up and down arrows move an exercise within a superset, and out of it at the edge (svillar,
    #377).
  • Strong's current export, the one with semicolons, imports again (davidjorgensen, #394).
  • Pairing the phone app says why it failed: a proxy or CORS rule in the way, a login page answering
    in openGym's place, or a server that can't be reached (#329).
  • A cardio block or a long hold at the end no longer shortens the workout's duration.
  • 8.5 in a reps field no longer becomes 85, a running plank survives a reload, and the rest timer
    stops when you sign out.
  • Loading the same starter plan twice no longer doubles your routines; a custom exercise can share
    a name with a catalogue one; an equipment profile no longer hides imported custom exercises.
  • Plates: a single stack counts each pair properly.
  • Imports refuse impossible dates and numbers (year 9999, negative, 1e308 kg), a Hevy session over
    midnight keeps its length, a zip's photos upload straight away, and the summary says how many
    rows it skipped.
  • Workouts dated later today are no longer in the future, durations and body weight have sane
    limits, and the weight axis never says "-0".
  • Passkey, pairing and import errors speak your language instead of developer English.
  • Polish and Ukrainian plurals are right everywhere (#365), "Drop {0}" means a drop set in every
    language, and long labels no longer get cut off in Russian, Portuguese, Hungarian or German.
  • Android: status bar icons readable in the light theme, Back works after "All settings" and from
    the Start menu, and no tab bar on the very first screen.
  • Without an account, nobody can flood the admin log with junk sign-ins or fill the server with
    pairing codes.

For self-hosters

  • FIRST_USER_ADMIN=1 (seals187, #328), opt-in: the first profile on an empty instance becomes
    its admin. Off by default; if you turn it on, register yourself before you share the address.
  • BASE_PATH (#346): serve openGym under a sub-path such as /gym. The web container checks
    the value at start-up.
  • Phone app and CORS (#329): a new section in SELF_HOSTING.md on proxies
    that answer or change the CORS preflight (Traefik headers middleware, a second
    Access-Control-Allow-Origin, SSO in front of /api/), with a one-line curl check. openGym
    handles CORS itself, so leave it alone on the openGym route.
  • Show connection status (seals187, #330; xwr3, #369): Settings → Look & Home can hide the
    sync line at the top. A dot on Home still warns when sync is stuck.
  • Durable writes: every file the API keeps is flushed before it is renamed into place, and
    ./data/db.json.bak holds a copy of the last good db.json. Back up ./data as before.
  • If you build your own API image from a copy of the Dockerfile: it now also needs queue.js,
    nudge.js, nudge-copy.js, durable.js and sync-stamps.js.
  • PASSWORD_LOGIN is unchanged and still off by default.
  • build-api-docs --check runs in CI (#342).

Known limit while old phones are around

The server stamps what a v1.3.9 phone sends, so most things just work. Until every device is
updated, though, an old phone can't always say what it has seen: if it sets something back to
exactly what it was before, after another device changed it, the other device's change loses.
Workouts that v1.3.9 deleted offline and never uploaded may come back once; delete them again and
they stay gone. Anything the update had to set aside is under Settings as "This device, before the
update". Once everything is on 1.3.10, none of this applies.

Languages

  • 🇹🇼 Traditional Chinese (nauish, #368): eighteen languages now. Browsers set to zh-Hant,
    zh-HK or zh-MO open in it.
  • Every string reworded to sound more human, with fewer long dashes and a bit more fun.

Credits

Code from @kurktchiev, @giulioleuci, @EmilZapata, @horusglez, @NtsCiccio, @FranciscoFavela, @dima-po, @nauish,
@tomlongfield, @alessandromoretti90, @olivierbbommel and @tfdmendes. Bug reports and ideas from
@Gitoffomalawn, @Space-Hermes, @seals187, @schklom, @LaDaniWapa, @jdpiqueras1979, @Teo230, @xwr3,
@noname-nan, @svillar, @davidjorgensen, @EmilZapata and @NtsCiccio, plus everyone on Discord who
told us where it hurt. Thank you!

Install

  • Android: download openGym-1.3.10.apk below (or update from inside the app).
    SHA-256 1527d58866f97a380c555351cbdc0934c341eb4d8fbe034a2ed002f51278cc65, signing certificate 0d22a49e… (unchanged)
  • Docker: git pull && docker compose pull && docker compose up -d
    Images 1.3.10, 1.3, latest (amd64 + arm64) on registry.gitlab.com/duartesantos8/opengym: api sha256:bb3af45b…, web sha256:15e7c311…

Full history: CHANGELOG.md

Don't miss a new openGym release

NewReleases is sending notifications on new releases.