Commit Graph

2172 Commits

Author SHA1 Message Date
Maurice 8ce3b24a01 feat(studio): 71 more designed pages and five new styles, each with a theme of its own
Every style now has four covers and five double spreads, 108 in all, and the
spreads of each style take different photo counts, from a words-only page to
eight photos, so a book can be laid on them without an empty frame. The five
new styles come with their own themes: Riso (overprinted spot inks), Magazine
(a travel magazine), Retro travel (vintage posters), Midnight (a dark film
look) and Field notes (a traveller's notebook). Each new style has a cover
composer for the design engine and a recipe for the assistant, and its chip,
theme and template names are translated into every language.
2026-10-24 20:13:41 +02:00
Maurice 06a1dcd730 fix(journey): the share link's copy button and its switches show their words again
The filled buttons set their label in text-accent-on, the accent used as
text on a plain surface, which on the accent's own ground is the same
colour: a black button with black words. They take text-accent-text, the
colour made for words on the accent, and a test pins it.
2026-10-24 18:28:47 +02:00
Maurice 4b633d8cd2 feat(admin): release notes show a #### heading as the feature it names
The release notes in Admin read ## as the version and ### as a section,
and printed a #### line as plain text. A release that heads each feature
inside a section with #### (Tours, TREK Studio under Added) now shows it
as a feature heading between the section and its text, on desktop and on
the phone.
2026-10-24 18:28:44 +02:00
Maurice 728a275fef chore(assistant): drop Connect with Claude from the integration settings
The card that opened claude.ai's custom connector dialog for this instance
goes, with its phone twin, the line in the assistant setup that jumped to it,
its endpoint and its contract. Anyone who wants Claude uses TREK's MCP
server under Integrations, or an Anthropic key in the assistant. It came with
the assistant and never shipped in a release.
2026-10-24 18:28:41 +02:00
Maurice 01333c6ff3 chore(client): hold the complexity count at the notifications redesign's lower one 2026-10-24 17:31:46 +02:00
Maurice aecef03090 feat(notifications): a tile per kind, the list cut into days, and clear actions
Every notification gets a tile in the colour of what it is about (a trip, a
message, a booking, packing, a to-do, Vacay, a collection, shared photos, a
tour, an update or an alert) with the sender's face on its corner, the page
and the bell's panel group the list under Today, Yesterday, the weekday or
the date, and answering or following a notification is a proper button.
The server's UTC timestamps are read as UTC for the grouping and the time.
2026-10-24 17:31:46 +02:00
Maurice 3c73da4427 fix(assistant): bring the end of a long answer into view once it is written
A new question is held at the top of the view, so its answer reads from its
first line. When the answer carries steps, a strip of places and cards, its
closing words and the changes to apply ended below the view, and the user
saw only the places found. Once the answer is written, the thread now
scrolls to where those closing blocks begin, or to the bottom when they are
shorter than the view, unless the user scrolled it by hand meanwhile.
2026-10-24 16:33:14 +02:00
Maurice cff2e55db7 feat(help): Studio's help as Studio is now, with guides for themes, stickers, travel, text effects, backgrounds, layers and own layouts
The screen texts name the top bar, the rail and the workbench as they are
after the redesign, the travel guide walks through the four tabs, and six
new guides cover what Studio gained since its help was written. Every
Studio picture is taken again, and all texts are translated.
2026-10-24 15:38:36 +02:00
Maurice 429a25faa9 fix(admin): name the addon columns by start and end 2026-10-24 15:10:13 +02:00
Maurice 486a2eeca3 feat(admin): addons tab in the cards of the other tabs, with a search and an on/off filter
The addons sit in a card per type now, the way every other admin tab sets
its cards, instead of three columns nested in one card. A head card shows
how many of each type are on and finds an addon by its name or description,
with a switch between all, the ones on and the ones off.
2026-10-24 15:10:13 +02:00
Maurice 26a6147e8d fix(book): a summary's and a country's look are optional, so a stored book reads and saves as it did
Absent means the classic look. Defaulting it wrote the field into every
element the auto layout and the templates build, which moved their parity
fixtures and grew the page tools past their schema ceiling; the new
descriptions are also shorter for the same reason.
2026-10-24 14:59:00 +02:00
Maurice a7b53988ff feat(studio): rethink the travel tab with many new looks, a saved tile and a newer-book overlay
The travel tab is four tabs now, figures, maps, countries and marks, and
offers only the newer looks, each dressed in the book's theme and linked to
it. The looks books already hold still draw on their pages exactly as
before; they are just no longer offered.

- Figures: a summary as a poster, a ticket, tiles, a road sign, an
  odometer, a handwritten note, a pencil sketch or a band, and each figure
  on its own as a medal, on odometer drums or ringed by hand.
- Maps: the route with its photographs, its stops numbered, its two ends
  marked or on a dark ground, over satellite or relief imagery, a map per
  trip, and a map of each country with its stops alone, cut to its shape.
- Countries: each country as a passport stamp, a visa, an airmail
  postcard, its flag in cloth, a map pin, a luggage label or a sketch.
- Marks: the date, the day, the distance, the coordinates and the flag as
  stamps, tags, pills, ribbons, die-cut stickers, embroidered patches and
  sketches.

The schema gains a summary's and a country's look, seven mark styles and
the numbered and ends stops of a map, all additive, as revision 11.

Also in Studio: the save state is a tile beside who is here, a book a newer
Studio saved is said by an overlay that holds the whole Studio until it
reloads, and the page rail draws the first and the last page beside the
blank inside of their cover. The notifications page and the bell's panel
take the dialogs' look: a head with a tile, cards with an unread dot, and
tools that come forward on hover.
2026-10-24 14:45:04 +02:00
Maurice 3f3e2f0bcf chore(client): hold the refs count and the stylesheet size at what they are 2026-10-24 14:06:40 +02:00
Maurice f956ab07f3 fix(studio): tidy the head row, the layouts tab and the theme panel
Every piece of the head row is one raised tile of one height: the format
picker moved beside the tools, the assistant and help stand alone, the
close button is square like the rest, and the beta mark is gone. The
layouts tab lays the book's own and the built-in layouts out in sections
and in the same grid as the designed pages. In the theme panel the accent
dots sit in the sheet's corner, the three accents share one name, a font
keeps its name ahead of its kind, a doubled rule is gone, and the
inspector's empty hint is shorter.
2026-10-24 13:54:49 +02:00
Maurice 1be997f7d8 test(studio): the pattern picker test counts the tiles against BOOK_PATTERNS 2026-10-24 11:36:30 +02:00
Maurice 5a8ff16afa test(studio): the shape swap test finds the ellipse by its translated name 2026-10-24 11:28:13 +02:00
Maurice 4435dc32b8 refactor(studio): gradient stops built by a plain function; the letters' fill in a helper 2026-10-24 11:07:16 +02:00
Maurice f5a33e0c1e refactor(studio): a paint's SVG parts in a module of their own; the pattern letters a component of their own 2026-10-24 11:07:16 +02:00
Maurice a8326b6f5a chore(client): the shape name entry at the end of the dynamic key list, beside the sticker one 2026-10-24 11:07:16 +02:00
Maurice 1e999d968a fix(studio): the new stickers drawn with the path commands the catalogue takes; the text fill test without Array.at 2026-10-24 11:07:16 +02:00
Maurice 9695e269e3 fix(studio): shapes named in every language, the align target kept across selections, up and down in a tab grid 2026-10-24 11:07:16 +02:00
Maurice 82bdf62c7b feat(studio): linen and paper grain, two quiet textures among the patterns 2026-10-24 11:07:15 +02:00
Maurice 8893e3afe0 feat(studio): letters filled with a gradient or a pattern 2026-10-24 11:07:15 +02:00
Maurice cd1e7d8fa8 refactor(pdf): call the markdown row directly 2026-10-24 10:39:36 +02:00
Maurice 059e72df69 refactor(pdf): the markdown rows and styles in a module of their own; the shared stop's markdown test beside its component 2026-10-24 10:39:36 +02:00
Maurice dc519b3ea7 fix(journey): a journey's created_at is an epoch number 2026-10-24 10:39:36 +02:00
Maurice ad4074f107 fix: journey year helper takes what a journey row carries; PDF markdown test without casts 2026-10-24 10:39:36 +02:00
Maurice 0534d7b3a7 fix: test strings, logical sides in the PDF markdown styles, one export per markdown module 2026-10-24 10:39:36 +02:00
Maurice a0554c2346 fix: four reported bugs that dev still had
- Dashboard: a browser that names no time zone (Chrome on Windows for a zone
  it cannot map) crashed the world clocks and the whole dashboard. One helper
  now reads the browser zone and every reader picks its fallback; a stored
  zone the browser does not know is left out instead of throwing (#2694).
- Phone: a leg of a multi-leg train or flight showed only its route, and its
  sheet showed the first leg's seat. The day plan subtitle is one helper for
  desktop and phone now, so a leg names its own train or flight, platform and
  seat, translated instead of the hardcoded "Gl."/"Sitz"; the sheet opened
  from a leg shows that leg's number, seat, platform and times (#2701). The
  PDF export translates platform and seat too.
- Journey list: the year badge named the year a journey was written, not the
  years of its trips; a trip over New Year shows both (#2685).
- A place's description and notes are markdown in the planner but printed as
  raw syntax in the PDF export and on a shared trip. Both render it now through
  the app's sanitized markdown pipeline, raw HTML stays text (#2692).

Closes #2694
Closes #2701
Closes #2685
Closes #2692
2026-10-24 10:39:35 +02:00
Maurice bc5af23896 chore(client): lower the test non-null assertion baseline to what the tree holds 2026-10-24 10:08:00 +02:00
Maurice 92be8a7ca5 fix(studio): lint and test fixes: zoom bar labels without the studio object, tile zooms in a helper, tests without non-null assertions or the window toast 2026-10-24 10:07:59 +02:00
Maurice 5b4030f86b fix(studio): the full page notice names no number, so it needs no plural forms 2026-10-24 10:07:59 +02:00
Maurice e2c00ba18b feat(studio): a full page says so instead of swallowing the click 2026-10-24 10:07:59 +02:00
Maurice 0a9075af73 test(studio): the head band 2026-10-24 10:07:58 +02:00
Maurice c3a5383f5e feat(studio): the head band in the dialogs' shape, tools grouped by what they do, book view beside the zoom 2026-10-24 10:07:58 +02:00
Maurice 5e36e38b72 fix(offline): the vector prefetch takes the vector source and each source's own zooms; driving settings sync only with the add-on on 2026-10-24 10:07:58 +02:00
Maurice 658536c217 fix(trips): a member another member removed cannot rejoin through the invite link
Removing a member deleted their membership row only, and the invite link
checked nothing but its own token, so whoever kept the link walked straight
back in (GHSA-wr4c-964p-39jg).

trip_member_removals now notes who another member took off a trip. The invite
link refuses them on preview and on accept with a 403 that says so, old link
or regenerated, and the join page shows that instead of the join button.
Adding them back by name, or through a trip-bound invite or a plugin acting
for a member manager, lifts the note. Leaving a trip yourself leaves none, so
the link keeps working for whoever left and for everybody else.
2026-10-24 08:29:51 +02:00
Maurice 00018959c6 fix(studio): a full page takes no new element, the opacity slider commits a move only, a theme draft survives saves
Every add in the Studio (a sticker, a shape, an icon, a text, a frame, a line,
a travel element, a photo from the content panel or a drop), a text style and
a grid of frames appended without looking at the page's cap of 90 elements,
which paste and duplicate already kept. The save then failed with a 400 and
every later save of the book failed the same way. Each of them now leaves a
full page as it is and selects nothing, as a paste does.

The opacity slider committed on every key let go on it, so the Tab that moved
the focus there wrote the value it was last moved to, an empty undo step at
best and another colour's opacity at worst. It commits once after it moved,
on the key or the pointer let go or when the focus leaves.

The Theme panel threw away colours, faces and motifs being tried whenever the
book came back from a save by another editor or the assistant, because the
same theme read anew is a new object. The draft now follows the book's theme
only when the theme itself changed.
2026-10-24 04:19:25 +00:00
Maurice 117af4a8a7 fix(studio): the sheet's keys leave a key to the control that took it, and the layers tree works by keyboard
The sheet listened on the window in the capture phase, before any control saw
a key. Delete on a focused gradient stop removed the whole shape, an arrow on
the angle dial or the radial centre also moved the shape, and Delete, the
arrows and Ctrl+V pressed on a button of the assistant's window acted on the
page although the window stops its keys. The sheet now listens on the
document as the key bubbles, after every control had it and still before the
page's Escape on the window, and leaves a key whose default was prevented. A
gradient stop takes Delete and Backspace even when the last two stops cannot
go.

The layers panel was a tree a keyboard could not walk: only its toggles could
be focused. The tree is now one stop in the Tab order, the row last focused or
else the selected one. Up and Down move along the rows, Home and End to the
ends, Right opens a group or steps into it and Left closes it or steps from a
member up to its group (mirrored right to left), Enter or Space selects a row
as a click does with Shift adding, and F2 renames it. Enter and Escape in the
name field hand the focus back to its row, and the row in focus is ringed. A
hidden or locked layer that cannot be clicked on the page is reached this way.
2026-10-24 04:06:37 +00:00
Maurice 84e18e4954 fix(studio): paste style, the page background, layouts and fill page keep the engine's rules
Paste style wrote the copied fields straight onto the element, although a
pasted look is meant to be the style operation the assistant sends. It now
runs the engine's own restyle (bookElementStyled): a colour or face pasted by
hand takes the element off the theme, so the next theme applied no longer
brings the old colour back; a plain fill replaces the paint of the shape it
lands on instead of staying hidden under it; and a line takes another line's
look without its points, which are its course, not its look.

A background picked by hand in the inspector kept the page's link to the
theme, so the next theme applied set the page back to the theme's colour. The
picker and the background operation now paint through one helper that takes
the link away (withSpreadPaintByHand). Giving one page's background to every
page carries that page's link along, or takes the others' away when it was
painted by hand.

A built-in layout, a book's own layout and laying a page out again from its
entry ignored locks in the Studio: a locked shape was dropped and a locked
photo poured into a slot unlocked, while the assistant's layout operation left
both where they were. All four now lay a page out around its locked elements
through one function (layoutAroundLocks), which the engine's layout operation
uses too.

Fill page and fill spread kept the photo in its group, so the background
picture was selected and dragged with its caption and listed under the group
at the front. It leaves its group as the engine's fill does, and a group left
with one member goes.
2026-10-24 04:06:27 +00:00
Maurice bdf5767a5f feat(studio): rebuild both side panels around one head, one row and one order
The rail lists its sections in the order a book is made: Pages, Content,
Layouts, Elements and Travel, then Theme and Layers set apart below a rule.
Stickers are a tab of Elements beside the icons instead of a rail section of
their own, and Elements has six tabs (text, shapes, lines, frames with the
grids, icons, stickers). The quotation mark moved to the text styles, the
outline rectangle to the basic shapes and the plain rule to the lines. The rail
and every tab row are tab lists the arrow keys walk through, and a long name
wraps instead of being cut. The icon and sticker searches say in the field how
many match, which the sticker library's own head used to.

Every panel on both sides opens on the same head, and every labelled control
uses one row that moves the control under its label when the two do not fit,
so no label sits in a fixed column any more. Number fields, chips, sliders,
tab labels, theme names and travel cards wrap the same way, a country beside
a stop wraps under itself, and an upload cell holds its words to two lines
with the whole label in its tooltip. The heads, shelves and groups are real
headings, so a screen reader can walk the panels by them.

The inspector shows every kind in one order: what the element is and says,
its position and size, its look, its effects, then Arrange. Align and the
stacking buttons are one Arrange group with a button that opens the page in
Layers; its rows sit under their labels, each in two sets that move to a
second line whole. Rarely used groups start folded and open on an element
that already uses them (a turned element, a map held at a zoom, a summary set
in another face), and every group mounts afresh for the next selection. A
sticker's duplicate angle and opacity are gone in favour of the shared
position group, which now has the turn buttons for every kind. With several
elements selected it keeps their angle, opacity and turn, and the mirror when
all of them are stickers, and leaves the frame's numbers to one element. A
photo's fill page and fill spread sit under its crop. With nothing selected
the inspector shows the page background, the book's theme with the way to the
Theme panel, and the page numbers.

Seventeen translation keys nothing has used since before the rebuild (the old
inspector title, the empty spread note, the summary and country list names,
the roads buttons and others) are gone from every language. The broad key
template the old panels used had counted them as reached; the format names,
the empty photo grid messages and the map source hints are now named where the
key check can read them.

Also fixed on the way: the travel stops list shared its class with the
gradient stops and was laid out as sixteen pixel handles; the alignment
buttons were named in raw English; the map's print resolution note joined its
two halves with a dash.
2026-10-24 03:08:27 +00:00
Maurice e8b071aecd fix(tours): restoring a recorded track and saving a copy wait for the tour's queued edits
Both go straight to the server. While an edit of the same tour still waited in
the queue, the restore went out first and its answer replaced the cached edit,
and the edit replayed afterwards planned the track over again. A copy copied
the server's older line instead of the one on screen. Both now wait the way the
actual track writes do: offline, behind a queued write of the tour, or for a
tour the server has not got yet they refuse with OnlineOnlyError, and the
planner says a connection is needed and the waiting changes go first, in all
27 languages.
2026-10-24 02:18:08 +00:00
Maurice 508e17bc11 fix(assistant): the phone chat holds the focus as a dialog, and its lists close on Escape
The full screen chat is a modal dialog but left the focus on the trip behind
it. It now takes the focus when shown, keeps Tab inside and hands the focus
back when set aside or closed, through the helper MSheet now shares. The
dropdown panels take the focus onto their first entry, close on Escape and
give the focus back to their button; the history and menu buttons say
whether their panel is open, and the open chat is announced as current.
2026-10-24 02:06:24 +00:00
Maurice 4d00858b8a fix(assistant): the window's menu and trip list keep the keyboard in reach
The home chat's trip list opened before its trips had loaded, so the focus
stayed on its button and no trip could be reached by keyboard; the first trip
now takes the focus once the list is there. The header's menu says whether it
is open, and closed by Escape or a pick it hands the focus back to its
button, so the next Escape closes the window again. The open chat in the
history list is announced as the current one.
2026-10-24 02:06:24 +00:00
Maurice 5651c11803 feat(assistant): the book designer works from a brief, with archetype covers, lively spreads and stickers
- design_book takes a brief (energy, decoration, collages, theme), a cover
  archetype and a cover lockup, and pages.overrides that give single pages of
  the plan another beat or layout. Directives written before parse as they
  did, and a design asked for none of it is composed exactly as before.
- The engine composes the seven cover archetypes from the book's own photos,
  words, theme faces and colours, lockups, shapes and stickers, varied by the
  seed: spine band, poster pop, cut-out, illustrated postcard, grid and
  badge, minimal serif and stamp collage. A title the directives give a
  display tier is held to it, and the notes say when a band, a badge or a
  stamp holds it smaller or a cover leaves a layout out.
- A lively or loud book turns two in five hero and grid spreads into
  collages, script overlays, badge grids, stamp rows or two-tone splits, the
  first of them always, turns and frames the prints of its other pages, sets
  its cover title larger and takes one or two, or three to six, stickers of
  its theme's motifs a spread, never over words, a photo's detail or the
  fold. A calm book asked for collages gets them and nothing else.
- Every turn the engine gives a print or a sticker stays within what the
  brief's energy takes, a calm book's within its theme's own, so a design is
  never judged against its own brief.
- New checks name a flat cover, a page without a lead, colours or faces off
  the theme and, for a design made with a brief, a book livelier or calmer
  than it asked, on the pages the design made and on a page revised in the
  draft. Page edits answer with the art checks too, and the assistant's
  cards name them in every language.
- list_book_assets lists the shapes, faces, lockups, themes and patterns
  beside the stickers, and the Studio's shape groups and photo frames are one
  list the assistant reads too.
- The Studio prompt gains an index of themes, archetypes and faces and JSON
  recipes of the elements to add and style for each cover and three lively
  spreads, and a turn that designs the book may preview sixteen pages, still
  three images a request; a viewer is told of none of it.
2026-10-24 01:14:03 +00:00
Maurice ff749611c6 feat(studio): the Templates panel offers the decorated templates with a style filter
The Templates section of the rail now opens on the decorated templates of
the page's kind, covers two to a row and spreads at full width, each card
the page renderer drawing the page the click will lay: this page's photos
and words in it, in the book theme, a cover in the journey's title and
subtitle as the assistant's layout sets it. A row of style chips narrows
the set to one archetype. A click is one undo step on the page as it is
then, refused for the other kind of page, and opens the photos when frames
are left empty. The book's own layouts and the built-in wireframes follow
below, and the help guide and the wiki describe the panel as it now is.

The panel moved out of StudioSidebar into its own file; the sidebar keeps the
rail, and its two physical sides went with the code, so the rtl baseline
entry goes too. The Travel panel and a template's map build the journey
they draw with one helper.
2026-10-24 00:36:00 +00:00
Maurice 49f7a447d3 feat(studio): decorated templates, 21 covers and 16 spreads laid on any page in the book theme
A decorated template is a whole designed page kept as data: full document
elements in fractions of the page they were drawn on, with roles for the
photos and words a page brings, links to the theme for its colours and
faces, groups for its lockups (a title with its date line, a badge with its
words, a stamp with its postmark) and an archetype with tags. Seven cover
archetypes in three variants each and sixteen double spreads ship in
shared/src/book/templates/data.

Laying a page out on one pours its photos into the photo roles in order and
its words into the title, subtitle, date, story and caption roles, takes
the words it has none for from the book or the journal entry, sets the
template in the book theme, scales it to the page format with its bleeds
on the bleed of that page, and parks what has no room, a date line the date
mark was not made of included. A text set on a colour is made to read there
at the size it was fitted to, on a band of ink or paper when neither reads.
A mark set as text, such as a large quotation mark, is design to every
layout and never taken for the words of a page.

A fitted text keeps the size it was drawn at as its ceiling, so a shorter
title grows back, and every fitted text is now solved with eight percent of
headroom on letter width: set in the browser, the bold condensed faces and
several scripts run that much wider than the letter measure, and a fit at
exactly the measure wrapped its last word out of the frame.

The layout operation of edit_book_page and revise_book_design takes the new
ids as a checked string and keeps the name of a locked group,
list_book_layouts lists them with archetype, tags and roles, and the design
prompt names them. A sibling extract script reads a page drawn in the
Studio back into the format, roles, tints and groups kept.
2026-10-24 00:36:00 +00:00
Maurice a202f2dc95 fix: the four reliability findings Sonar reports on dev
- The warmed fonts' key sorts by code units, so the same faces give the same
  key in every locale.
- The nearest weight of a snapshot face starts from the first face it has.
- The round hike search names its candidates with their place in the list
  explicitly instead of handing map a function of two arguments.
2026-10-23 22:40:27 +00:00
Maurice 6395ef655f style(studio): the photo view and the findings in Prettier's form 2026-10-23 22:08:13 +00:00
Maurice cbf9325e7e fix(studio): the book tools state every field once, and the server typechecks within its memory again
- The element, spread, document, page operation and card unions carry a
  name of their own, so the declarations of every schema that holds them
  refer to them instead of spelling them out again. The shared declarations
  shrink from 9 to 5.5 MB and the server's typecheck from 4.4 to 2.9 GB, so
  the build fits the image's 4 GB again.
- edit_book_page and revise_book_design take add by what the element is,
  with an id of its own; its look follows with style by that id in the same
  call, every look field described once. A change an assistant card kept
  with its look on add still reads and runs.
- restore_book_page states what every element has once, then each kind's
  own fields and the type the five travel kinds share, without defaults; the
  page is read as a spread again before it goes back.
- The theme links are explained once in the page edit's description, and
  style points a text's face, a shape's paint and outline and a photo's crop
  look at their one full description.
- The lockup roles live in a module of their own, so the operation schemas
  no longer import the lockup engine, whose cycle left the operations unset
  in the shared tests.
- The theme switches no longer fall through a comment, the newer document
  test follows the current revision, the line inspector names its stroke
  keys, a text's anchor reads no physical side, two shapes record the
  proportions they are drawn at, and the photo look and line tests follow
  the slider and the folded ornaments.
2026-10-23 22:08:13 +00:00