github ulsklyc/yuvomi v2.79.0

7 hours ago

Added

  • You can move money between two budget accounts. (#1061, from D#781) Use the budget
    entry dialog, with category and subcategory selection. The linked outgoing and incoming entries
    update each account's balance and stay consistent when edited or deleted. Deleting one occurrence
    of a recurring transfer asks whether to remove only that pair or the entire series, and the
    confirmation that follows names what you chose. Transfers are shown
    separately in the month summary and category chart and do not count as income or spending in
    summaries, statistics, budget plans, or the dashboard. Savings is created as a subcategory of Financials
    when Financials still exists, without restoring deleted categories or rewriting entries, series or plans.
    Accounts with transfers can be archived; deleting them is blocked to keep both sides intact.
    Transfer rows carry a marker and show the account direction. Savings transfers appear in a separate
    Transfers chart section. Transfers require both accounts to use the same currency; currency exchanges
    are not supported. The amount field follows the source account's currency. Existing transfers
    remain editable after account or household currency changes when their accounts stay the same.
    API: POST /api/v1/budget/transfers creates a transfer, GET and
    PUT /api/v1/budget/transfers/{id} read and correct one booking, and PUT .../{id}/series
    changes a recurring one. Entries carry the read-only transfer_entry_id and, in the list,
    transfer_account_id; the month summary carries transfers.

  • A device showing the wall display gets no personal push notifications (#1904). Reminders,
    task-comment mentions, and medication doses are personal and would disturb a tablet mounted in
    the kitchen. While the wall is up, the device reports its state to the server and delivery is
    paused for it. The pause expires after 12 hours so a device that was switched off with the wall
    up heals on its own; a device that comes back alive renews it automatically.
    API: PUT /api/v1/push/wall-mode with endpoint and active sets or clears the pause for
    that device.

  • Wall display shows today's meals, shopping count, housekeeping status, waste pickups, and
    expiring pantry items
    (#1903). Paired wall displays previously showed only the calendar,
    tasks, rewards, and weather sections of the today sheet. The dashboard now delivers the five
    missing sources to display sessions with the same narrow fields the wall tile uses: meal title,
    type, and cook - no private notes or recipe content; shopping open-item count; housekeeping
    presence, worker name, and check-in time - without the unpaid amount or visit count;
    waste-pickup type names and icons; and expiring pantry items. Individual module routes for
    these remain closed to displays. Paired displays pick this up with the update - no
    configuration needed.

  • Stock: every batch now belongs to a household product (part 1 of #1448). Nothing changes on
    the page yet. Batches with the same name, compared trimmed, case-insensitive and with collapsed
    whitespace, and the same unit share one product; existing stock is grouped once on update. The
    product is the groundwork for a minimum over all batches, recipe matches that survive the last
    bottle, and a grouped stock page. For API clients, pantry items additionally return
    product_id; a batch whose name or unit is edited moves to the matching product.

Changed

  • Language, region and time zone settings show their whole value on a phone. On a narrow
    screen the choice was cut off at the part that matters, such as "Automatic (Europe/Ber…".
    "Automatic" now stands alone, and the hint below starts with what it means right now
    ("Currently English.", "Currently Europe/Berlin."), updating when you change the choice or the
    region. Regions are named after their country ("Germany"); Canada, the Philippines and
    Switzerland keep their language ("Canada (French)"), since there the language sets the format.
    Members who see the household time zone see a chosen zone by its name instead of "Automatic".

  • The loading screen sketches the overview you are about to see. While the app starts, it now
    shows the greeting, the "Today" heading and one tall card where the day's program will appear
    (with the tile row below on larger screens) instead of three generic cards.

  • The household help overview leads to the full report. The overview lists the five latest
    visits, the same rows the Reports tab shows for the month; when there are more, a last row "All
    visits in the report" takes you there.

  • A selected row speaks in its module's colour. In list-and-detail pages the selected row was
    violet while the active filter chip above it carried the module's colour; both now use the module's
    colour. Purchase prices in the inventory read like every other amount, in semibold.

  • The repeat and receipt marks of a booking stand next to its date. At the end of the line they
    could wrap onto a line of their own on a phone; now they follow the date ("01.10. ⟳ · Health").

  • Editing an amount shows it with its cents. An entry of 200 € opened as "200" and 38.50 € as
    "38.5" in the budget, subscription, loan, plan and household help dialogs; they now read "200,00"
    and "38,50" in the format of your region. Nothing is rounded: an amount with more decimals stays
    as saved. In the budget entry dialog, "Category" and "Subcategory" also stand as close to the field
    above as every other label.

  • A short birthday list no longer puts a month heading over almost every row. Month headings
    appear once the list has, on average, at least two birthdays per month; a shorter list is one
    sequence by how soon each birthday comes, with the next one still highlighted.

  • A phone number looks the same in the contact list and in the contact. The list showed a
    number formatted, the contact's detail showed it as typed; both now use the same format.

  • On a phone, documents filter by folder and category from one place. The filter row held the
    active/archived switch, the folder button and six category chips, and at phone width none of the
    categories was fully in view. The folder button now opens folders and categories as two groups,
    shows the chosen category with its icon, and the row fits the screen. On larger screens nothing
    changes.

  • The installed app describes itself as a home, not a family planner. The description of the
    installable app and of the start page names your home in one place - whether you live alone, as a
    couple or as a family -, like the sign-in page and the welcome tour already do. The app's name is
    unchanged.

  • Forms use one text size around their fields. Field labels, the hints below a field, field
    errors and the heading of a field group are all one size now; before, labels and most hints were a
    step larger than the system's label size and some hints a step smaller. The description under a
    setting, the income and spending figures next to a balance on phones, and the day headings of the
    calendar agenda follow the same text styles as the rest of the app.

  • The demo household looks like one the app would create. Emma and Leo start with the
    permissions every new child account gets - no budget, household help without amounts, no fasting
    and the cycle tab off - so the demo no longer shows a child account with bank balances and wages.
    The holiday and garden notes are real checklists you can tick off, the German demo names
    medication forms in German, and only a few pantry items are running low instead of almost half.

  • Events in the calendar month have room above and below their title. The tinted bars in a
    month cell sat with their text flush against their top and bottom edge; they are now one pixel
    taller on each side, and multi-day bars grow with them.

  • The same message stands once. When the same notice comes up again while it is still on
    screen, it stays one notice with a small count instead of stacking up and pushing other notices
    away. Notices with an Undo button stay separate.

  • Swiping through days joins the two days seamlessly. In the calendar's day view the next day
    now follows directly after the current one while you swipe, without an empty strip in between.

  • Every form points at the field that needs attention. Leaving out a required field in the shift
    plan, shared expenses, household help, subscriptions, documents, fasting, the settings or the
    tablet pairing no longer shows the browser's bubble; the message stands at the field in the app's
    own words, like in the health forms. The household help's task form said nothing at all before.

  • The arrow keys page through a period, and through documents. With focus on the month or week
    switcher of the budget, the meal plan, the household help reports or the shift plan, Left and
    Right go to the previous or next period. The document viewer has previous and next buttons, and
    the arrow keys move through the documents of the list you opened it from.

  • The search lists coming events first and shows its keys. Events from today on come first, past
    ones after them, the latest first. On a computer, a line under the results names the keys:
    arrows to select, Enter to open, Esc to close. The keyboard help lists "g s" and "g k s" in one
    line, since both open the shopping list.

  • Every list row ends the same way, and a tap anywhere on a row opens it. Rows now end with at
    most one visible action, then the More button, then the drag handle in sortable lists. Shopping
    moved its More button in front of the handle, a medication dose shows Take with Skip under More,
    a pocket-money account shows Book with plan and close under More, recipe rows lost their arrow
    and wide document rows their eye. Tasks, birthdays, inventory, contacts, pantry, recipes and
    household help now open from the whole row, not only from the title.

  • The add sheet answers your tap right away. Tapping + to add a task, event, note, contact,
    birthday, entry or any other item first dims the page and then slides the form in once it is
    ready, with its full spring. On a slow phone the tap used to wait for the whole form: measured
    with a four times slower processor, the screen answered after 104-176 ms; now the page dims
    after about 70 ms and the sheet follows a frame later.

  • A document preview never opens on an empty stage. On a phone the viewer showed nothing
    and no sign of loading until the file had arrived. It now shows a loading indicator right away,
    on top of the card's thumbnail when the card has one (grid view), and the full image fades in
    over it; a PDF from a card shows its first page the same way until it is drawn.

  • Long lists only do the work for what is on screen. The agenda, the pantry, the inventory,
    the budget's entries and the shopping list on a phone now skip days, groups and rows below the
    screen until you scroll near them, as tasks, contacts and recipes already did. Opening a dialog
    over a long agenda is lighter for it.

  • Swiping the calendar starts moving with your finger right away. The neighbouring week or
    month is now placed and measured while the app is idle, so the first frame of the swipe only
    has to uncover it.

  • Swiping the calendar asks the server less often. To have the next and the previous week
    or month ready under your finger, the calendar used to ask four sources for each of them,
    up to eight requests after every change of period on a touch device. It now asks each
    source once for both.

  • Adding a dialog, a notification or a field no longer recalculates the whole page. Four
    style rules (the collapsed search, the folding toolbar and the budget's two ledger sections)
    made the browser re-style every element on the page whenever something was inserted. They
    now only touch what they style; measured on the task list, an insertion costs about half as
    much.

  • Two rows of documents fit on a laptop screen. Each card's preview showed the whole page in
    a tall frame, so the second row stood half below the edge. The frame is square now and the
    page still shows whole inside it; a card is about 60 pixels shorter.

  • Switching a note to editing keeps the Read/Edit switch in view. On a phone the long text
    field pulled the sheet up by about two lines when it got the cursor, and the switch slid under
    the sheet's header. Dialogs now only move a field into view when it is not already in the
    upper half of the sheet.

  • Small alignments in contacts and settings. In a contact, phone numbers, e-mail addresses
    and addresses now sit as close under their label as category and notes do. On a phone the
    label field of a number or address moves under the value, so "Label (e.g. work)" is no longer
    cut off. The fields of a settings page start at one edge instead of three.

  • Splitting expenses starts with the group. On a phone "You owe 24.14 €" stood above the
    group choice that says whose debt it is; on a wide screen the two amounts formed their own row
    above the group list. The amounts now sit in the group's column, right above its header, and
    the group list starts at the top like every list beside a detail. Pointing at a group no
    longer looks like selecting it.

  • Subscriptions read like the other budget tabs on a wide screen. The list ran across the
    whole budget width, a full screen from a name to its amount. It now stands on the reading
    width with the key figures and the charts in a column on the right, like the overview and the
    plan. When the subscriptions cost more than their budget, the bar says so in red once; the
    card next to it names it in words instead of repeating the red.

  • The shift plan's planning tab is shorter when it is still empty. Exceptions and extra
    shifts without an entry are now one quiet row each, with the sentence on the left and the add
    button on the right, instead of two more centred empty pages below the empty shift plan. The
    period choice in the evaluation is as wide as its three words instead of the whole card.

  • Settings, Help, What's new and Sign out are always visible in the More sheet. On a phone
    they sat at the end of the scrolling list, below the edge of the sheet on most screens. They
    now stay fixed at its bottom while the modules scroll above them, and the sheet uses the
    grouped background of the app, so its lists no longer look like cards stacked on a card.

  • The budget plan starts with your categories. On a phone the plan opened with the card
    asking you to set a savings goal; the category budgets started below it. Without a goal that
    card now comes after the categories; a goal you set still leads.

  • The cycle page keeps its pieces together. On a phone the legend of the cycle ring now
    sits right under the ring instead of below the today card and four tiles. On wider screens
    the "Day 7" marker on the ring no longer lies on the tile next to it, and the header of each
    health area is a card like the areas below it instead of a square white bar.

  • The detail column next to a list ends under its content. On a wide screen a birthday, a
    recipe, a contact or a task stood in a card that reached the bottom of the window, with up to
    half a screen of white above its buttons. The card is now as tall as what it shows, the
    buttons sit right below, and a long detail still scrolls inside it.

  • The calendar header takes one line on a laptop, and the date above it is never cut. At
    1280 pixels the header used two lines, with an empty stretch next to the date. When the full
    line does not fit, the search now waits as a magnifier button and opens over the view switch
    while you type, and "Manage calendars" stays in the filter sheet: the header shrank from 113
    to 69 pixels. Where the date ran out of room - "21.10. - 23.10.2026" on a phone in Ukrainian,
    "Wednesday, 21.10.2026" on a laptop in English - it now drops the current year or shortens
    the weekday instead of ending in "...". In the month view the sidebar no longer repeats the
    month as a small calendar.

  • The cycle settings are easier to find and to read. Searching the settings for "cycle",
    "contraception" or "pregnancy" now finds "Cycle settings", and the health settings link straight
    into them. The dialog uses switches instead of checkboxes, puts "days" after each length, and
    explains "leave empty to calculate" right under the two fields it is about. The tip at the end
    of the cycle page is now one link to the cycle calendar feed, which had moved to the health
    settings, plus a short line on adding the cycle tile to the Overview.

  • Health answers "Who can see this?" where you pick the person. The person menu in your own
    health view ends with "Who can see this?", which opens your default visibility. That page now
    also says that anyone allowed to record for you sees your private entries, except the cycle
    diary, and links admins to the members page where this is set.

  • A contact and its birthday lead to each other. When a birthday was imported from a contact,
    the contact's birthday line now offers "Show in birthdays", and the birthday offers "Show contact"
    next to its date - one tap instead of switching modules and searching. The link only shows when
    you can open the other module. API: contacts carry birthday_id, the birthday imported from
    that contact or null; it is always null for a caller who may not read the calendar, which
    birthdays belong to.

  • Shift plan, rewards and household help name themselves on a phone again. Below 768 pixels
    the three showed only their tabs, so nothing on screen said where you were. The header now
    carries the module's symbol and name with the tabs below, like the budget; while you scroll,
    the tabs stay at the top with the module's name in front of them, in a header no taller than
    the tabs - the household help's header shrank from 73 to 65 pixels there.

  • The shift plan's first tab is called "Overview" and only appears when there is something to
    show.
    "Compare" stood first even without a single shift type, while you started on "Shift
    types" next to it. It now uses the same name as the first tab in budget and health, shows up
    with the first shift type, and the "Shift types" heading no longer repeats the tab above it.

  • Roles and permissions name every level in words, also with a mouse. From 1024 pixels with a
    mouse the matrix showed only icons - a crossed-out eye, an eye, a pencil - with a legend above to
    look them up. Each level now reads "No access", "Read only" or "Full" next to its icon, and the
    legend is gone. When a row runs out of room, as for a member with "Inherit", the levels move
    under the name instead of squeezing it.

  • Jump links at the top of a settings page look like links. They used the same capsules as
    the choices below them, such as the default reminders in the calendar settings. They are now
    plain links in the accent colour.

  • "No one" no longer sits among the people in a multiple choice. Who may record health data,
    who a task or booking is assigned to and whom the shift plan compares: choosing nobody now
    means choosing no one, instead of a chip that looked like another person. Picking a meal's
    cook keeps "No one", because there it is one of the answers.

  • The numbers on the faces in the Overview's family card say what they count. On a phone, a
    bare "1" next to a face read like a notification. The badge now starts with the tasks symbol,
    and it sits at the edge of the face so the initials stay readable. With six or more people it
    moves onto the top of the face instead of covering the next one, and when only some of the
    family share the next event, the shortened list of names leaves room for the event itself.

  • Red in the budget means something needs doing. The statistics showed seven red amounts
    for categories that simply cost a little more than last month - "+25.00 €" while 25 of 80 € were
    spent. Changes against the previous month now show in grey with their sign and arrow, here and
    on the budget cards; red marks a category only once its plan is exceeded. A credit card's usual
    minus is no longer red, only a card over its limit; any other account in the minus stays red.
    What you owe in shared expenses, on its card and on the Overview tile, is shown in the normal
    text colour.

  • Sign-in and the welcome tour speak to every household. "Welcome back to your family
    planner" left out everyone who lives alone or as a couple. Sign-in now says "Welcome back. Your
    home in one place.", and the first step of the tour names tasks, calendar and shopping for a
    household of any size, in every language. The two fasting texts in German that still addressed
    you formally now say "du" like the rest of the app.

  • The fold-out for less common fields has one name in every dialog. Tasks called it "More
    settings", while bookings, inventory and the cycle diary called it "More details". It is "More
    details" everywhere now.

  • The note under the keyboard shortcuts no longer apologises for the user guide. It says who
    maintains the guide and that it opens in a new tab.

  • Health opens with one sentence about what changed. The overview now starts with a line
    such as "Since the last measurement: weight -0.2 kg, sleep +30 min and blood oxygen +1 %" - the
    change, never a judgement. Measurements nobody has taken no longer show as grey boxes with a
    dash; a single quiet row offers to record the first one. The charts read better: each kind of
    measurement keeps a minimum range, so a blood sugar between 88 and 90 no longer looks like a
    swing, the unit stands at the axis, the pulse has its own axis below the blood pressure, and the
    lines are named where they end instead of in a colour legend. The activity chart names its
    minutes, and a lab result without a rating shows an empty cell instead of a dash. New child
    accounts start without the cycle, as they already did without fasting; it can be shown again
    in the child's own settings, and existing accounts keep what they have.

  • The Overview opens with your day. On a phone, "Today" now shows as many entries as fit on
    the first screen instead of stopping after two, with the rest behind "+N more"; the shopping
    line counts too, so it no longer slips behind the tab bar, and the number follows when you turn
    the phone or the browser bar changes the height of the window. The budget card
    and the account balance are no longer on a new Overview - bring the card back under
    "Customize" if you want it there; layouts you saved keep it. On wide screens the tiles close the
    gap that was left under a small tile next to two tall ones.

  • Small text on the Overview tiles reads at the sizes used everywhere else. Counts, time
    left, amounts and the line under an empty tile were 14 pixels, the "+N more" line under every
    list tile only 12. They now use the shared sizes: 13 pixels for the small line under a name and
    for "+N more", 15 for a nutrient's name; badges, avatars and buttons keep their size.

  • Recipe rows keep their actions in one More menu. From a medium width up, every recipe row
    showed edit, duplicate and a delete bin, and the detail column next to it offered the same three
    again; on a wide screen the titles were cut to make room. The row now carries only its More
    button at every width, with Delete as its last, red entry.

  • The small line under a name reads the same in every module, and a little larger where it
    was smallest.
    Dates, places, amounts and counts under a task, an entry or a contact were 12
    pixels in tasks and on the Overview and 14 pixels in budget, inventory, contacts and the
    agenda. They now share one size, 13 pixels, everywhere. Explanations in empty pages, document
    descriptions and the line under a contact's name move from 14 to 15 pixels.

  • On tablets, the month view shows more of each title, and the tab bar is easier to read.
    Event and task titles in a month cell may now take two lines instead of being cut after about a
    dozen letters; what no longer fits is counted in "+N more". The tab bar labels grow from 11 to
    12 pixels, the budget statistics name each category in 15 instead of 14 pixels, and the compact
    budget figures, tasks in the agenda and the loan details no longer drop to 12 pixels.

  • With "Increase contrast" turned on, small grey text gets darker too. The setting already
    made borders and glass solid, but dates, counts and other secondary lines kept their light
    grey. They now move one step closer to the main text colour, in light and dark mode.

  • "Manage participants" in rewards now lives in a More-actions menu. The section header showed
    two equally-weighted buttons; only "Grant bonus" stays as the primary section action. "Manage
    participants" is reached via the ⋯ button next to it.

  • "Add recurring expense" moved to the recurring-expenses section header. The button used to
    appear below the list; it now sits in the section title row.

  • "Add group" in split expenses is now in the More menu next to the group search. The bare +
    icon button in the Groups panel header has moved into the ⋯ More menu.

  • A single occurrence of a calendar series is now named by its original start time (#2034).
    Until now an occurrence was named by a day, and around a clock change two occurrences could share
    that day - deleting one of them could hide both. An occurrence is now named exactly as calendar
    apps do it (RFC 5545 RECURRENCE-ID): a date for an all-day series, the original start in UTC for
    a series with a time zone, the wall time for a local series without one. Exceptions and edited
    occurrences saved before keep working exactly as they did; when you change the start time of a
    series, or the household time zone, its exceptions move along with it.
    API: recurrence_id in calendar reads, search, countdowns and MCP now takes one of three
    forms: YYYY-MM-DD, YYYY-MM-DDTHH:MM:SSZ or YYYY-MM-DDTHH:MM:SS (URL-encode it in a
    path). The occurrence routes and POST /api/v1/calendar/{id}/exceptions still accept the old
    YYYY-MM-DD form; where it matches two occurrences they answer 409 with reason
    ambiguous_recurrence_id. The exceptions route takes the new field recurrence_id next to
    date and stores the exact key. It answers 400 with reason invalid_recurrence_id for a key
    that names no occurrence of the series and with reason malformed_recurrence_id for a value that
    is no occurrence key at all; until now any well-formed date was stored unchecked.

  • Task, calendar and Overview lists load much faster in households with profile pictures.
    Every task, event, note, housekeeping visit and money ledger row used to carry the full profile
    picture of its person, and a task twice. With 200 tasks and five pictures the task list weighed
    17 MB, and over plain HTTP in a home network about 13 MB of it crossed the wire on every load. The
    rows now carry a short picture address instead, and the browser downloads each picture once (now
    about 215 KB, under 5 KB compressed) and afterwards only asks whether it changed, so a signed-out
    browser no longer shows it. Pictures still show offline where the list does.
    API: requests with an API token see no change and keep receiving data URLs. For the app
    itself (session and wall display) the fields assigned_avatar, assigned_users[].avatar_data
    (tasks, events), creator_avatar (notes), worker_avatar_data (housekeeping visits),
    user_avatar and person_avatar (completion feed, money ledger) hold
    /api/v1/people/{id}/avatar?v=..., served by the new GET /api/v1/people/{id}/avatar. Member
    lists and the profile endpoints keep the data URL.

  • The Overview no longer rebuilds every time you switch back to its tab. Returning to the tab
    reloaded the whole Overview, even after a few seconds elsewhere. It now reloads only when its data
    is older than a minute or the day has changed; the greeting, date and clock still update at once.

  • Pages with an extra stylesheet show up sooner. The Overview, Health and Budget pull in further
    stylesheets that the browser only discovered after loading the first one. They now load in
    parallel.

  • Warming up the other pages in the background no longer competes with the page you are on.
    After the start, Yuvomi preloads the main pages while the browser is idle; these downloads now ask
    for low priority.

  • Switching pages fades into the finished page instead of its loading placeholders. The fade
    used to start from the old page into grey placeholder bars, and the real content popped in
    halfway through it. The old page now stays for up to 150 ms while the new one draws, so the
    fade lands on content - including the scroll position when you go back - and the selection pill
    in the tab bar continues its glide where it was instead of skipping ahead.

  • Loading spinners turn at one pace and keep turning with reduced motion. The button,
    sign-in and document preview spinners turned at three different speeds, and with reduced motion
    they stood still, so a running action looked stuck. They now share one pace, and as a status
    they keep turning in place when reduced motion is on.

  • The kitchen tab bar on phones has a proper capsule. The highlight of the current kitchen
    tab was almost a circle hugging the word, and a count read as "Pantry10". It is now a 40-pixel
    capsule with even room around the word, the count sits apart as its own badge, and all four
    tabs still fit on a 375-pixel screen. Switching between kitchen tabs fades only the page
    content: the tab bar and the row under it change at once, and the highlight glides over.

  • Going back to the Overview shows it at once. If the Overview was loaded less than a minute
    ago and nothing was changed since, it appears straight away instead of through loading
    placeholders, then quietly checks for news and only redraws when something is different.

  • Long contact and recipe lists open faster. The browser now skips rows outside the visible
    area until you scroll near them. Measured on a slowed-down device, opening 500 contacts blocked
    the page for about 0.8 s, now about 0.55 s; 300 recipes went from about 0.45 s to under 0.4 s.

  • The module guide says how to find third-party modules (#746). Yuvomi keeps no curated list of
    modules. MODULES.md now points to the GitHub topic yuvomi-module, says that nothing found
    there is tested or recommended by this project, and asks module authors to set the topic on their
    repository. Why there is no curated index is recorded in docs/DECISIONS.md, entry 15.

  • The API reference lists the waste, shift schedule and birthday calendar feeds (#1990).
    /feed/waste/{token}.ics, /feed/schedule/{token}.ics and /feed/birthdays/{token}.ics were
    served but missing from the OpenAPI document. The calendar, waste and birthday feeds now share one
    token lookup; their behavior is unchanged.

  • Swiping through the calendar now turns the page. In month, week and day view the next or
    previous period now comes along with your finger, while the hour column and the weekday row stay
    where they are. Let go after a short distance or with a quick flick and it settles into place; a
    short, slow swipe springs back. Before, the whole view including the hours moved only a little,
    next to an empty area, and the new period appeared only after you let go. With reduced
    motion, the new period fades in instead of switching abruptly.

Fixed

  • Icons are drawn with one line weight, at every size. Small icons looked thin and large
    ones heavy: next to each other, icons on one screen used up to twelve different line widths,
    from 1 to almost 5 pixels. The module symbols were meant to keep a fixed line all along, but
    the setting sat where the browser ignores it. Every icon now draws a 1.5-pixel line.

  • Health forms point at the field that needs attention, in the app's own words. Leaving out a
    value, typing a number outside its range or an end date before the start no longer shows the
    browser's speech bubble or a message without a place; the note now stands under the field, and the
    cursor goes there. The empty blood pressure fields no longer show 120 / 80 and 72 in grey, which
    read like a saved measurement.

  • The add button on the cycle page says what it is for: adding a past period. "Period started"
    next to Today records today with one tap; the dialog behind the add button is for entering dates.

  • An invitation link that no longer works says what to do next. Instead of "no valid token was
    found", the page now says the link is invalid or expired and to ask for a new one, and the way to
    sign in stands out for anyone who already has an account.

  • A password reset link that no longer works says what to do next. Instead of "No valid token
    was found" above a locked form, the page says the link is incomplete or has expired and offers
    "Request a new link". A busy server or a lost connection no longer reads like an expired link:
    the form stays, and the message says what went wrong.

  • When ticking off a task or shopping item does not go through, the message says which one.
    Instead of "An error occurred", it names the item, says it is open again (or ticked again), and
    that you can try once more.

  • Upload areas on phones and tablets say "tap" instead of "drop here". Documents, event
    attachments, backup restore and module install offered to drop a file where there is nothing to
    drop; on touch screens they now say to tap and choose a file.

  • "More details" in a dialog opens into view instead of under the buttons. On phones the fields
    it revealed lay behind the fixed Save and Cancel row; the dialog now scrolls them into view. In
    the budget entry dialog the account moved out of "More details" and sits right after the date
    once you have accounts.

  • Settings keep asking before you leave when saving did not work. A form counted as saved the
    moment you pressed Save - before its fields were checked and before the server answered. If a
    field was wrong or the server refused, leaving the page no longer asked, and what you had typed was
    gone. Now a form is only clean once saving actually worked.

  • Document previews no longer show a thin sliver next to each picture. The file icon behind a
    loaded preview stayed on screen as a narrow strip beside it. Anything the app hides is now hidden
    everywhere, by one rule instead of one per element.

  • Messages sit just above the tab bar on phones with a home indicator. The space for the
    indicator was counted twice, so a message floated about 34 px higher than on other phones.

  • "Today" in the phone week view is there as soon as today is off screen. The phone week shows
    three days at a time, but the button checked the whole week: after one step forward today was out
    of sight, and the way back to it was missing until the next week.

  • Sheets and glass controls settle sooner. Their springy entrance kept them slightly past their
    resting place for most of the movement. In current browsers it now moves like a real spring: the
    same small overshoot and the same duration, but it comes to rest after about half the time.

  • The tab bar no longer nudges the page when it shrinks while you read. Shrinking changed its
    height, which moved its top edge a little in every frame (and in one step with reduced motion).
    It now keeps its size and squeezes from the bottom edge, so nothing on the page shifts.

  • An undo message no longer covers the top of the More sheet. With no free spot beside the
    nearly full-height sheet, the message sat on its handle and search field. It now steps back
    while the sheet is open, its countdown paused, and returns when the sheet closes, so the undo
    is still there.

  • The title of a sheet stays at the same height, however long it is. A title that wrapped to
    two lines started 12 pixels higher than a one-line title, so the title jumped from task to
    task. The first line now always lines up with the buttons beside it.

  • Opening a settings page on a phone no longer starts from a half-finished frame. The first
    frame of the slide already showed the back link and cut the settings list to its first two
    rows. The list now stays whole while the page slides in with its content, and the title fades
    over to the back link.

  • Switching to the Overview no longer flashes the previous page's title. For one frame at the
    end of the page fade, the title of the page you came from (for example "Tasks") stood fully
    visible over the greeting. The fading title now keeps its end state until the fade is gone.

  • The calendar no longer jumps while it loads. The row with the arrows and the view switch
    arrived only with the data, and the whole calendar below slid down by 52 pixels on phones. The
    full header now stands from the first frame and becomes usable as soon as the calendar has loaded.

  • The calendar arrows stay put when you change the view on a phone. The view button was as
    wide as its word, so the forward arrow moved by up to 26 pixels between "Day" and "Agenda". The
    button now always takes the width of the longest view name.

  • The day list under the phone month no longer jumps when you change months. A month with
    five weeks was 48 pixels shorter than one with six, and the list below moved with it. The weeks
    now share the same height, so the list always starts at the same place; folded to one week, the
    row keeps its height across month boundaries.

  • Folding the phone month also folds the calendar header. Pulling the day list up folded the
    month to its week but left the two-row header standing. Both now fold and unfold together. Also
    fixed: in week and month view the header folded only once - after it unfolded, scrolling no
    longer folded it again.

  • Ticking off a task or a shopping item no longer cuts off the rows below. While the ticked
    row left, its card shrank at once and the rows beneath slid up from below: the last one was
    cut off at the card edge for a moment, and an empty band opened under the card. The rows, the
    card edge and the groups below now move up together, and the group count changes as the row
    starts to leave instead of afterwards.

  • A CalDAV outage or an expired password no longer brings deleted entries back (#1863). A
    deletion or change that the server refuses is retried up to five times before Yuvomi gives up and
    takes the server's version again. Until now every refusal counted, also those that say nothing
    about the entry: with the server down, rate-limiting or rejecting the password, each edit you made
    used up an attempt of every waiting deletion and change. After five edits, deleted events and
    tasks came back with the next successful sync and pending changes were overwritten. Now only an
    answer about the entry itself counts (for example a conflict or an invalid entry). Answers about
    the whole account or server (401, 403, 429, 5xx, no connection) leave the work waiting until the
    server accepts it again, and after the first such answer Yuvomi sends nothing more to that account
    until the next sync instead of one request per waiting entry; a 403 only pauses its own calendar.
    This covers calendars, Apple calendars and tasks; Google is unchanged.

  • The meal plan now follows the household week-start setting, just like the calendar (#2075).
    Both the server (GET /meals, "add week to shopping list") and the frontend week-grid previously
    hard-coded Monday as the week start. Both now read the household week_start preference
    (monday / sunday / saturday), so a Sunday-first household sees Sun-Sat in the meal plan and
    the shopping-list transfer covers those same seven days.

  • Overview: the Calendar and Tasks tiles follow their size, so a small tile no longer stretches
    its row (#2087).
    A small (1x1) Calendar tile showed five, eight or twelve appointments and a
    small Tasks tile five tasks, so their neighbours in the same row grew taller and showed "+N more"
    above empty space. Both now show three entries like every other small list, followed by a note
    when more are waiting; on the phone the Tasks tile shows three in every size. In the tall sizes
    the "How many appointments?" option (5, 8 or 12) now decides how many grid rows the Calendar tile
    spans (2, 3 or 4), so a longer list makes a taller tile instead of a taller row; your saved size
    and option stay as they are. Appointments that already ended today take only the rows left over
    by upcoming ones, at most two, and the rest still fold into "+N earlier today". The wall display
    keeps its own limit.

  • Kitchen settings: a recipe provider says why its last sync failed, in your language (#1909).
    The account card in Settings > Kitchen showed the raw text of the last failed sync or connection
    test, for example "Mealie request failed (401)", "getaddrinfo ENOTFOUND mealie" or "HTTP 404". It
    now names the cause in the language of the app: the provider refuses the API token, no provider
    answers at the server URL, the provider answered with an error status, it did not answer in time,
    it cannot be reached, its certificate is not trusted, its answer could not be read, or the address
    points to a private network (with the setting that allows it). Any other failure gets a general
    sentence that points to the server log. An account whose last failure happened before this update
    shows the general sentence until its next sync. For API clients: GET /recipe-providers/status
    carries lastErrorReason and lastErrorParams next to lastError, and a failed sync or
    connection test answers with reason and params next to error; lastError and error are
    unchanged.

  • The demo seed now works on an encrypted database (#2114). scripts/seed-demo.js opened
    the file without a key and stopped with "file is not a database" on every installation with
    DB_ENCRYPTION_KEY set, which is the installer default. It now opens the database the way the
    server does: it reads .env from the working directory, applies the key, and runs the
    migrations, so it also fills a database the server has not opened yet. --db still wins over
    DB_PATH, and --locale is unchanged. A wrong key ends with the same message the server
    gives instead of a stack trace.

  • Shared expenses: a group now shows all its expenses, not just the 30 most recent (#2108).
    Older expenses could not be opened, edited or deleted. "Load more" under the expense list now
    loads the next page, like the history below it, and after you edit or delete an expense the
    list keeps everything you had loaded. Switching to another group starts at the top again.
    Balances were always complete and are unchanged. API: expenses of a group are now ordered by
    id as a last key, so expenses written in the same second keep a fixed place, and they page
    with a cursor: pagination.next_cursor (before_date, before_at, before_id) continues
    behind the last expense, so one deleted meanwhile no longer makes the next page skip another.
    offset keeps working, and pagination.has_more is false when exactly limit expenses remain.

  • Menus no longer all stand open on older browsers (#2107). On a browser without popover
    support - Chrome or Edge before 114, Firefox before 125, Safari or iOS before 17, such as a
    wall frame stuck on an old system WebView - every "more" menu, the account menu and the
    Overview's New menu were drawn open on top of the page and caught the taps meant for what lay
    underneath. These menus now stay hidden there, and their buttons do nothing; everything else
    works as before. Log out is also under Settings > Account. Current browsers are unchanged.

  • Birthdays without a year from iCloud no longer show the year 1604 and an age of over 400
    (#2095).
    iCloud stores a birthday without a year with the placeholder year 1604 and marks it;
    the contact sync and the .vcf import read the date but not the mark. Both now recognise it, and
    the --MM-DD form other apps write, as a birthday without a year. Birthdays and contacts can now
    be saved as "Year unknown": the editor offers it as a checkbox under the date, which swaps the
    date picker for month and day. Such a birthday shows day and month only and no age - in the list,
    the detail view, the overview tile, the wall and the calendar - while sorting, the next birthday
    and reminders work as before, 29 February included. Contacts and birthdays already stored with
    1604 are converted on update, so you do not have to enter them again.
    The same choice is in your profile and in the member editor under Settings, for a member whose
    birthday has no year.
    API: birthdays carry year_unknown, contacts birthday_year_unknown (0 or 1; true/false
    accepted on create and update) and members birth_year_unknown. With it, the date carries the placeholder year 2000 and
    next_age is null; calendar reads return birthday_date: null for such a birthday. The vCard
    export writes it as BDAY;X-APPLE-OMIT-YEAR=1604:1604-MM-DD, the form Apple reads.

  • Deleting or editing one occurrence of a series affects only that one, also on the night of a
    clock change (#2034).
    For a series at 01:30 in Berlin, "only this one" on 25 March 2035 also
    removed the day before. "This and following" on a series in another time zone - say Los Angeles
    at 23:30 - left the chosen occurrence in the old series and showed it again in the new one, and
    for a series that ends after a number of times east of UTC it failed with an error.

  • The countdown tile skips a cancelled occurrence of a series in another time zone (#1998).
    A series from Los Angeles in a Berlin household counted down to an occurrence the calendar had
    already hidden, and could name the wrong day. The tile now counts on the same occurrences as the
    calendar and shows the day it falls on in your household.

  • The countdown tile stops when a series in another time zone ends (#1998). For an imported
    series with its own time zone, the tile could keep counting past the series' end: an end date
    with a time of day, or "ends after N times" on a monthly series anchored after the 28th, still
    produced a next date the calendar no longer showed. The tile now takes its next date from the
    same series calculation as the calendar, so both always name the same day, and a long-running
    series is still found without counting through every past occurrence.

  • Search shows the right next date for a calendar series in another time zone (#1999). A
    series kept in its own time zone, such as an imported one from a calendar in Los Angeles, was
    checked against your household's today on its own calendar day. Near midnight that is a
    different day: at 23:30 in Los Angeles it is already the next morning in Berlin. Search then
    skipped an occurrence that happens today and showed the one a week later, or showed one from
    yesterday as the next date. Search and the calendar now place every occurrence on your
    household's day before comparing.

  • Budget category bars are one color again, and their stripes stand at 45 degrees (#2084).
    Every expense bar in the Overview and in Statistics started with a short stroke in the module
    color instead of the category color, which was most visible on short bars. The two striped
    categories (the sixth and seventh color, striped so they stay apart with color vision
    deficiencies) showed their stripes almost upright on short bars instead of diagonal, which read
    as a rendering error. Both now follow the category: the stroke takes its color, and the stripes
    keep their angle at any bar length.

  • Saving in a Health dialog no longer closes a dialog you opened in the meantime (#1997).
    Measurements, medications and dose entries, lab reports, activities, prevention records,
    nutrition entries and targets, periods, cycle days, the cycle history import and the cycle
    settings now close only the dialog the save came from. If you had closed it and opened another one
    before the answer arrived, the other one stays open with what you typed in it.

  • Saving in a Waste or Shopping dialog no longer closes a dialog you opened in the meantime (#1997).
    In Waste, waste types, collection schedules, one-off pickups, moved pickups, sources, the calendar
    import, mapping profiles and reminder settings now close only the dialog the save or delete came
    from. In Shopping, the same holds for editing an item, sending, duplicating, moving ticked items to
    the pantry and taking ingredients from the meal plan, and for the reload after something was deleted
    elsewhere. If you had closed the dialog and opened another one before the answer arrived, the other
    one stays open with what you typed in it.

  • Saving in a Schedule, budget plan or family settings dialog no longer closes a dialog you opened
    in the meantime (#1997).
    In Schedule, adding and editing shift types, patterns, exceptions and
    extra shifts and saving a custom field now close only the dialog the save came from, also after
    the overlap or range question. The same holds for setting and removing a budget plan, adding and
    editing a household member, the prevention types in the Health settings and the recipe provider
    accounts in the Kitchen settings. If you had closed the dialog and opened another one before the
    answer arrived, the other one stays open with what you typed in it.

  • Saving a task, contact, birthday, inventory item, quick link or sync account no longer closes a
    dialog you opened in the meantime (#1997).
    Adding and editing a task, a contact, a birthday or an
    inventory item, setting a tag on several selected tasks, the vCard import, taking birthdays over
    from contacts, marking an inventory deadline as done and adding or editing a quick link now close
    only the dialog the save came from. The same holds for adding a CalDAV account, adding and editing
    a CardDAV account and editing a calendar subscription in the settings. If you had closed the dialog
    and opened another one before the answer arrived, the other one stays open with what you typed in it.

  • Saving an event, a meal, a pantry item or a shared expense no longer closes a dialog you opened
    in the meantime (#1997).
    Adding and editing a calendar event, adding and editing a meal (also as
    a series), filling the week at random, sending a meal's ingredients to the shopping list, deleting
    a meal, adding and editing a pantry item, and in Shared expenses adding a group, an expense, a
    payment, a recurring expense, a member or a guest now close only the dialog the save came from. If
    you had closed the dialog and opened another one before the answer arrived, the other one stays
    open with what you typed in it, and focus stays where you are.

  • A dialog that is still loading no longer replaces one you opened in the meantime (#1997).
    Dialogs that load something first now open only if you are still where you asked for them:
    editing a contact, a budget transfer, a calendar event from its details or a family member;
    managing quick links, calendars, inventory locations and categories, pantry locations or reward
    participants; importing birthdays; matching ingredients to the pantry; a member's points or pocket
    money history; sending a shopping list or moving checked items to the pantry; editing a shared
    expense group or inviting a member; waste reminders and the mapping profile preview. If you had
    opened another dialog or left the page while it loaded, the other dialog stays open with what you
    typed in it. After deleting a subscription category or payment method, the management dialog no
    longer reopens over another dialog, and saving a prevention type that no longer exists closes only
    its own dialog.

  • Inventory, notes, contacts and birthdays: an error message is in your language and names the
    cause
    (#1909). These pages showed the server's own text when something could not be saved,
    pinned, completed or deleted, whatever the app language, in English or in German - for example
    "Notiz nicht gefunden" in an English session when somebody else in the household had deleted the
    note in the meantime. An item, tracked date, booking, note, contact or birthday that no longer
    exists, a location or note category chosen in the form that was deleted in the meantime, and a
    booking that is already linked now get a sentence in the language of the app. When the thing
    itself is gone, the page takes it out of the list and closes the dialog of the action; deleting
    something somebody else has already deleted counts as done instead of bringing the row back with
    an error, also when you delete several contacts at once. When only the chosen location or note
    category is gone, the form stays open with your input and offers the current ones; a booking
    noted for a new item that is gone is dropped from the form. A picture that cannot be used for an
    item or a birthday keeps its own message, and any other failure there shows the general message
    instead of the browser's own text. When a list cannot be refreshed after you change locations or
    categories, the message says why (offline, server, too many requests) instead of the server's
    text. The contact import still names the field a vCard was rejected for. For API clients: those
    answers of /api/v1/inventory, /api/v1/notes, /api/v1/contacts and /api/v1/birthdays carry
    a reason next to error (inventory_item_not_found, inventory_tracked_date_not_found,
    inventory_booking_not_found, inventory_booking_already_linked,
    inventory_selected_location_not_found, notes_note_not_found,
    notes_selected_category_not_found, category_exists, contacts_contact_not_found,
    birthdays_birthday_not_found), the German texts of those answers are now English, and the
    status codes are unchanged.

  • Saving in a Budget or Housekeeping dialog no longer closes a dialog you opened in the meantime (#1997).
    In Budget, entries, loans, accounts (save and archive) and confirming a planned entry now close only
    the dialog the save came from. In Housekeeping, the same holds for adding and editing a task,
    editing a visit and saving a staff member. If you had closed the dialog and opened another one
    before the answer arrived, the other one stays open with what you typed in it.

  • Tasks, inventory locations and categories, contact form: an error message is in your language
    (#1909). The tasks page showed the server's or the browser's own text when ticking off, moving,
    archiving, sorting, tagging, saving or deleting a task failed, for example "Task not found." in a
    German session. It now says the sentence of the app; a task that somebody else deleted or made
    private in the meantime is named as such, the list is reloaded, an open edit form for it closes,
    and deleting a task that is already gone counts as done, also when you delete several at once.
    The managers for inventory locations and categories now say "this location already exists here"
    and "this location (or category) no longer exists" in your language instead of the server's
    English text, and deleting one somebody else already removed counts as done. In the contact form,
    a chosen category that was deleted in the meantime keeps the form open with your input and offers
    the current categories. For API clients: those answers carry a reason next to error
    (tasks_task_not_found, inventory_location_exists, inventory_location_not_found,
    inventory_category_not_found, category_exists for inventory categories,
    contacts_selected_category_not_found), and the status codes are unchanged.

  • Task view, shift schedule, confirm dialogs and module install: error messages in your language
    (#1909). The open task showed the server's or the browser's own text when finishing, starting,
    archiving, adding a subtask, ticking a line or writing, editing or deleting a comment failed, for
    example "Parent task not found." It now says the sentence of the app. A task that somebody else
    deleted or made private in the meantime closes the view and reloads what is behind it, and
    deleting a task or comment that is already gone counts as done. The shift schedule no longer shows
    the server's English text: a shift type, field, plan or entry that was deleted in the meantime is
    named as such and the page reloads, deleting one that is already gone counts as done, and the
    messages for "shift type still in use", "cycle too short" and "choose a shift type" now come from
    the case, not from matching the server's wording. The error line of a confirm dialog and the
    messages of the module installer in the settings say the app's sentence instead of the server's
    text when there is no known cause. For API clients: those answers carry a reason next to
    error (tasks_parent_not_found, tasks_comment_not_found, schedule_shift_type_not_found,
    schedule_custom_field_not_found, schedule_pattern_not_found, schedule_override_not_found,
    schedule_extra_shift_not_found, schedule_selected_shift_type_not_found,
    schedule_selected_custom_field_not_found, schedule_shift_type_in_use,
    schedule_cycle_length_conflict, schedule_shift_type_required), and the status codes and
    texts are unchanged.

  • Housekeeping and rewards: error messages in your language (#1909). Checking in or out,
    finishing, editing or deleting a chore, paying, editing or deleting a visit, saving a housekeeper
    and stepping through the reports showed the server's or the browser's own text, for example
    "Visit not found." The rewards page did the same when redeeming, deciding a request, granting
    points, editing the catalogue, the participants or pocket money. Both now say the sentence of the
    app. A visit, chore or request that somebody else deleted or decided in the meantime, or a
    housekeeper who was checked out already, is named as such and the page reloads; deleting one that
    is already gone counts as done. Deleting a reward no longer fails silently. For API clients: those
    answers carry a reason next to error (housekeeping_worker_not_found,
    housekeeping_visit_not_found, housekeeping_task_not_found,
    housekeeping_open_session_not_found, housekeeping_already_checked_in,
    housekeeping_username_taken, housekeeping_username_invalid, rewards_reward_not_found,
    rewards_redemption_not_found, rewards_redemption_decided, rewards_insufficient_points,
    rewards_not_participating, rewards_money_account_not_found, rewards_money_plan_not_found),
    and the status codes and texts are unchanged.

  • Quick links, budget, waste import and recipe sources: error messages in your language
    (#1909). Saving or deleting a quick link showed the server's own text, for example "At most 24
    quick links can be created." in every language, and picking an unsuitable picture for a tile
    showed the browser's text. The budget page passed the server's text through for some failed
    saves, a waste calendar import printed the server's English note for an entry it did not know,
    and "Sync now" for a recipe source showed the raw error of the fetch. All of them now say the
    sentence of the app; the recipe source card keeps naming the cause of the last failure. A quick
    link that somebody else deleted in the meantime is named as such and the list reloads; deleting
    one that is already gone counts as done. For API clients: those answers carry a reason next to
    error (quick_links_link_not_found, and quick_links_limit_reached with params.limit), and
    the status codes and texts are unchanged.

  • Kitchen settings: error messages in your language (#1909). Adding a recipe provider, changing
    its link, turning it on or off, syncing or removing it showed the server's own English text when
    something went wrong, for example "Base URL must start with http(s)://" or "Could not connect to
    the recipe provider with these credentials.", and so did saving the visible meals or their names.
    All of them now say the sentence of the app, and a server address in a private network still names
    the setting that allows it. A recipe provider that another admin removed in the meantime is named
    as such and the list reloads; removing one that is already gone counts as done. For API clients:
    those answers carry a reason next to error (recipe_providers_account_not_found,
    recipe_providers_url_invalid, recipe_providers_external_url_invalid,
    recipe_providers_private_network, recipe_providers_connection_failed,
    recipe_providers_account_exists), and the status codes and texts are unchanged.

  • Contacts and housekeeping: error messages in your language (#1909). When every contact of a
    vCard import failed, the message named the rejected field in the server's English text, for
    example "Telefon may be at most 100 characters long." It now says the sentence of the app, which
    still names the field and its maximum length, or that the birthday is not a valid date; saving
    the contact form says the same. Opening a housekeeping visit from a calendar link that no longer
    works now names a deleted visit as such and says to wait a moment when the server asks
    to wait, instead of a general error. For API clients: creating or editing a contact with a field
    that is too long or an invalid birthday carries a reason next to error
    (contacts_name_too_long, contacts_phone_too_long, contacts_email_too_long,
    contacts_address_too_long, contacts_notes_too_long with params.limit, and
    contacts_birthday_invalid), and the status codes and texts are unchanged.

  • Contacts: the form says which phone number or email address it refused (#1909). Saving a
    contact with an email address without an @, or a phone number that was too long, said only that
    an error occurred. It now says what is wrong: that the email address needs the form
    name@example.com, or how long a phone number may be, and likewise for too many entries or a label
    that is too long. For API clients: every refusal of phones, emails and addresses carries a
    reason next to error (contacts_phones_too_many, contacts_emails_too_many,
    contacts_addresses_too_many, contacts_phone_label_too_long, contacts_email_label_too_long,
    contacts_address_label_too_long, contacts_address_part_too_long, contacts_phone_too_long and
    contacts_email_too_long with params.limit, contacts_email_invalid, and
    contacts_phone_entry_invalid, contacts_email_entry_invalid, contacts_address_entry_invalid
    for an entry that is incomplete or malformed), and the status codes and texts are unchanged.

  • Contacts: a phone number may be 100 characters long everywhere (#1909). The form sends the
    first number twice, as phone and as the first entry of phones, and the two had different
    limits: a number of 101 characters was refused with "at most 100", and after shortening it to 60
    with "at most 50". The list phones now accepts 100 characters like the single field, so a number
    between 51 and 100 characters - for example one written with an extension or a note - saves, and
    the phone fields of the form stop at the same 100 characters. One limit for the server and the
    form lives in public/utils/contact-limits.js.

  • Recurring events on the day the clocks change are no longer an hour off (#2034).
    A series with its own time zone, for example a daily 01:30 event in Berlin, showed the occurrence
    on the day of the clock change one hour early or late, both in the calendar and in subscribed
    calendars. Each occurrence now keeps its local time. Where that time does not exist on the day the
    clocks go forward (02:30 in Berlin), the occurrence moves forward by the skipped hour; where it
    exists twice when the clocks go back, the first one counts. Occurrences you deleted or changed keep
    their place.

  • Older series ends now reach Google, CalDAV, iCloud and the calendar feed on the same last day Yuvomi shows (#1992).
    Before #1989 the repeat form saved a series end as the end of the UTC day, and series saved that
    way still carry it. For a series without its own time zone Yuvomi ends it on that date, while
    other calendars read the UTC moment: west of UTC (for example Chicago, 8 pm) they dropped the last
    occurrence, east of UTC (Berlin, 0:30) they showed one more. Such a series now goes out with the
    end of that day in the household's time zone, so both sides end on the same occurrence. Nothing
    stored is rewritten: the calendar feed shows the corrected end right away, Google, CalDAV and
    iCloud receive it with the next change sent for that series, and reading it back counts as
    Yuvomi's own change rather than an edit in the other calendar. Series imported from other
    calendars still go back word for word.

  • Reconnecting or disconnecting Google Calendar now stops a sync that is still running (#2035).
    A sync that was waiting on Google while you reconnected, perhaps with another account, or
    disconnected used to carry on with the old connection: it could still send queued changes to the
    previous account, import its events after the disconnect, and leave its progress and errors on the
    new connection. It now stops at its next step, and the new connection's own sync takes over. A
    reconnect also no longer removes calendars from the selection based on the calendar list of an
    account that was replaced in the meantime.

  • An account that signs in only through single sign-on no longer sees a change-password form.
    Such an account has no password, yet the account page asked it for the current one, so the form
    could never succeed. The card now only appears for accounts that have a password, linked to a
    provider or not. For such an account the page subtitle no longer mentions a password, and the
    single sign-on card now says to ask an administrator to set one instead of "Set a password first"
    (#1703).

  • A task ticked off in Apple Reminders or another synced reminders app now counts as done (#1836).
    It used to be marked done without a record of when, so it was missing from the task history, and
    an overdue one disappeared from the wall display instead of getting its check mark. It now shows
    in the history at the time it was completed on the phone, labelled "Via sync" since the sync
    cannot tell who ticked it off, and reopening it there removes the entry again. Marking a
    housekeeping visit as paid likewise records its payment task as done by the person who marked
    it, and taking the payment back removes that again. Tasks completed this way before the update
    stay without an entry, and points are still only booked when a task is ticked off in Yuvomi.
    API: entries of GET /api/v1/tasks/completions and the series history carry source
    (null for a completion in Yuvomi, "caldav" for one taken over by the sync).

  • Moving a completed reminder into or out of a parent reminder now updates the task history (#2078).
    When the reminders app changed only which reminder a completed one belongs to, the history kept
    its old state: a completed task moved under another one stayed in the history, although subtasks
    never appear there, and a completed subtask moved out to stand on its own never showed up. Now
    the first loses its entry, and the second gets one at the time it was completed on the phone. If
    the reminder carries no completion time, it stays without an entry rather than claiming it was
    done at the time of the sync.

  • Saving no longer counts as failed when only the refresh afterwards fails. Many dialogs
    reloaded their list in the same step as the save. When the save went through but the reload hit
    a network blip or a busy server, the dialog stayed open with a "could not save" message, and
    saving again created the entry a second time. Now the dialog closes once the save went through,
    and a failed refresh says so in its own notice. This covers pantry, budget, inventory, meals,
    tasks, health, housekeeping, waste, rewards, documents, schedule, calendar and several settings
    pages.

  • Logging a dose counts down the stock in the same step. Taking a planned or as-needed dose
    used to log it and then update the stock in a second request; when the second one failed, the
    dose was logged but the stock stayed where it was. The server now does both together, from the
    stored stock. Tapping the dose again after a dropped connection no longer logs it twice or
    counts the stock down twice: the app repeats the same request, and the server answers it once.
    API: POST /api/v1/health/medications/{id}/logs and POST /api/v1/health/logs/{id}/take
    accept stock_deduct. A second POST .../logs for the same schedule_id and scheduled_at
    updates the existing entry (200) instead of adding another one.

  • A countdown to an evening event no longer names the next day. With the server running in UTC
    (the default container) and a household east of UTC, an event at 23:30 counted down to the day
    after; west of UTC, an early-morning event could count down to the day before. The countdown now
    reads the event's time in the household's time zone, wherever the server runs (#1998).

  • A session that ends while the sign-in page is open no longer wipes what you typed (#1945).
    When a request found the session gone, the app drew the sign-in page again even when it was
    already showing, so a half-typed user name and password were cleared; with setup still pending
    the same happened to the setup page. A session that ends on a page that needs no sign-in (sign-in,
    setup, invitation, display pairing, password reset) now leaves that page as it is. On every other
    page it still leads to the sign-in page.

  • A new medication is saved together with its intake plan, or not at all. If saving one of
    the plan's times failed, the medication itself was already stored. Cancelling the dialog then
    left it behind without its plan and without showing it in the list, so it was easy to add it a
    second time. The medication and its plan are now saved in one step; if that fails, nothing is
    stored and the dialog keeps everything you entered, so Save simply tries again (#2054).
    API: POST /api/v1/health/medications accepts an optional schedules array and writes the
    medication and its schedules in one transaction.

  • Saving in a rewards dialog no longer closes a dialog you opened in the meantime (#1997).
    Redeeming a reward, granting bonus points, adding or editing a reward, booking pocket money,
    setting a pocket-money plan and opening a pocket-money account now close only the dialog the save
    came from. If you had closed the dialog and opened another one before the answer arrived, the
    other one stays open with what you typed in it.

  • Large imported recipe collections no longer lock up the app with "Too many requests" (#2048).
    On iPhone and in Firefox the recipe list fetched the picture of every imported recipe at once
    instead of only those on screen, and each picture went to Mealie or Tandoor again on every visit.
    With 500 recipes that used up the request budget of a whole minute, and every other page answered
    with an error until it refilled. The list now loads only the pictures you scroll to, a picture the
    browser already has is confirmed by Yuvomi without asking Mealie or Tandoor again, and pictures
    (recipes and profile pictures) have a budget of their own, so they can no longer block the rest
    of the app.
    API: GET /api/v1/recipes/{id}/provider-thumbnail takes an optional ?v=, the recipe's
    provider_updated_at (meal rows carry it as recipe_image_version). The response is
    private, no-cache with an ETag derived from that version, and If-None-Match answers 304
    without a request to the provider.

  • An open row menu closes when the list scrolls. With a mouse wheel, trackpad or keyboard the
    menu stayed where it opened while its row scrolled away, so "Delete" ended up under a different
    entry. Like menus on iOS and macOS, it now closes as soon as the content beneath it moves, in
    lists, headers and sheets alike; scrolling inside a long menu keeps it open (#2041).

  • On the overview, the people of an event sit at the end of its line in right-to-left
    languages.
    In Arabic and Persian they sat right after the event's title instead. Left-to-right
    layouts are unchanged.

  • Typing Japanese, Korean or Chinese no longer saves half a word. In these languages Enter
    first confirms the character conversion. Dialogs, tag and mention fields, suggestion lists and
    the comboboxes used to act on that Enter and saved or picked the text while it was still being
    written; they now wait for the conversion to finish. Esc, which cancels a conversion, no longer
    closes the dialog either.

  • New health entries start at the household's time. Vitals, activity and nutrition prefilled
    "now" from the device clock, while Yuvomi reads the value in the household time zone. On a phone
    set to another zone, for example while travelling, saving the default stored a shifted time and
    sometimes the wrong day.

  • Esc in a picker of the subscription form closes only the picker. The lists for currency,
    cycle, category, account and payment method and the logo search used to close the whole form
    with the same keystroke. Closing the logo search puts the keyboard focus back on its button.

  • Open browser tabs no longer reload extension translations every 30 seconds. With extension
    modules installed, each open tab fetched every language file of every module twice a minute, also
    in the background. They now load again only when a module was installed, updated or changed its
    languages, and a tab in the background skips the check.

  • Switches, active filters and tabs stay visible in Windows high contrast mode. The mode
    replaces the app's colours with system colours and drops shadows. A switch then disappeared
    completely, the active filter chip and the active tab looked like the others, and a focused input
    field showed no focus. Each of them now uses the system highlight colour or an outline there.

  • The page no longer flashes white in dark mode before the styles load. The app and the offline
    page now tell the browser up front that they support light and dark, so the background, scrollbars
    and form fields start in the right colour. A theme you picked yourself wins over the system setting
    from the first frame too.

  • "Undo" in a toast is reachable with the keyboard while a dialog is open. Tab used to jump from
    the dialog's last button back to its first, past the toast. A dialog now leaves keeping the focus
    inside to the browser.

  • The More sheet, search, the welcome tour and the pickers inside forms lock the page behind
    them.
    These layers only asked screen readers to stay inside; the page behind them could still
    be reached with Tab, a click or the virtual cursor. It is now inert while the layer is open. After
    the welcome tour, the keyboard focus returns to the page content instead of getting lost.

  • Setting a password tells you the rule before you try. First-time setup, joining by
    invitation and resetting a password showed "at least 8 characters" only as an error after
    submitting. The rule now stands under the field. An error on these pages and on "Forgot password"
    also marks the field it means, so a screen reader names it there, and "Forgot password" with an
    empty field says what is missing instead of only moving the cursor.

  • Required fields say so to screen readers, and every form shows which fields are required. In
    the budget's entry, account and loan dialogs and the waste type dialog the asterisk was only
    visual; the field now reports itself as required. About thirty fields required an entry without
    the asterisk, among them adding and editing members, your profile and password change, API tokens,
    document management, Immich, Apple Calendar, calendar subscriptions, folders, documents, health
    entries and medication, pairing, bonus points and shopping items. Forms with a single field and
    the sign-in pages stay without it.

Security

  • Contact websites and recipe links only open http and https addresses. A website from a
    synced address book or a recipe link from the API or a recipe provider could carry a
    javascript: address and became a clickable link. Such values now show as plain text or no link.
  • Password managers no longer offer your Yuvomi password for other services. The password and
    token fields for CalDAV, Apple Calendar, WebDAV backup and storage, document management, email,
    Immich and push notifications asked for the sign-in of this site, so a password manager could fill
    in your Yuvomi password and send it to that server on save. They now mark themselves as a new
    password, the hint that keeps a saved password out (an "off" is ignored by many browsers on password
    fields); the CardDAV form, the recipe provider token and the backup key field do the same.
  • Widget names from extension modules are escaped on the Overview. In customize mode and on the
    error tile the name went into the page unescaped.

Don't miss a new yuvomi release

NewReleases is sending notifications on new releases.