github ulsklyc/yuvomi v2.67.0

12 hours ago

Added

  • The cycle tab grows into a full tracker: visible flow strength, feelings, more fertility
    signals, hard-private intimacy logging, PMS patterns, and a "today" insight bubble.
    The day log
    gains cervical mucus, LH and pregnancy tests, multi-select feelings (replacing the single mood),
    and intimacy - cervical mucus, the two test results and intimacy are never shown to anyone but
    yourself, even on days shared with the family, enforced by the server. On
    POST /api/v1/health/cycle/logs, mood (kept for older clients) and feelings now both accept
    only the fixed feelings list - an out-of-list value is a 400 instead of being stored as free text.
    Saving a day log through the app always sends the current feelings selection, so an older
    free-text mood value is cleared the next time that day is edited in the app; only a save that
    omits both fields entirely (outside the app's own form) leaves it as-is. Flow strength finally
    shows up everywhere it matters: a four-step dot scale on the calendar, a heaviest-flow chip per
    period in the history, a per-cycle flow intensity chart, and a calm hint when recent periods run
    repeatedly heavy or over a week. A bubble at the top answers the daily question at a glance -
    cycle day and phase, plus whichever of these applies: period expected today (start it right
    there), symptoms likely today, a PMS window approaching, or the fertile window. Predictions got
    more honest along the way: a temperature-confirmed ovulation now also moves the month calendar
    (ring and calendar can no longer disagree), implausible gaps from overlapping or future-dated
    periods no longer poison the averages (the period dialog warns about both), the BBT chart spaces
    its points by real dates and breaks across logging gaps, and the likelihood overlay projects into
    the next cycle instead of only backwards. New per-person settings: contraception (hormonal methods
    pause the fertile-window prediction, with the reason shown instead of an empty tile), a
    perimenopause mode that predicts a date range rather than a false-precision single day, a
    PMS-window toggle, and an opt-in partner reminder that shares only the predicted date - never any
    log content. Period history can be imported from CSV (German date and separator formats included),
    the Health overview shows the next period at a glance, and the trends section was restructured
    around one expander per symptom with an added feelings-by-phase view and a pain summary.

  • New optional module: Waste collection (#1063). Define your household's waste types
    (recycling, organic, general, or your own, each with an icon and color) and a weekly or
    fixed-day-of-month pickup schedule for each. A single calculated pickup can be moved to a
    different date or skipped without touching the rest of the schedule, and moving one origin never
    hides another - a manual one-off pickup recorded on the same day a schedule occurrence moved away
    from still shows. One-off pickups cover irregular or special collections that are not part of any
    recurring schedule. A type with schedules or pickups cannot be deleted (archive it instead), so a
    season's history is never lost by accident. Off by default; a household turns it on in
    Settings → Modules. A municipality's ICS calendar file can also be imported: preview its pickups,
    map each label to a waste type (or create one on the spot, or ignore it), and commit - the file is
    re-parsed on commit so nothing is trusted from the preview alone, and re-importing next year's file
    diffs cleanly into additions/changes/removals without duplicating or losing manual data. A source
    with no future mapped pickup is flagged for a refresh. An optional Dashboard widget shows the next
    pickup per active type, soonest first, and carries the same "needs a refresh" flag as the module
    page; hidden by default, like the module itself. A device-local Calendar layer, off by default,
    shows every type's pickups in month, week, day, and agenda view; a pickup carries its type's icon
    and color and opens the module directly, never the ordinary event editor. Beyond a one-time file
    import, a source can also subscribe to an ICS URL: it refreshes itself automatically on a
    configurable schedule (hourly to monthly), applying an update only once every label already has a
    confirmed mapping - unrecognized content is flagged for review instead of guessed at, and a manual
    "check now" is always available alongside the automatic schedule. Each household member can also opt
    into their own pickup reminders per waste type, choosing how many days ahead and what time of day
    (household-local) to be notified - personal, so a reminder never goes to someone who didn't ask for
    it. A monthly schedule can now also follow an ordinal weekday - "the second Monday" or "the last
    Friday" of every month - alongside the existing weekly and fixed-day-of-month rhythms; the
    underlying shared recurrence engine gained this once and every existing recurring feature (Tasks,
    Calendar, CalDAV/ICS import) benefits from it, not just Waste. A revocable, personal read-only ICS
    feed of upcoming pickups is now available too (Settings → Feeds), with an optional per-type
    selection; a source's label-to-type mapping decisions can be exported as a portable profile and
    re-applied to another source or household, without the app ever shipping a municipal/provider
    catalog. Waste types are now searchable from the global search bar, and the Calendar layer's filter
    sheet gained a per-type visibility list nested under the one Waste toggle, so a rare collection is
    never silently hidden while a noisy one can be tucked away.

  • Waste page UX: labelled add-type entry point, unified row actions, curated type colors (#1146).
    The page now leads with a labelled "Add waste type" button rather than hiding all four actions
    behind one unlabelled menu, both empty states offer the step their own text describes, and the
    pickup button no longer dead-ends on a fresh install - without a type it now opens the type dialog
    instead of only saying that one is missing. Waste type, schedule, and source rows carry the same
    single overflow menu with named entries that the pickup rows already used, so a destructive action
    is no longer one stray tap away and an action whose meaning changes with the source finally says
    which one it is; every one of those menus now sits at the trailing edge of its row, and every row
    puts its icon beside the name instead of above it, so all four row types read the same way. A
    paused schedule is now visually distinct from an archived type instead of wearing the same badge.
    A type's color comes from a curated palette instead of a free color picker, which had happily
    accepted a white or black icon that then disappeared against the light or dark background - an
    existing color outside the palette is kept, not silently overwritten.

  • A fasting journal records timers and past fasts in Health (Refs #1173).
    Start now or earlier, record completed intervals, and edit or undo changes with
    conflict protection. Elapsed/remaining clocks, personal goals and an optional
    educational dial preserve the recorded time zone. History loads ten records at
    a time; date filters and CSV cover the complete visible history. Family members
    can read shared records; personal settings stay private. Fasting is available to
    every member by default and an admin can switch it off per family role or person.
    Yuvomi records fasting and does not provide medical advice.

  • A calendar's default assignee can now be applied to the events it already imported (#1154).
    Until now the mapping only reached events that arrived after it was set, so the first thing
    anyone saw after mapping a calendar was a list of unassigned events. Settings → Sync gains a
    one-off "Apply to existing appointments" action for admins: it runs over the calendars of all
    accounts that have a default assignee, names how many events it will touch, and fills only
    events that are not assigned to anyone yet. An assignment made by hand is left alone. ICS
    subscriptions are not included.

  • The Housekeeping Reports tab can step through past months (#1137). Until now it only ever
    showed the current month, and older reports were reachable only through a single worker in the
    Staff tab. A previous/next stepper with a jump back to the current month now sits next to the
    title, in the same order as Budget. The chosen month stays put while you work in it: marking a
    visit paid or editing one reloads that month instead of jumping back, and an empty month says
    which month it is.

  • A shopping list can be duplicated (#1103). "Duplicate" sits in the list menu next to
    rename/delete and copies every item into a new list, with category assignment and the manual
    per-category order always carried over - that is the point of duplicating, not a switch. Three
    flags control the rest: reset checked state, keep quantities, and keep notes & links, all on by
    default.

    A duplicated item is a new, local item: CalDAV sync fields, the originating meal, any recorded
    price or shop, and tags are never copied. The first three each name something true of the
    original item only (a synced remote object, a specific meal, a price actually paid in a specific
    shop), never of a fresh copy - and tags are mirrored VTODO categories, so they follow the same
    rule as the sync fields they belong to.

  • A shopping suggestion carries its category and quantity (#1113, from discussion #1103).
    Picking a suggestion while adding an item now also fills in that item's most recently used
    category and quantity, instead of only its name - without the category, every picked suggestion
    landed back in the fallback category and the aisle order had to be re-sorted on the next trip.
    Suggestions are also now ordered by most recently used first, instead of alphabetically - a
    household buys the same handful of things again and again, and the ones bought last stood out
    less behind everything the alphabet puts first. For API users this is a contract change on
    GET /api/v1/shopping/suggestions: the response items are now objects { name, category, quantity } ordered by recency, where they used to be plain name strings.

  • A shopping list follows what the rest of the household does, while it is open (#1108). Two people
    in the same shop used to see two different lists: what one ticked off stayed unticked on the
    other's phone until that page was reloaded. The open list now hears about changes within about ten
    seconds and redraws the affected rows in place - the same gesture as your own tap, no jump, no
    animation - and rebuilds only when an item was added, removed, renamed or moved.

    The server keeps a change counter per list, maintained by database triggers rather than by the
    routes: shopping items are written from six modules (the list itself, meal-plan and recipe
    imports, the housekeeping module, MCP, the CalDAV to-do sync), and a counter that every writer
    has to remember is a counter one of them forgets. The counter also moves when a list is renamed,
    and its row goes with the list, so a list someone else deletes disappears from your screen too.
    The open page asks GET /api/v1/shopping/versions every ten seconds while the tab is visible,
    and at once when it becomes visible or gets focus - the moment somebody looks at the phone. It
    reloads only a list whose number moved, through the same request it used to open it, so there
    is still one read path. Deliberately a poll and not an open stream: it works through any
    reverse proxy, holds no connection, and can grow into a stream on the same counter later. Your
    own taps do not cost a reload: the write routes answer with the counter before and after, and
    the page skips the reload when nothing else moved in between.

  • BIND_ADDRESS sets the address the server listens on. Unset, nothing changes: the app
    listens on all interfaces, which is exactly what a container needs for its published port to
    reach it, so Docker, Podman, Unraid, TrueNAS and Umbrel installations leave it alone. When Node
    runs directly on a machine behind a reverse proxy on that same machine, 127.0.0.1 keeps the
    app itself off the network. The built-in MCP bridge follows the setting when it calls the API
    back. It is not the same as OIKOS_HTTP_BIND, which decides where the container engine
    publishes the port.

Changed

  • Housekeeping staff and shared-expense guests no longer appear where you pick or list household
    members
    (#1207). The pickers for task assignees, calendar attendees, budget responsibles,
    schedule owners, medication owners, synced-calendar assignees and the Outlook account owner, the
    family list, the calendar's person filter, mentions, the reward standings and enrolment and the
    Overview's member cards now show household members only, and the household size counts them the
    same way - a household of one person and a cleaner is a household of one for what the app shows.
    Visibility, locking and document sharing stay available as long as anyone else can read the
    module, a cleaner with access included, so a new entry can still be kept private. Splitting an expense
    still offers the guests of that group, and guests can still be added to a group; housekeeping
    staff cannot. Nothing is taken away: a task, event, budget entry, schedule, synced calendar or
    document share that already names a staff member or guest keeps them, still shows them in its
    editor and can still be saved, and an event's visibility stays as it was. Existing group
    memberships stay as well and still show in the group editor, so they can be ended. An old reward
    enrolment of a staff member or guest stays on record, but it no longer earns points, redeems or
    receives a bonus. Schedule
    rows on the dashboard keep their names; only choosing a staff member or guest anew is refused.
    User administration and permissions still list every account, API tokens every account except
    shared-expense guests as before, and the two-factor overview for admins now shows every account,
    housekeeping staff and guests included.
  • The README is shorter between the introduction and the install steps (#1212). Each module
    gets one line in the module table, with the detail left to the spec, and "Before you commit" -
    what happens if the project stops, how to take your data elsewhere, what it costs - now comes
    before the first command instead of after it. The install section opens with the three ways in,
    lists the encryption key and the blocking of addresses on your own network as facts that apply
    to every path, and names the logs command for both Docker and Podman.

Fixed

  • A request with an API token is judged by the token's own role, even when an admin session comes
    along.
    If the same client also sent the session cookie of a signed-in administrator, a request
    made with a member's API token could still pass as an administrator in several places: calendar
    subscriptions and events, locked tasks, household note categories, documents and DMS connections,
    recipe providers, the shift schedule and split expenses. Each of them had its own admin check that
    also looked at the session. They now use the same check as every other route, which looks only at
    the role of the person the token belongs to. Signing in as an administrator without a token keeps
    full access, and a request with only a session or only a token behaves as before.

  • Form fields have a clearly visible edge in both themes. Text inputs, selects and text areas
    drew their resting edge in the same faint shade as card and group outlines, which rendered at 1.2
    to 1.5:1 against the surface around them - well below the 3:1 a control boundary needs for people
    to find the field at all. Fields now have an edge color of their own, at 3.2 to 3.5:1 in the light
    theme and 3.9 to 5.5:1 in the dark theme on every surface they sit on: the sign-in page, dialogs,
    settings pages, the search overlay, and the search and quick-add fields above the lists. Card
    edges and separators keep their quieter shade, and a focused field still takes the accent color.

  • Set-aside cards and rows stay readable. Done and archived tasks (in the list and on the
    board), archived accounts, paused and completed subscriptions, inactive medications and rewards,
    archived waste types, paused pickups, and rows that an import has already added all faded out by
    turning partly transparent. That pulled every text on them below the 4.5:1 normal text needs,
    status badges and the initials in avatars included: 1.7 to 3.9:1 in the light theme, 2.4 to
    4.2:1 in the dark theme. They now recede in one consistent way instead: the card sinks to a
    slightly deeper surface with a quieter edge, secondary details use the quieter text color, and
    titles, status badges, priority chips and avatars stay at full strength. They keep that look
    when the pointer rests on them, instead of lighting up like an active card. The amount of an
    expected budget entry is no longer faded either (3.5:1 and 3.0:1 before); it keeps its income or
    expense color, and the "expected" badge marks the row. In the birthday import dialog, the
    "already added" badge had no background at all and its text was practically invisible; it now
    shows in the module color again.

  • Checked-off shopping items look the same with reduced motion, and stay readable. A checked
    item was meant to fade as a whole, but that only happened for people who had reduced motion turned
    on, and for them its name and quantity dropped to 2.0:1 (light) and 2.5:1 (dark). Everyone else
    saw the item unfaded, because the fade-in animation of the list left a setting behind that
    overrode it. The animation now cleans up after itself, and a checked item recedes through quieter
    text colors instead of transparency: the name struck through in the secondary text color, details
    and tags in the tertiary one, at 5.4:1 or more in both themes. Its tags no longer fade on their
    own either (2.6:1 and 3.7:1 before). A checked item can still be tapped to reopen it, so it is not
    exempt the way a disabled control would be. The same leftover setting had also kept a dragged row
    or board card fully opaque, and stopped note and document cards from lifting slightly when the
    pointer rests on them; a dragged card now fades while it is being moved, and notes and documents
    lift on hover again, as intended.

  • An early click on the simple setup no longer overwrites an existing installation. The web
    installer locks its simple path when it finds an .env, because that path sets host, port and
    cookie security itself. The lock only took effect once the installer had finished checking for
    the file, so a click in the moment before could still start the simple path and write over, for
    example, a setup running behind a reverse proxy. The simple path now waits for that check and
    continues in the advanced setup, where each of these values is visible, and its save step refuses
    to write over an existing file. The check itself no longer waits indefinitely for a container
    engine that does not answer: after a few seconds the installer carries on and treats the container
    as not running.

  • The web installer shows an existing configuration as a warning, not as a hint. When the
    installer finds an .env, the setup says that the current file will be backed up before saving -
    a setup that works is about to be replaced. That line was tinted like a plain hint; it now carries
    the same amber warning style and icon as the installer's backup reminders.

  • On the project page, the module list on phones folds away again, and the jump menu marks the
    right section after a language switch.
    On a phone, "Show all modules" opened the full list and
    then disappeared, so the list could not be shortened again; the button now stays and switches
    between all and fewer modules. The jump menu remembered where each section starts and measured
    again only when the window changed size, so after switching to the longer German page it
    highlighted the next section too early. It now measures again whenever the language changes or
    the module list opens or closes. The calendar screenshot also tells screen readers what it shows,
    instead of just "Calendar".

  • A Google Calendar change made while the connection is down now reaches Google once it is
    back.
    Before pushing an edit or moving an event to another calendar, Yuvomi asks Google for that
    calendar's details. When that request failed for a passing reason, such as no network, a token
    refresh or a rate limit, the change was handled like one for a read-only calendar and dropped: it
    never reached Google, and nothing said so. It now waits for the next sync and is only given up
    after the usual five attempts, or when Google reports the calendar as gone. A different calendar
    picked while a move is still under way is also no longer discarded when Google rejects that move.

  • The website and both READMEs now say what reaches out once you use a feature (#1212). Out of
    the box the only outbound request is still the update check against the GitHub releases API. The
    pages said that weather, calendar sync and cloud backup stay off until you enter credentials, but
    weather needs only a location, and once a country is set, holidays are fetched from
    openholidaysapi.org - except the public holidays of Australia, Brazil, Canada, New Zealand, the
    United Kingdom and the United States, which Yuvomi works out itself without a request. Opening the
    calendar settings loads the list of holiday countries from openholidaysapi.org as well, whether or
    not a country is set. Looking up a logo for a subscription contacts the service's website, and
    push goes through your browser's push service. The outbound line now names all of them.

  • A WebDAV backup URL made of whitespace no longer locks the backup settings. A space or line
    break in WEBDAV_BACKUP_URL, for example from ${WEBDAV_BACKUP_URL:- } in a compose file, was
    ignored as a URL but still marked the backup fields as set by the environment, so they could not be
    edited in Settings. Both now use the same check: only a value that is not blank comes from the
    environment.

  • A modules folder set through MODULES_DIR in .env is found again. docker-compose.yml,
    podman-compose.yml and the Podman Quadlet hand the .env to the container, and the app reads
    MODULES_DIR there as its own folder: an absolute host path in it pointed the app at a folder
    nobody had mounted, so dropped-in modules never appeared. The three descriptors now pin it to
    /app/modules inside the container; with Compose the .env value only moves the mount source, and
    the Quadlet keeps its host folder in the unit file. It reaches an existing install once its compose
    file or Quadlet unit is updated.

  • The Unraid template no longer takes email, backup and document-storage settings out of the
    app's hands.
    Seven of its variables shipped a value, and a value there wins over the matching
    setting in Settings, locking the email and document-storage fields. New containers leave them
    empty. A container created from the older template keeps what it was created with; clearing the
    variable on its Edit page hands the setting back to the app (see the Unraid section of the
    installation guide).

  • Belgian school holidays can be narrowed to one language community. OpenHolidays lists Belgium
    without any regions but splits its school holidays between the Flemish, French and German-speaking
    Communities, so the calendar settings had nothing to choose from and the calendar showed all three
    side by side. A country without regions now offers its school-holiday groups directly under
    Settings > Modules > Calendar, and the hint there no longer speaks only of Swiss cantons.

  • Housekeeping only offers visit actions you are allowed to take (#1135). A paid visit is
    settled, and only an admin can change or delete it - but the Staff log and the recent visits on
    the Overview showed edit and delete on every visit, so a member found out at save. The server now
    sends per visit whether the current user may edit or delete it. Where that is not allowed, the row
    offers the visit report instead and says that only an admin can change it. A calendar link to
    such a visit opens the report rather than a form that cannot be saved.

  • An item added without a category lands in the misc category again (#548). The item route had
    drifted to defaulting to the first category ("Fruit & vegetables" in aisle order). It now
    prefers the misc category by name as long as the household still has it, and only falls back to
    the last category in aisle order once it has been renamed or removed - "last" alone would have
    meant whatever category was added most recently, since new categories append at the end. The
    pantry import follows the same rule, so the two stay in step. In the same corner, quick-add's
    category selector resets to the default after every item added, instead of staying on whatever a
    previous suggestion or manual pick set it to - an unrelated item typed right after could quietly
    land in the wrong aisle.

  • Household members and guests created as contacts now show the translated "Other" category
    instead of the German "Sonstiges"
    (#1140). The contact that is mirrored when a household member
    or a split-expenses guest is created carried the raw German word instead of the category key, so
    every non-German household saw it untranslated on the contacts page. New contacts get the proper
    key, and existing ones are corrected when the app updates.

  • Opening Housekeeping with a broken visit deep link now says so (#1139). Tapping a
    housekeeping visit in the calendar opens Housekeeping through an ?editVisit=<id> link; when
    that visit has been deleted or the link is malformed, it used to fail silently and land on the
    ordinary dashboard, with nothing to tell a stale link apart from a working one. It now shows a
    localized message - a missing or invalid visit says so without a retry, while a server error, a
    network problem or rate limiting offers to try again. The broken link is cleared from the
    address bar right away - only that parameter, the rest of the URL stays - so a reload or going
    back does not repeat the failed request.

  • A full audit of the Schedule module, fixed in one sweep. The override editor no longer
    destroys typed input when its "fill the whole range?" confirmation is cancelled - the confirm now
    parks and resumes the open form instead of force-closing it, and the same holds if the confirmed
    save itself then fails: the form stays parked until the write actually succeeds, instead of
    closing on confirmation and leaving a failure toast over an already-empty page. A member with
    read-only access to the
    module sees an honest page: the banner was always there, but every create/edit/delete control
    rendered anyway and failed only on save; they are now gone, matching what the API has always
    enforced. Statistics and Overview refetch when the page is revisited (previously they re-labelled
    another user's cached numbers as your own after a tab switch), show real loading and error states
    instead of zeros that looked like data, and rapid week-flipping can no longer let a slow older
    response overwrite a newer one. The dashboard "who's working today" widget refreshes with the
    15-minute cycle instead of showing the morning state all day, and a failed load renders the error
    tile with a retry button instead of the "create a shift type" onboarding. Shift-start reminders
    fire at the DST-correct minute around clock changes, enabling them defaults to a 15-minute lead
    instead of "at shift start", and a reminder can no longer keep firing for a shift type deleted in
    the sync's blind window. On the server, a pattern save is capped at 500 cycle-day rows (each
    stored row is re-emitted on every resolved read - an uncapped save was stored read amplification
    any member could create), deleting a pattern or a user no longer leaks its custom-field values,
    duplicate field ids in one payload are rejected instead of half-committing and answering 500, and
    omitting field_values from an override save now preserves stored values, as the extras route
    always did. The statistics hint text in all 24 languages finally describes the rolling
    7-day-window rule the overtime flag actually applies, the printed statistics sheet no longer leads
    with the personal reminder settings card, and a member with no schedule access no longer gets a
    dead "Schedule" calendar layer plus a guaranteed-403 request on every calendar load.

  • A second pass on the Schedule module, this time on comprehension and everyday polish. Deleting a
    shift type now asks first, naming what it removes, like every other destructive action in the
    module already did. Two raw server strings that used to reach the toast ("shift_type_id must be a
    positive number.", "cycle_length cannot exclude existing pattern days.") are now plain sentences
    that say what to do next, and an Extra with no shift types yet shows a hint instead of an empty,
    submittable dropdown. Editing a pattern's cycle days and leaving the tab (or the card) without
    saving now prompts to discard, matching the confirm every other unsaved-changes flow in the app
    already has; merely switching the Add-entry modal's Pattern/Override/Extra segment no longer
    counts as a change worth asking about. Each cycle-day position shows the actual next date it falls
    on, with a one-line explanation of the repeating cycle; creating or reactivating a pattern that
    overlaps another one now asks first and names the consequence, and the pattern currently in effect
    carries a small marker. A household with no shift types yet opens on that tab instead of the
    planning tab it would immediately dead-end on. Every schedule tab now has its own address
    (/schedule/patterns, /schedule/statistics, ...), so reloading keeps the tab, the back button
    walks between tabs instead of leaving the page, and the dashboard widget and a shift reminder both
    link straight to the relevant tab instead of the bare module. Clicking a shift anywhere it appears
    (the Today card, the Compare view, a week/day calendar block) now opens a small read-only detail
    view instead of doing nothing; week/day calendar chips show the full time range instead of just
    the start; and the "Free today" hero and the per-member status row on the dashboard no longer
    contradict a schedule entry sitting right next to them. The Statistics owner picker is self-only
    for non-admin members now - statistics remain a read-only summary of data everyone can already see
    via the Today card and calendar, but the convenience of pulling up someone else's totals was never
    meant to be open to everyone. Shift-type presets are grouped by template (Work/School/University)
    instead of one flat list of fifteen, the reminder lead time accepts any custom value up to the
    server's own 24-hour cap instead of the seven fixed presets, and an expanded shift-type card spans
    the full row instead of leaving a gap beside it. Tracking overtime at all is now its own switch
    next to the weekly-hours target, instead of that number being the only way to affect whether the
    Statistics tab flags anything - turning it off removes the overtime card entirely rather than
    requiring a number nobody's schedule will ever cross. All of the above is translated into all 24
    languages.

  • Schedule: a stable "Today" card and one clear way to add an entry. The Today card used to be
    the first block of the Planning/Shift-types tabs only, so switching to Statistics or Compare made
    it vanish and everything below it jump up to fill the gap; it now renders once, above the
    per-tab content, and simply stays in place across every tab (still hidden entirely for a household
    that hasn't used the module yet). The Planning tab offered up to four "add" affordances at once -
    the page's own FAB, an always-visible "Create override" button, an always-visible "Add extra
    shift" button, and each section's empty-state CTA underneath its own always-visible twin; a
    household with nothing entered yet saw two identical buttons stacked in both the Overrides and
    Extras sections. The FAB (which already opens the same form, pre-selecting the right mode) is now
    the one durable way in; the section headers no longer carry their own button, and each empty-state
    CTA remains as the contextual nudge for first-time setup, matching how the Patterns section already
    worked. The three quick-start template buttons on the Shift-types tab looked like a segmented
    toggle even though picking one is a one-shot action with no "selected" state to show - they're
    plain buttons now, and the household's own hidden-template setting still filters which ones
    appear. The Compare tab's day headers scrolled away with the hours beneath them; they now stay
    pinned to the top of the scroll area while the day's shifts scroll past, so a block halfway down a
    long day is never orphaned from the day it belongs to.

  • The calendar keeps keyboard focus when a deletion is committed (#1083). A deleted event
    disappears at once and is removed for good once the Undo notice runs out, and the view then draws
    itself once more. Whatever you had moved on to in the meantime, for example the next row in the
    agenda, lost focus at that moment, so the next Tab started again at the top of the page. That
    element now keeps focus across the redraw. Pressing Undo from the keyboard lost focus the same
    way, because the notice removes its button before the event comes back; focus now lands on the
    restored event.

  • A dialog no longer moves keyboard focus into its first field after you have already moved on
    (#1156). Opening a form puts focus into its first field a moment later. On a slow or busy device
    that moment could arrive after you had already acted, for example after answering a save
    confirmation, which hands focus back to the Save button: focus then jumped to the first field
    instead, and nothing brought it back. The same could pull focus out of an open date picker. The
    first field now stays out of the way once focus has moved inside the dialog or into something on
    top of it, such as a date picker; focus that lands on the page behind the dialog still moves in.

  • The warning about a password login that is still open now names the administrator condition
    (#1194). AUTH_ALLOW_PASSWORD_LOGIN=false only takes effect once an administrator account is
    linked to the OIDC provider; a member signing in through SSO does not arm it, so that an
    administrator without a linked account cannot be locked out of the administration. The startup
    warning said that no account was linked, so an operator whose member had already signed in through
    SSO read the switch as armed while the login form was still open. It now says administrator. In
    the same pass the Portainer compose file stopped defaulting OPENWEATHER_LANG to de, where the
    code, .env.example, the Unraid template and the installation guide all use en.

  • Shared expenses embedded in Budget no longer skip a heading level (#1190). The embedded tab
    title is a level-2 heading, which left the group name beside it at the same level and its
    Balances, Recent expenses and Activity cards directly under the title instead of under the group.
    The group name is now a level-3 heading and those cards level 4, so the outline a screen reader
    announces reads Budget, then Shared expenses, then the group, then the section. Nothing moves
    visually: size, weight, line height, margin and color are unchanged.

Don't miss a new yuvomi release

NewReleases is sending notifications on new releases.