A field outside a form gets enterkeyhint="done", but a web view only sends Enter and nothing listened, so the key did nothing. When no handler took the Enter (same text, still focused a moment later) the field lets go of the focus; a field that acts on Enter and clears itself keeps it. TestFlight feedback, 5.1.3.
A proxy's block page or a refused client certificate (Cloudflare's "Sorry, you have been blocked") left the app on a page without TREK's UI and no way to change the server. Any 4xx main-frame page that the client-certificate path does not handle now shows the sign-in bar with its own hint and "Change server", on iOS and Android. TestFlight feedback, 5.1.2.
The claim screen loads the agreement text and its version from /api/iap/consent, shows it with its own checkbox and buys nothing until it is ticked. The redeem sends consent { acceptedDeviations, version }; a refusal for an outdated text reloads it and asks again without a second purchase.
The login card is a fixed light surface whose text colours are written out,
not tokens. Four of them moved with the two-factor step, so the baseline moves
them too: 58 to 54 for the page, 4 for the new component, the same total.
A partial update that left day_id out (a notes-only PUT, an MCP
update_reservation or update_transport call) re-derived the day from the
stored reservation_time whenever one was set. A time-only value such as
"12:00" resolves to no day, so the booking's day_id was written as null and
it vanished from its day in the planner. The end_day_id branch did the same
when a time-only reservation_end_time was sent.
The day is now derived only when the time carries a date that resolves to a
trip day; otherwise an omitted day_id or end_day_id keeps the stored value.
A dated time still re-pins the day, an explicit day_id null still clears it,
and a cleared end time still clears end_day_id. REST and both MCP update
tools share updateInTx, so the fix covers all three.
Tests: service unit cases (RESV-SVC-044..048), an e2e case per behaviour
on PUT /api/trips/:tripId/reservations/:id, and an update_reservation MCP
case, all seeded with the ORM factories.
Fixes#3025
Both files had grown past their size limit with this round's fixes. The
two-factor step moves to pages/login/MfaCodeStep.tsx and the reservation row
types to reservation-rows.ts, re-exported from the repository, and both size
baselines come down to match.
On iOS the keyboard plugin sizes the body and zeroes the scroll inset in a
frame update that runs after the keyboard is up, so the room made for it was
taken back. The inset is now kept while a sign-in page shows, the body gets its
height back after that update, and with the keyboard down the page can scroll
past the bar. On Android before 11 the keyboard went unseen in the insets
Capacitor passes on, so the bar stayed over the form; it is read off the
window's own insets now.
Behind Pangolin or authentik the app shows the proxy's sign-in page itself, and
nothing on it led back to the address screen: a failed passkey left users stuck
on every launch. A bar over that page now offers to change the server and says
that passkeys and security keys do not work there, as a web view cannot use them
for a domain the app is not tied to. It steps aside while the keyboard is up.
On iOS the page also gets the room the keyboard takes, so a button under it can
be scrolled into view. The address screen hands the bar its words in the user's
language when it connects.
The pager held the selected day and two either side, and moved that window
only once the strip had come to rest. Swiping on before the snap settled ran
into the end of the strip after two days and sprang back until the animation
was over. Every day now has its page, only the selection and two either side
draw their content, so a run of swipes goes as far as the trip does.
A booking with stopovers was one stop at its first departure, and a stop
counted as done the moment it began. With a car at one and a connecting flight
at two, the Live Activity said all done for today mid-afternoon. Each leg is
now a stop of its own, as the planner shows it, and a flight or anything else
with an end time counts as under way until it lands or ends.
The edit form fell back to the linked stay's times, the cards read only the
booking's metadata, so a hotel showed 15:00 and 11:00 when edited and no times
in the list. The reservation list now carries the stay's check-in window and
check-out, and the desktop facts and the phone card fall back to them. On the
phone they come first, so a price or a seat cannot push them off the card.
The prompt looked at the app's features once, when the user counted as signed
in. After the sign-in the page loads with the session already there, and on
iOS the bridge had not named its features yet, so the prompt gave up for good.
It now waits for them. It also counted as asked the moment it opened, so a
sheet that went under another one never came back; it counts once answered.
The code step drops the email field, so a password manager had no login to
match a one-time code to; the step now keeps the address in a hidden username
field. The code field names itself and sets its keyboard hints directly
(characters, no autocorrect), as autoFocus gave it focus before anything could
prepare it, and its placeholder is translated.
The file preview kept its data source in a stored property inside an
extension, which Swift does not allow, so every iOS build since failed. It is
a static now, in its own extension, and the Wallet comment it had split is
whole again.
The fixes that keep the app's sign-in in the app live in the server's UI,
so an updated app on a 5.1.2 server still ended in the browser. The server now
reports nativeApi 2 and the app refuses anything below it, naming 5.1.3.
A server the app remembers from before is not loaded unchecked: the first
launch after the update shows the address screen filled in with it, says why
and checks it right away. A server that is new enough loads again with its
session; an older one gets the update hint.
The strip re-centred only when its window of pages changed. On a trip of up
to five days a tap can keep the same pages, so the rail showed the new day
while the card below stayed on the old one.
The iOS app rewrites raster tiles to trek-tile:// and answers them from its
store. WebKit checks that scheme against img-src, which had only https:, so
every tile was refused and the app showed routes and markers on a blank map.
The app's browser sign-in opens /native-handoff, which sends the user on to
the identity provider by itself. The page was not on the list of public auth
pages, so the 401 from loading the user sent the browser to /login with the
hand-off as its return path first. On a server that also offers passwords the
user then had to pick SSO a second time before getting back to the app.
A PDF, image or document opened in the app went straight to the share sheet.
It now opens in Quick Look on iOS, to page through and zoom with its own share
button, and in the app that views its type on Android. An app without the
viewer (feature filePreview), or a type nothing on the device shows, gets the
share sheet as before.
The home assistant wrote its answer and offered the trip's own chat in the
same step. The loop asked the model once more after the card, and it wrote
the same answer a second time below it. A step that has its answer and only
hands the conversation on now finishes the turn; a hand-on without an answer,
or beside a read, still asks the model again.
The actions under a swiped row were square blocks to the row's edge, unlike
the rounded cards around them. They are now tiles of their own with the
card's radius and a gap, inset within a grouped card such as the packing
list, and show only their icon (the label names them for a screen reader).
An expense already shows edit and delete beside its card, so it no longer
swipes to a second, larger pair of the same buttons.
An app linked against an SDK older than iOS 27.1 runs letterboxed on the inner
display of an iPhone Duo. The iOS build and the release now run on GitHub's
xcode-27 image and select Xcode 27.1; the previews stay on Xcode 26.
From #3032, adjusted where it broke:
- react and react-dom are pinned in the root overrides; the group raised the
workspaces to 19.3.1 and left the override at 19.3.0, so two react-dom
versions met in every client test. The override moves along.
- @mikro-orm/nestjs kept the old @mikro-orm/core at the root while the server
got 7.2.8 of its own, two copies whose types do not match; the lockfile now
holds one 7.2.8.
- mapbox-gl stays at 3.31: 3.34 drops setRTLTextPlugin from its types, which
the map engine uses.
- the musl pins of rollup stay at 4.62, the rollup version the lockfile holds.
@capacitor/cli 8.6 drops the old uuid 7 through its xcode dependency (#3012).
vite-plugin-pwa 2 keeps the registerSW.js in public/ in place of its own, as
1.x did (#3033). @nestjs/schedule 12 still runs on Nest 11 (#3035).
The login on an iPhone scrolls in no pane of its own, and the keyboard plugin
holds the body's height, so the page had nothing to scroll by and the password
field stayed under the keyboard, most of all with an error shown above it. Such
a page now gets room as tall as the keyboard at its end and scrolls the field
above it; the room goes with the keyboard.
A browser that ran TREK before 5.1.1 keeps that version's app in its service
worker. When the app opened /native-handoff, the worker answered it from its
cache with an app that has no such page, which sent the user to /, and the
sign-in ended on the dashboard in the browser instead of in the app.
The app now opens /api/auth/native/start, which every TREK service worker
passes to the server. That page takes the workers off the browser and
forwards to the handoff page. Until the sign-in is handed back, the web app
registers no service worker and does not reload for a new version: a tab
still open on the older TREK keeps its worker alive, and a registration or a
reload in the middle of the sign-in brought it back to answer the next page.
A proxy that lets /api through (an Authelia or Authentik bypass for the app)
still sends the page itself to its sign-in. The app took that redirect for a
foreign link and handed it to the browser, so the sign-in happened there and
the app stayed black on every launch. A redirect away from the server while
its first page loads is now kept as the proxy's sign-in host, on Android and
iOS, and the iOS bridge guard is always in place for hosts learned that way.
Bookings in the Bookings tab, the day sheet, a place's sheet and the road trip
opened their editor straight away, while a transport showed its details with
a pencil to edit. Every booking now opens the same detail sheet; its edit and
delete follow the booking's own permission (reservation_edit for a stay, a
table or a ticket, day_edit for a transport). Notes keep opening for editing,
as on the desktop.
The wallet button reads "Wallet" (its accessible name still says which one),
and "On map" reads "Map" in every language.
Mapbox GL measures its container on window resizes only. In the app on a
tablet the trip's plan pane closes beside the map without one: the box grew
to the full width while the canvas kept its old size, and the rest stayed
black. Every GL map built through buildGlMap now watches its container and
resizes once per frame while it changes; the observer goes with the map.
Closes#3023
Each photo's write follows its own network lookup, the repair's marker only
records that the pass ran, and a lookup may renew the Synology session on
its own; none of these can share one transaction.