Commit Graph

698 Commits

Author SHA1 Message Date
Maurice 48ff1b3a98 feat(assistant): curated cards and undo for the changes of a journal itself
Starting a journal, changing its settings, linking or unlinking a trip,
bringing back its suggestions, the user's own view of it and deleting it
fell back to the generic card, which names ids and offers no way back.
They now share a journeyHeader card: the journal with its trips, the one
the change links or unlinks marked, what a new journal brings in and what
a deletion or an unlink takes, and each setting old to new in the
journal's own words. A new journal is deleted again while nothing was
written, added or laid out in it, changed settings are written back from
what the tool answered, a linked trip is unlinked by its owner while none
of its suggestions was written up, and the own switch flips back.
2026-10-24 22:54:44 +02:00
Maurice cf35dc7afd feat(journey): update_journey takes every setting REST does and answers what it replaced
The MCP tool lacked show_trip_tracks and cover_gradient, which PATCH
/api/journeys/:id has always taken. Both now read the input through one
helper, and the tool goes through a small settings service that writes the
same patch in a transaction with the stored values it replaces, answered
as previous, so a change can be written back. The subtitle and the cover
gradient take null to clear them. The tool's inline zod moves into strict
schemas in @trek/shared; the REST route and its body are unchanged.
2026-10-24 22:54:43 +02:00
Maurice 4b3340546f feat(assistant): the journey page opens the journal's chat on desktop and phone
On /journey/:id the assistant window and the phone's assistant screen now
open the journey's conversation, the one TREK Studio holds too, instead of
the home chat; the Studio route keeps its own column. A turn sent from a
chat the Studio does not host names the journal page, a hosted one the
Studio, so the server offers the right tools. A journal card from the home
chat opens that conversation in place on the desktop and the journal page
on the phone, and the empty chat asks about the journal rather than the
book.
2026-10-24 22:54:43 +02:00
Maurice 1d9648267b feat(assistant): the home chat starts a journal and hands a journal's questions to its page
Asked on /journey to create "Japan 2026", the home chat had nothing to
offer: it keeps no write that names a trip or a journey. It now keeps
create_journey, whose trips the tool checks one by one, and delete_journey,
which the journey's own chat leaves out because the conversation goes
with it. For anything inside a journal it offers open_journey_chat, the
twin of open_trip_chat: the journal is read from the user's own journals
and shown as a card whose button goes on in the journal's chat with the
question waiting there. The trip and journal cards share their question
and button.
2026-10-24 22:54:43 +02:00
Maurice 2508fd8624 feat(assistant): a journey's chat request names the page it is asked from
The journey's assistant lives in TREK Studio today, and the journal page is
about to get one of its own over the same threads. The chat and decision
bodies take an optional surface, studio or journal, and the journey scope
carries it to the service; left out it reads as the Studio, so today's
client is unchanged. The scope key ignores it, so both pages keep one
thread list per journey.
2026-10-24 22:54:42 +02:00
Maurice 89c33ac3f4 feat(assistant): an attached file can be kept in Files, on its own or with a booking or an expense
The chips offered to keep an attached file in Files, but nothing could do it:
the assistant's upload_trip_file stays denied, and the file never reached
Files. A new server write, keep_attached_file, is offered to the model where
the thread holds an attachment and held as a change card naming the file and
the booking, expense or place it goes with.

Applied, it runs the checks of a Files upload with the user's rights (the
demo block, the trip, file_upload and file_edit for a link, the instance's
file types, every linked id on the same trip), copies the bytes to a trip
file of their own, and writes the trip file, its expense link and the
attachment's pointer to it in one transaction; the members' planners get
file:created after it. A second keep of the same attachment answers the file
kept the first time. FilesService gains storeBytes and discardBytes so the
storage write stays out of that transaction.

The receipt opens the Files tab; the card's verb, its "Attached to" row and
the receipt's open label are new keys in all 27 locales. Undo is not offered:
no tool takes a trip file back yet.
2026-10-24 22:32:48 +02:00
Maurice aeda658f18 feat(assistant): the model reads an attached file once the user agrees
The assistant could not read a file the user attached: the bytes were gone
after the request, the thread only held the file's name, and read_trip_file
stays denied because it would send any document of the trip to the provider.

A new server tool, read_attached_file, reads only the files attached in this
conversation by this user; any other id is answered "No such attachment in
this conversation.", whoever it belongs to. It is offered in a trip turn whose
thread holds a file with text. The first read of a file is held as a change
card that names the file and the model and host its text would go to; once
the user agrees, the agreement is kept on the attachment and later reads run
at once. The text reaches the model through the history and, for a later
read, as a tool answer only the model gets (AgentToolRun.modelText): no message
part, stream chunk, shared answer or client store ever carries it.

The model is told each kept file's attachment id, and the standing
instructions say to read the file when the user wants to work with it, to
propose a booking found in it through create_reservation and then to offer
keeping the file with it. The card's verb, its "Sent to" row and the step's
name are new keys in all 27 locales.
2026-10-24 22:32:47 +02:00
Maurice 2f3a0219cd feat(assistant): every attached booking file gets an answer with what to do next
A booking file without a booking ended the answer on the error "No booking
found in this file." with no action, and the user was left to type. Now the
server answers every booking file itself, without a model: one line that
names the file and what TREK found in it, or that it found nothing, why, and
asks what to do with the file. Under it come up to three chips, picked from
what the user may do on the trip and what the file allows: keep it in Files,
make a booking from its text, attach it to a booking or an expense, ask what
is in it, or keep it with the booking just found. A chip sends its words as
an ordinary chat message.

The line and the chips are written in the language of the request from new
assistant.attach.* keys in all 27 locales, through a small helper the sports
proposals now share. The empty answer finishes as stop; no_bookings_found
stays in the contract for the threads older builds wrote. Route files keep
their answer as it was.
2026-10-24 22:32:47 +02:00
Maurice 6a77496438 feat(assistant): an attached file stays with its conversation
A file attached in the trip chat lived only as a buffer for the one request
that read it, so the assistant could not look at it again and nothing could
keep it in Files. Now its bytes go to storage before the turn writes anything
(under the trip files' category, which is never served by path) and a row in
the new assistant_attachments table keeps its name, type, size, hash and the
text TREK read out of it, written in the turn's opening transaction. The
message's attachment part carries the row's id; old messages without one still
read.

The text is read the way the AI import reads it, through a new public
LlmParseService.readText, and a file whose text cannot be read is kept all the
same. A storage that refuses the bytes refuses the turn before any row exists.
Deleting a thread takes its files along, and the nightly retention sweep drops
files older than seven days and bytes no row names any more.
2026-10-24 22:32:47 +02:00
Maurice cb34c46226 fix(studio): CI on the templated auto layout
The rhythm test holds the picker to what it does now: it gives the rhythm up
only where no template of the book's styles frames every photo and keeps it.
A design applied over a stored book keeps that book's theme, as the merge has
always done, so the end to end test checks the pages instead. The MCP test
builds its request through the shared schema, a travel mark's frame is read
with its sides spelled out for the client's looser types, and the client's
react-hooks/refs baseline drops to the 555 it holds now.
2026-10-24 20:54:16 +02:00
Maurice e777118272 feat(studio): auto layout lists bare stops on a words-only template of the book's style
Stops nobody wrote about or photographed were set as a small list on a plain
spread, the old composed page. They now take a words-only template of the
book's styles: the list's label as its title, the stops as its story grouped
by day, as many as its story frame holds, and the day in the template's date
where all of them share one. The words go to their roles by name, since a
short list that opens on a date would otherwise read as a date line. The
composed list stays as the fallback where no template takes it.
2026-10-24 20:28:37 +02:00
Maurice 3f2da7a867 test(studio): repin the templated parity digests on top of the design figure and riso cover fixes 2026-10-24 20:14:06 +02:00
Maurice 9c3649f011 fix(studio): auto layout keeps every page in the book's own styles and every photo in a frame
The picker scored all 108 templates at once, so a page whose photos the own
pool could not frame borrowed a template of another style (a night film page
in a poster pop book). It now goes in tiers: the theme's archetype and its kin
with a frame for every photo, then the same with the rhythm given up for that
page, then another archetype, and only then a photo left in the tray. The
photos of a chapter are cut into the counts the own pool has, and only where
those leave a photo over into counts another archetype has, at a price. Riso
joins poster pop's kin for its one photo story page.

Across the 17 themes and the nine fixture journeys no photo waits in the tray,
no page is laid in another style and no page has a severe finding.
2026-10-24 20:13:44 +02:00
Maurice 73fdbdc0c3 feat(studio): Auto layout lays the book on the designed pages
"The whole book" now lays the book on the designed templates through
autoDesignedBook, in the book's own page format and theme (a recoloured
one of its own included), its title kept and every page holding a locked
element kept; each press takes a new seed, so a second press gives another
book, one undo away as before. "This spread" lays the page on another
design than the one on screen and its neighbours, its id kept, and now
works on the cover, the summary and the countries too, so the menu offers
it wherever the auto layout knows the page. Loose gallery photos reach the
layout with the day they were taken, which it shares them out by. The
menu's two hints say what the button now does, in every language. Nothing
here places the classic summary, countries or marks any more.
2026-10-24 20:13:44 +02:00
Maurice 0879b5aecc feat(shared): the Studio's auto layout entry points
auto/auto-designed.ts holds what the Studio's Auto layout menu calls.
autoDesignedBook lays the whole book on the designed templates in the
book's own theme object (a recoloured one of its own included, the calm
fabric-classic theme for a book without one), over the stored book, its
page format kept and every page holding a locked element kept; another
seed lays another book. autoRelayoutSpread lays one page again around its
locks, its id kept: an entry's page on the best template other than the
one on screen and its neighbours', avoiding one that would cut its story
where it can; the cover on the next cover template of its archetype and
then of its kin; the summary and the countries in their next look, an old
classic summary included. Pages the engine did not make are left alone,
as before. autoRelayoutKind says which pages those are.

designBook's templated path is split so the relayout reads the same
setting (templatedSetting) as the whole book, and the page layer is
shared (layEntryPage); the parity digests are unchanged by it. buildBook
and relayoutSpread stay exported and unchanged.
2026-10-24 20:13:44 +02:00
Maurice 9729b0b575 feat(server): design_book offers the designed templates
The design_book tool says in one sentence that layouts: 'templates' lays
every page on the Studio's designed templates in the archetype of the
book's theme, as the Studio's Auto layout does, and that each plan row then
names its template; style classic alone stays the old built-in Auto
layout. The field comes from the directives contract in @trek/shared, so
the tool's schema takes it without a zod line of its own, and the answer's
plan row gains an optional template. The REST draft routes take no
directives, so nothing changes there. Without the field the answer is the
same as before, no row naming a template.
2026-10-24 20:13:43 +02:00
Maurice 35acdb8ba1 feat(shared): design_book can lay the book on the designed templates
A new optional directive, layouts: 'templates', lays every entry on the
decorated spreads of the book theme's archetype and its kin
(design-templated.ts). An entry's photos are cut into page-sized parts that
leave no frame empty, at most twelve of them, the first part carrying its
story; each part takes the template that suits it best, poured from a page
of the entry's photos and story so the title, place, date and story stay
bound to the journal. A story longer than its frame is cut at a sentence
and goes on over a page of words. Date marks are set as stamps, never in
the classic styles. Loose gallery photos go to the entry they are linked
to, then to the entry of their day, then to the entry with the fewest
(shareGalleryByDay, beside distributeGallery, which stays as it is); what
no entry has room for closes the book on up to three pages of more
moments, and anything past that is said to be left out, so no photo is
dropped without a word.

The rest is the composer's: scope, the photo picker, the page budget, the
stored pages kept, repair and findings. A book can bring its own theme
object (BookDesignInput.theme), recoloured or not, and it is kept whole.
Plan rows name the template a page was laid on. Without the directive
every design is composed exactly as before, and classic is still buildBook.

AUTODSN-001..015 cover the rules, and AUTODSN-020 pins a digest of every
page on the auto layout's parity journeys and a fourth one in three themes.
design-templated.parity.json was computed with the spec's own canonical form
and digest over these inputs, run through tsx; CI checks it from here on.
2026-10-24 20:13:43 +02:00
Maurice a19fdf6161 feat(shared): framing pages from the new travel looks
design-templated-framing.ts builds the pages around the chapters of a book
laid on the designed templates. The cover is laid on one of the theme
archetype's cover templates, poured from a page whose title and subtitle
are bound to the journey, so the binding survives; an archetype with no
cover for the photos there are has its cover composed as before. The
journey at a glance is its map with a photo at every stop beside the
figures as a poster (tiles for the collage and grid books, a sign for the
postcard ones), a ticket stub of how far and how long, and the furthest
point on an odometer. The countries are one country's map cut to its shape
beside its stamp, a card each for up to twelve, one panel of stamps past
that. The back cover adds a band of days, places and photos and a row of
country stamps. A page of words, where no template takes a story, sets it
beside the stop's map, its day as a stamp and its country as a tag. None of
these sets a summary, a country or a mark in the classic look.
2026-10-24 20:13:43 +02:00
Maurice 813dd7a7eb feat(shared): pick a decorated spread for a page's photos and words
design-template-pick.ts says which decorated template a page of the auto
layout is laid on. Every built-in theme belongs to an archetype
(THEME_ARCHETYPE, the five new themes to their own five), and a book picks
from that archetype's spreads and from those of the archetypes that sit
well beside it (ARCHETYPE_KIN). A template that would leave a photo frame
empty, lose the story, draw a map with nothing to draw, repeat the page
before or follow a busy page loudly is never a candidate; of the rest the
best fit wins: the photos all used, the theme's own archetype, the story
fitting its frame (bodyCapacity measures each frame once per format and
face), the first frame the shape of the first photo, not used a few pages
back, and calm where the book should breathe. Equal ones are chosen by the
design's seed. chunkPhotos cuts an entry's photos into page-sized parts
that leave no frame empty, and pickCoverTemplate does the same for the
cover.
2026-10-24 20:13:43 +02:00
Maurice d51b9de2b0 feat(shared): a laid page knows which decorated template it is
matchDecoratedTemplate reads a page's elements by kind and frame, rounded
to the millimetre, and compares them with every template laid on the same
page format: a template is the page's when nearly all of its design is
there and it explains most of the page, and of those the one explaining the
most wins. A page rearranged by hand reads as none. The auto layout's
"this spread" uses it to offer a template other than the one on screen.
2026-10-24 20:13:43 +02:00
Maurice 6254510e0f refactor(shared): the travel looks are built in shared
The factories behind the Travel panel's cards (a summary as a poster, a
ticket or a sign, a figure on a medal or an odometer, a map of the journey
or of one country, a mark as a stamp or a tag, a country as a stamp, a visa
or a postcard, each dressed in the book's theme) move to
book/travel/book-travel-looks.ts, so the auto layout can build its framing
pages from the same looks. Where an element lands stays the caller's: the
panel still centres it on the spread on screen, through the same wrapper and
the same API, and a designed page names its frame. A mark can now also take
an entry's value rather than the journey's.
2026-10-24 20:13:43 +02:00
Maurice c525b2f84c fix(studio): the riso cover's year band deepens a mid-tone ink so the year reads
In a theme whose second ink is a mid tone (riviera's olive), neither white nor
near black reached 4.5:1 on the year's band. The band is taken towards the dark
until the year reads, as the other covers do for small words.
2026-10-24 20:13:42 +02:00
Maurice b3d30a834e test(studio): pin which texts count as a template's figures 2026-10-24 20:13:42 +02:00
Maurice 589d3354eb fix(studio): a template's figures stay its design, never the next template's date line
Figures a template draws as design, a film's timecode or a frame number, came
back as the page's words when another template was laid on the page, and took
its date line. Texts with no letter that are not a date and are bound to
nothing are design now, and the new templates spell their plate numbers and
REC marks so they read as such.
2026-10-24 20:13:41 +02:00
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 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 8dacd0a50c fix(book): the auto layout's drawn templates no longer carry photos of the book they were drawn in
Three photo frames in the templates kept the photo ids of the journey the
templates were read out of (68 and 69). Only empty frames take an entry's
photos, so every book laid out on those templates pointed at those ids: a
broken picture on most installs, and on one where the id exists, someone
else's photo or an unrelated one of the user's own. The frames are empty
now and take the entry's photos like the others. The parity digests of the
five spreads that use them are written anew, as the spec asks for a
deliberate layout change.
2026-10-24 16:59:53 +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 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 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 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 d0f74c9f02 feat(studio): add_book_pages, set_book_cover and design_book's cover take the decorated templates too 2026-10-24 11:07:16 +02:00
Maurice f14f1e41b9 fix(studio): bold text measured at each family's own bold width, so a bold condensed heading no longer overruns its frame 2026-10-24 11:07:16 +02:00
Maurice 9138e722bb feat(studio): twelve new stickers: Parthenon, Milan Cathedral, canal houses, gondola, Lisbon tram, Celtic harp, tiger, monkey, camel and three doodles 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 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 1050029842 fix(studio): a saved layout's background unlinks the page from its theme colour 2026-10-24 10:07:58 +02:00
Maurice 64edf899ac fix(studio): stickers without gaps: the ramen bowl overlaps its broth, the croissant is one closed crescent, the nata's ribs stay in their cup 2026-10-24 10:07:58 +02:00
Maurice 890473ebd5 style(i18n): format the translated locale files 2026-10-24 09:41:34 +02:00
Maurice 2b86d1fda7 fix(i18n): translate the English left in the other 26 locales
About 2900 strings still carried the `// en-fallback` placeholder and some
3100 more were unmarked English copies, most of them from the Studio, the
assistant, OAuth and the date picker. Every one of them is translated now;
where the English word is the locale's own one (German "Status", "Backup"),
it is kept and marked `// same-as-en`. Placeholders, markup and product names
are unchanged.

"Studio", the photo book editor's name, joins Atlas and Vacay on the
untranslated check's list of names. The baseline drops from 2900 marked and
3100 identical strings to 1 and 158.
2026-10-24 09:41:33 +02:00
Maurice fc27b254bb style(i18n): format the German trip strings 2026-10-24 08:38:12 +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 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 090e754077 fix(studio): a restore brings in no photo from outside the journey's gallery, letter fills counted
restore_book_layout took any layout the caller sent, so a layout naming a
photo of another journey was kept, and laying a page out on it put that photo
into this book while place_photo refused the same id. The layout is now held
to the rule a page restore states: every photo it names, in a frame, on a map
marker or in the letters of a text, is in the gallery or on a page of the book
already, or the call is refused with photo_not_in_gallery.

restore_book_page and the design apply read the photos of a page in one place
now (book-photo-refs.ts), which counts the photo a text is filled with. A page
put back with letters filled with a photo from outside the gallery is refused
as a frame of it would be, and a designed page whose letter fill photo left
the gallery since is skipped as photo_gone; on a new book's cover the letters
keep their colour instead, as its frame is emptied.

A saved layout keeps no photo of the page it was taken from in its letters, as
it keeps none in its frames, so laying another page out on it no longer
carries that photo along. A layout kept before this fills such letters with
the first photo of the page it is laid on, or leaves them in their colour.

The style operation checks a letter fill photo only when the change sets the
fill, so a title whose photo left the gallery can still be resized or
recoloured, as the text operation already allowed.
2026-10-24 04:05:59 +00:00
Maurice 4322159d8e fix(i18n): the Studio rail and its tabs in every language, and the rail in the help
The names on the rail and in the tab rows the rebuild puts first (Pages,
Content, Layouts, Elements, Shapes, Text, Photos, Entries) were still English
placeholders in twenty one languages. They carry each language's own word now,
and so does the quotation mark, which the Text tab shows as a word under its
tile instead of only in a tooltip. The Frames tab's name was already translated
in those languages and loses the placeholder mark it still carried.
The help on Studio and the wiki describe the rail as it is: seven sections,
Theme and Layers set apart, the stickers under Elements, and the inspector's
order.
2026-10-24 03:08:27 +00:00