Commit Graph

1208 Commits

Author SHA1 Message Date
Maurice e86cb6a897 refactor(bookings): let the phone plugin slots use the reservation detail plugin hook
ReservationPluginSlots in tabChrome repeated the plugin store selector
that useReservationDetailPlugins already holds for the desktop panels.
It now calls the hook, which gets its own test.
2026-10-09 16:15:49 +02:00
Maurice c8d8ddfd3e refactor(packing): share the template row of the two apply template menus
ApplyTemplateButton and the packing list header drew the same template
row in their menus. PackingTemplateOption now draws it; the header's
faded hover stays a parameter (fade).
2026-10-09 16:15:49 +02:00
Maurice 2a05e6d20d refactor(files): share the preview dialog frame between the PDF and Markdown previews
Both previews built the same dialog head band with the file name, the
open in tab pill and the download pill. FilePreviewDialog now draws it;
the dialog width, the body class and the icon colour stay parameters,
and each preview keeps its own body.
2026-10-09 16:15:49 +02:00
Maurice 71b7b209dc refactor(studio): one great circle distance for the map bows and the road fetch
TravelElements ramped how far a leg bows by a local km helper and
roadRoute refused long legs by a second copy of it. Both now call legKm
from legKm.ts, the same formula with the same clamp.
2026-10-09 16:15:49 +02:00
Maurice e6930e00ac refactor(studio): share the typeface buttons and the weight line between the inspectors
The text inspector and the travel inspector each drew the same row of
typeface buttons and the same weight choice. Both now render FontButtons
and WeightLine from StudioTypeControls.tsx. The travel inspector keeps
casting its patches to Partial<BookElement>, so each side writes exactly
the fields it wrote before.
2026-10-09 16:15:49 +02:00
Maurice d08c949b14 refactor(time-picker): draw the hour, minute and AM/PM columns with one spinner column
The three columns of the time picker each repeated the same chevron up,
value box and chevron down markup. TimeSpinnerColumn draws one, and the
button style it shares with the clear button moves to timeSpinnerStyle.

The AM/PM column keeps its narrower box, smaller type and leading gap as
props, and the hour and minute boxes keep their tabular digits.
2026-10-09 16:15:48 +02:00
Maurice c1a9e98ec4 refactor(planner): share the cross-day move and end-of-day drop between the day body and the end zone
The day body and the drop zone at the end of the list both carried their
own copy of two steps: moving a stop or note dragged in from another day,
and putting a same-day row after the day's last row. Both now live in the
plan hook as moveInFromOtherDay and dropAfterLastItem.

The differences stay where they were: only the end zone passes a
reservation id, so only it moves a booking to the end, and only it clears
the drag state after the move, which it still skips on an empty day.
2026-10-09 16:15:48 +02:00
Maurice 188d867aee refactor(planner): stop echoing the day plan's props back through its hook
useDayPlanSidebar returned about 145 names, and DayPlanSidebar destructured
the same list again, the largest copied block in the client. Most of it
was the component's own props passed straight back, plus values nothing
read any more.

The optional props' fallbacks move into withDayPlanDefaults, which the
hook and the view both read the props through, so they are written once.
The hook now returns only what it computes. State that only the view
reads (the context menu, the permission flags, the hover and expansion
states, the pending note deletion) is declared in the view, and the day
note handlers come back as one notes object. The values no one read are
gone, which also drops their unused variable warnings.

No behaviour changes: every value keeps its source and its fallback.
2026-10-09 16:15:48 +02:00
Maurice eb271f0d45 refactor(planner): share the suggestion dropdown between the airport, location and address fields
AirportSelect, LocationSelect and AddressInput each carried their own copy
of the open state, the keyboard highlight, the outside click that closes the
list, the floating list with its loading line and the suggestion row.

useSuggestionDropdown now holds the open state, the highlight, the outside
click and the arrow, Enter and Escape handling. SuggestionDropdown.tsx holds
the boxed input with its icon and clear button (airport and location), the
floating list (all three), the row button and the place row content
(location and address).

What still differs between the fields stays with them or is a parameter:
the icon, the placeholder, what typing does (LocationSelect also resets the
highlight), the rows the keys walk (LocationSelect walks the trip's places
below three characters), whether the loading line may show (not while
LocationSelect offers the trip's places) and how a row lines up its content
(centred for airports). Each field keeps its own query, search and pick.
2026-10-09 16:15:48 +02:00
Maurice 03cb9fa439 refactor(map): share the marker thumbnail loading between the Leaflet and GL maps
MapView and MapViewGL each held the same photo loading effect: read the
cached thumbs, fetch the missing ones, listen for their arrival and batch
them into one animation frame. It now lives in useMarkerThumbs, which
also owns the thumb state and the place photos switch, and both maps
call it where the effect used to be.

The effect keeps its keys (the picture sources and the switch). It reads
the places through useEffectEvent, which drops the old
exhaustive-deps suppression in MapViewGL and the warning in MapView.
2026-10-09 16:15:48 +02:00
Maurice 69d2f80fe2 refactor(map): share the transport hop building between the Leaflet and GL maps
ReservationOverlay and reservationsMapbox each carried the booking type
list, the icon and arc table, the time zone aware duration and the loop
that turns a booking into waypoints, arcs and labels. All of that now
lives in transportHops.ts; each renderer keeps only its drawing.

The one difference stays a parameter: Leaflet asks for arcs that cross
the antimeridian to be copied 360 degrees over, the GL map does not
because it repeats features across world copies itself. Leaflet still
adds its transit segments on top of the shared hop.
2026-10-09 16:15:48 +02:00
Maurice 369697650f refactor(map): build OSRM leg connectors in one place
calculateSegments and the cached legs call turned each OSRM leg into the
same connector record line by line. That record now comes from
osrmLegSegment; the legs call keeps adding its durationText on top, so
both answers stay exactly as they were.
2026-10-09 15:26:27 +02:00
Maurice cf5b5c1245 refactor(collections): share the save to list picker logic between desktop and phone
useSaveToCollection holds the store driven picker that
SaveToCollectionModal and MSaveToCollectionSheet each carried: loading
the lists and the membership for a new target, toggling the place in or
out of a list, the per list status, marking it visited everywhere and
opening the collections page. Both views keep their own markup.

The two copies did the same thing, so no option was needed. The load
effect now lists the membership query beside the target instead of
silencing the exhaustive deps rule; the query is derived from the
target alone, so it runs exactly as before.
2026-10-09 15:20:09 +02:00
Maurice 6d2490a3ba refactor(tours): share the planned tours filter between desktop and phone
The All, Unplanned and Planned filter of the tours list was copied into the phone selection list. It now lives in filterTours next to the other tour presentation helpers, and both lists call it.
2026-10-09 15:19:51 +02:00
Maurice f84924c56a refactor(trips): share the trip loading splash beats between desktop and phone
Both splashes carried their own copy of the four beats, the step time, the still beat and the interval that cycles them. These now live in useTripSplashBeats; each splash keeps its markup and styling. The phone follows the reduced motion setting live while the splash is up, the desktop reads it on each render; that difference stays as the liveReducedMotion option.
2026-10-09 15:19:51 +02:00
Maurice 973773e003 refactor(files): share the file filter, link list, note save and trash between desktop and phone
fileListRules now holds the type category of a file, the filter tab match
and the list of places and bookings a file is linked to (own column plus
extra links, transport or booking). useFileManager and FileManagerRow on
desktop and filesModel on the phone run on it. fileActions gains the field
save with its reload and assign error, which the desktop assign dialog and
the phone note edit both use, and the trash call with its toasts, used by
the desktop delete and the phone menu sheet. The phone sheet no longer
imports filesApi.

Differences that stay, each as an explicit option:
PHONE_FILE_FILTER_RULES sorts pdf, image and doc by type category (videos
count as images, doc is every file that is no PDF and no media, a pass
with a PDF mime type is a doc) and counts a note id of 0 as collab, while
desktop reads the mime type (images only, doc is Word, Excel and text).
DESKTOP_FILE_LINK_LIST_RULES skips an own place or booking column of 0,
the phone only a null one. PHONE_FILE_UPDATE_RULES waits for the reload
after a save, so a failed reload shows the assign error there; desktop
starts it and moves on. DESKTOP_FILE_TRASH_TOAST_RULES falls back to
English when the trash toast translation is empty.
2026-10-09 15:19:51 +02:00
Maurice 88a2479627 refactor(vacay): share the settings logic between desktop and phone
The holiday countries, the calendars split by type, the weekend day toggle, dissolving a fusion, the leave year save and window label, the region options and the add check now live in useVacaySettings. The phone sheet still loads countries only while open.
2026-10-09 15:19:50 +02:00
Maurice e4179dbc11 refactor(vacay): share the calendar sharing picker and row actions between desktop and phone
The read only share reuses useVacayUserPicker for picking and sending, and useVacayShareActions holds the hide toggle and the removal with their error toasts for the sidebar card, the phone sheet and the phone chips.
2026-10-09 15:19:50 +02:00
Maurice fd7f6f3cf9 refactor(vacay): share the fusion invite picker between desktop and phone
Loading the users that can be invited, the picked user and sending the invite with its toasts now live in useVacayUserPicker. The dialog still resets and closes on success, the sheet still closes and resets on the next open and empties the list when loading fails.
2026-10-09 15:19:50 +02:00
Maurice d0709c6a37 refactor(vacay): share the calendar logging logic between desktop and phone
The log mode and its half and comp modifiers, the entry, shared and company holiday maps, the trip dots, the day click rules, the default person and the day count format lived in both the desktop calendar and the phone screen. They now live in useVacayCalendarLogic and vacayFormat; the phone keeps reloading trip dots only on a new window shape.
2026-10-09 15:19:50 +02:00
Maurice 18eeb16aa0 refactor(dashboard): share the widget logic and plugin hooks between desktop and phone
The currency converter, the world clocks, the collection lists, the plugin widgets and card badges and the card date format each existed once per dashboard. They now live in useCurrencyConverter, useDashboardTimezones, useCollectionLists, useDashboardPlugins and dashboardModel; the phone keeps aborting a pending rate request through an option.
2026-10-09 15:19:50 +02:00
Maurice 080afa9cff fix(trips): keep the trip length across a DST change when the phone moves the start
The phone sheet added the old length with a local setDate on a UTC midnight date, so in zones east of UTC a range crossing the start of summer time came out one day short. It now counts UTC calendar days like the desktop dialog.
2026-10-09 15:19:50 +02:00
Maurice e964a98138 refactor(trips): share the trip form cover picker and checks between desktop and phone
The dialog and the phone sheet each carried the cover upload, the Unsplash search, the staged cover for a new trip and the title and range checks. They now live in useTripCoverPicker and tripFormModel; the blob url release keeps each view's timing behind an option.
2026-10-09 15:19:50 +02:00
Maurice 106830609e refactor(nav): share the context aware create action between the bottom navs
The centre button resolved its target in two copies of the same hook. useCreateAction now holds it once, with the phone only branches (gallery upload, atlas search, collections) behind a flag.
2026-10-09 15:19:50 +02:00
Maurice e1219a166a refactor(toast): share the toast queue between desktop and phone
Both presenters ran their own queue behind the window toast bus. The queue, the auto dismiss and the exit delay now live in useToastQueue; each presenter keeps its markup, its exit timing and its unmount handover.
2026-10-09 15:19:49 +02:00
Maurice 7261520659 refactor(journey): share the card carousel and the gallery upload between desktop and phone
useJourneyCarouselSync keeps the map on the card nearest the centre once
scrolling settles and brings a card to the centre for a marker, a day or a
tap, for both the phone journey screen and the narrow timeline of the desktop
and public pages. useGalleryUpload normalises and uploads gallery files for the
desktop gallery and the phone screen. The phone still moves the map on a tap
of another card, the desktop gallery still counts the files up while they go.
2026-10-09 15:19:49 +02:00
Maurice 8e95b4c7b6 refactor(journey): share the entry editor logic between desktop and phone
useJourneyEntryForm holds the fields, the photo queue that only goes out on
save, the gallery links, the location search and "use my location", the
verdict rows, quick capture and the save for both the editor dialog and the
entry sheet. journeyWeatherCategory moves to components/Journey/journeyWeather
so the dialog no longer reaches into mobile/. Where the two differed they still
do: the dialog starts with a blank verdict row, counts a moved point as a
change, toasts a failed save or location and fills the weather from the
forecast; the sheet edits tags and shows a refused location under the field.
2026-10-09 15:19:49 +02:00
Maurice 78ddb1b0b8 refactor(journey): share the journey settings logic between desktop and phone
useJourneySettings holds the name, cover, archive, the switches saved on the
spot, delete, unlinking a trip and removing a contributor for both the settings
dialog and the settings sheet. useJourneyTripLinking loads the linkable trips
and links one for the add trip dialog and the sheet, and useJourneyShareLink
manages the public share link for the share section and the sheet. The dialog
still closes after a new cover or an unlinked trip, the sheet still stays open.
2026-10-09 15:19:49 +02:00
Maurice df6a8ba003 refactor(collections): share the saved place detail logic between desktop and phone
useCollectionPlaceForm reseeds the edit form when a different place opens,
fetches a cover photo for a place without one, uploads and removes the custom
cover and saves the edits for both the detail sheet and the phone sheet. The
detail keeps editing the coordinates and keeps a late photo across an update
of the same place; the sheet holds the last place through its exit and drops
a late photo once the place object changes, as before.
2026-10-09 15:19:49 +02:00
Maurice 771d4bbf07 refactor(collections): share the list editor logic between desktop and phone
useListEditor seeds the form from the target, handles the cover upload and the
Unsplash search, cleans the links and creates or updates the list for both the
dialog and the sheet. The sheet keeps holding the last list through its exit
and still hands over a list whose cover upload failed when it closes.
2026-10-09 15:19:49 +02:00
Maurice 634dd411c5 refactor(collections): share the copy to trip picker between desktop and phone
useTripCopyPicker loads the trips on every opening, filters them by the search,
formats the date range and turns the copy result into toasts for both the
dialog and the sheet. The dialog keeps its guard against an empty selection.
2026-10-09 15:19:49 +02:00
Maurice 1a4f986cc3 refactor(collections): share the list sharing logic between desktop and phone
useCollectionSharing holds the invitable users lookup, the roster order, invite,
role, cancel, remove and leave for both the share dialog and the share sheet.
The dialog keeps one busy member per kind of row action, the sheet one for all.
2026-10-09 15:19:48 +02:00
Maurice cf73779070 refactor(notifications): share the notification row actions between desktop and phone
Answering a question once, following a link after marking it read and the compact timestamp live in useNotificationItemActions. The desktop item keeps closing its panel after a navigation through the optional onClose.
2026-10-09 15:19:48 +02:00
Maurice a7bd26722a refactor(settings): share the general settings save between desktop and phone
Saving one preference with the error toast on failure lives in one useSettingSaver hook; the desktop tab drops its eleven inline copies of it.
2026-10-09 15:19:48 +02:00
Maurice 3b4f17643c refactor(settings): share the appearance editor between desktop and phone
The live preview, the debounced save with its flush on leave, the colour mode save and the widget toggles live in one useAppearanceEditor hook. The contrast helpers and widget groups move to appearanceModel.
2026-10-09 15:19:48 +02:00
Maurice 05394644b9 refactor(admin): share the default user settings logic between desktop and phone
Loading, saving and resetting the defaults for users and the map field handling live in one useDefaultUserSettings hook that reads the presets and style rules from mapSettingsModel. Each shell passes its own error text and preview stamp.
2026-10-09 15:19:48 +02:00
Maurice 0722a3b6ad refactor(settings): share the map settings form between desktop and phone
The tile presets, the provider and style rules and the preview place move to mapSettingsModel, the form state and save to one useMapSettingsForm hook. The phone keeps showing the normalized style before the save lands, through an option.
2026-10-09 15:19:48 +02:00
Maurice d042a18d0a refactor(settings): share the notification settings logic between desktop and phone
The preference matrix, the webhook and ntfy credentials and the channel test sends now live in one useNotificationSettings hook. The phone keeps sending the whole matrix on a toggle and skipping a token typed as the mask, through two options.
2026-10-09 15:19:48 +02:00
Maurice a8dc000e7e refactor(settings): share the account settings logic between desktop and phone
Profile and avatar, the password change, two factor setup with its backup codes and the account deletion now live in one useAccountSettings hook. Two existing differences stay as options: the toast key for a failed avatar removal and whether the backup code actions skip an empty code list.
2026-10-09 15:19:48 +02:00
Maurice 231acced7e refactor(settings): share the passkey logic between desktop and phone
Listing, adding with the step up and the WebAuthn ceremony, renaming and
deleting passkeys now live in one usePasskeys hook together with the
date and abort helpers. The desktop section and the phone card keep
their own markup.
2026-10-09 15:19:48 +02:00
Maurice 3b4539f600 refactor(settings): share the integration and plugin tab gating between desktop and phone
The addon flags, the managed install flag and the addon reload of the integrations tab now come from one useIntegrationGates hook, and useSettings hands both shells the plugins tab flag next to the integrations one.
2026-10-09 15:19:47 +02:00
Maurice deff306755 refactor(mcp): share the MCP configuration logic between desktop and phone
The OAuth presets, the endpoint snippets, the OAuth clients, sessions and API tokens with their handlers and the copy tick now live in one useMcpIntegration hook. Two existing differences stay as options: the desktop loads only while the addon is on, and the phone reads the client list back after a create or rotate where the desktop appends locally.
2026-10-09 15:19:47 +02:00
Maurice 5ee7cc052c refactor(plugins): share the plugin user settings, OAuth and activity logic between desktop and phone
The declared field form with its save, the actions and their confirm state, the OAuth connect and disconnect and the activity log now live in usePluginUserSettings, usePluginOAuth and usePluginActivity. Each shell keeps its own form, confirm dialog or sheet and picker.
2026-10-09 15:19:47 +02:00
Maurice 2acfc9cb43 refactor(memories): share the photo provider connection cards between desktop and phone
The provider field model, the seeding and hydration, save and test now live in one usePhotoProviderConnections hook. Two existing differences stay as options: on the phone the status route alone sets the badge, and the desktop keeps its space before the server reason in a failed test toast.
2026-10-09 15:19:47 +02:00
Maurice 82070c72ec refactor(oauth): share the scope group picker logic between desktop and phone
The grouped scopes, the folded groups and the select all, group and single scope toggles now live in one useScopeSelection hook. Both pickers keep their own rows.
2026-10-09 15:19:47 +02:00
Maurice 309753b799 refactor(settings): share the AI parsing form between desktop and phone
The provider, model, key and multimodal state, the hydration from the settings store and the save with its reload on failure now live in one useLlmConnection hook. The phone keeps its picker sheet state.
2026-10-09 15:19:47 +02:00
Maurice 68e2e0639b refactor(airtrail): share the AirTrail connection form between desktop and phone
Both settings shells now read their state, the save and test handlers and the canSave rule from one useAirTrailSettings hook and keep only their own markup.
2026-10-09 15:19:47 +02:00
Maurice 6c5ab5414a refactor(admin): share the JWT rotation and passkey reset between desktop and phone
useAdminUserActions now rotates the JWT secret and resets a user's passkeys for the desktop dialogs and the phone sheets. Each shell keeps its own confirm step, and the phone sheet still stays busy until the reset settles.
2026-10-09 15:19:47 +02:00
Maurice feb99ce398 refactor(admin): share the admin settings saves and the TREK API lists between desktop and phone
useAdminSettingsActions now holds the OIDC and file type saves and the five place switches, writing through the admin bag both shells already receive. trekApiModel keeps the TREK Places API fields, facts and sources the desktop card and the phone block list.
2026-10-09 15:19:46 +02:00
Maurice 7738334fd6 refactor(admin): share the addon manager and the AI parsing config between desktop and phone
useAddonManager now loads and toggles the addons and builds the provider shelves, useLlmParsingConfig holds the AI parsing form with the Ollama model list and pull, and addonModel keeps the shared types, collab sub features, labels and recommended models. Both shells keep their own markup.
2026-10-09 15:19:46 +02:00