mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-11-13 07:40:59 +00:00
d7c4324afc
* chore(capacitor): base files for capacitor
* chore(capacitor): base plugins
* feat(auth): hand a browser sign-in over to the native app
The native apps show the server's own UI in a WebView, where neither SSO nor
passkeys can run. They sign in through the system browser instead and need a
way to carry that session back.
The app keeps a random verifier and sends only its sha256 into the browser.
Once signed in there, the browser trades that challenge for a one-time code
(cookie session only, so an API or MCP token cannot mint itself a browser
session), and the WebView redeems the code together with the verifier. The
code rides through a URL scheme any app could claim, so on its own it is
worthless; it is single use and good for a minute.
Also: /api/health/features reports nativeApp so the apps can refuse servers
that predate this, and hashed files under assets/ are served immutable,
which the iOS app needs to start offline without a service worker.
* feat(native): the apps load the server's own UI
The apps ship only an address screen now. Once a server is picked, the
native side points the WebView at it: TrekBridgeViewController on iOS and a
config copy with server.url on Android. The UI then comes from that server,
in the version it runs and on its own origin, so the session cookie,
uploads, /ws and plugins work exactly as in a browser and no app release
has to keep pace with the servers out there.
The address screen (native-shell/, built into native-dist/) probes
/api/health/features through native HTTP, tries https before http when no
scheme was typed, and refuses servers without the nativeApp flag. It also
serves as the error page when the remembered server does not load: retry,
change server, or on iOS the stored copy of the server's start page.
TrekShell is the app's own plugin for all of that: remember, change and
reload the server, sign in through ASWebAuthenticationSession or a Custom
Tab, and on iOS keep and open the offline copy of the start page, because
WKWebView runs no service worker for a domain the app does not list.
Plugins the frame does not use are gone (push, camera, geolocation,
calendar, file transfer, in-app browser and more): the WebView covers the
camera and location itself, and push needs a relay before it is worth
shipping. With them go the push entitlement, the calendar usage strings
and the Firebase bits. The iOS scheme falls back to capacitor://, since
Capacitor drops an iosScheme of https, and the arm64 capability replaces
armv7.
* feat(native): the UI knows when it runs inside the app
Everything the server's UI does differently inside the iOS and Android app
lives under src/native and is inert in a browser.
Sign-in: SSO and the passkey button go through the system browser
(signInThroughBrowser), because identity providers refuse embedded
browsers and WebAuthn needs a domain association no build can have for
every server. The browser end is the new /native-handoff page: it signs
the user in if needed and hands the session over only after an explicit
tap, so a link carrying somebody else's challenge cannot pass a session
on silently. The verifier is hashed with @noble/hashes because
crypto.subtle is missing on the plain-http servers many home networks
use. An OIDC-only install no longer bounces to the IdP inside the
WebView, and passkey management is hidden in the app.
Downloads: the WebView cannot save a blob, so downloadBlob, downloadFile
and openFile write to the app cache and open the share sheet. The eight
places that built their own download anchor now use downloadBlob, which
they should have anyway.
The rest: "Change server" on the login page and in the account settings,
the splash hides after the first frame, Android's back button walks
history before it leaves the app, the status bar follows the scheme, and
on iOS the start page is refreshed and every chunk of the build (listed
in the new asset-manifest.json) is pulled into WebKit's cache so the app
can start without network.
* ci(native): build the Android and iOS shells on every change to them
Compiles the Swift side on a macOS runner so nobody needs a Mac to know it
still builds, and leaves a debug APK on every run to install on a phone.
Unsigned: signing and store uploads need secrets fork PRs do not get.
* feat(native): offline vector maps in the iOS app
In a browser the service worker answers MapLibre from the gl-map-offline
cache that glPrefetcher fills for trips marked for offline. The iOS app has
no service worker, so nothing read that cache there and the map went blank
without network.
A trek-offline:// protocol takes the service worker's place. Inside the iOS
app the MapLibre style URL is rewritten to it, the handler rewrites every
https URL inside the style and its TileJSON the same way, and then serves
documents network first and tiles, glyphs and sprites cache first. Outside
the iOS app nothing changes. The default OpenFreeMap basemap is covered;
Mapbox GL has no protocol hook and stays online-only in the app, as does a
custom raster template, whose opaque responses only a service worker can
store.
* fix(native): keep the iOS offline copy inside the app
loadSimulatedRequest went to the server URL without its trailing slash, and
Capacitor keeps a navigation in the WebView only when it starts with the
bridge's serverURL, slash included. The offline start page would have
opened in Safari instead. Also covers the platform helpers and the
hand-off API module.
* feat(native): the small things that give a WebView away
- A short haptic tap on success, warning and error toasts, which is where
every save and delete already reports. Info toasts stay silent.
- No "‹ › Done" strip above the iOS keyboard.
- No Safari preview when a link is long-pressed.
- The swipe from the left edge goes back on iOS, through the same history
Android's back button walks.
* test(mobile): the backup-code download revokes its URL after the shared delay
The mobile twin of the AccountTab test still expected the object URL to be
revoked in the same tick. Since both screens download through downloadBlob,
the revoke happens after its 100 ms grace period.
* fix(native): remember the login by default inside the app
With the switch off the app got a session cookie, which dies with the app
process, so every time the phone unloaded TREK the user had to sign in
again. Found while running the Android build in the emulator.
* fix(native): no overscroll stretch on Android
The UI asks for no overscroll effect with overscroll-behavior: none on html,
and Chrome honours it. The Android WebView draws the stretch on its root
scroller natively, though, and it scales the whole view, so the top bar and
the bottom dock were pulled along with the page. Found in the emulator.
* fix(native): Android shows "server not reachable" instead of a blank page
Capacitor injects its bridge on Android only into the server's origin once
server.url is set, so the local error page it switches to when the server
does not load had no bridge. It could neither retry nor change the server
and stayed blank.
TrekWebViewClient now catches a failed page load (a network error, or a 5xx
from a proxy while TREK restarts) and the app starts over on the bundled
address screen, where the bridge is present and the screen offers exactly
those two choices. The server config no longer carries errorPath.
Two traps on the way, both found in the emulator: a restart during launch
has to be a fresh task, since recreate() leaves the system splash lying over
the new page; and a restart shows no launch splash at all, because the
splash plugin cannot take it down again when the page hides it early.
* feat(native): TREK's own app icon and launch screen, named just TREK
The shells still carried Capacitor's placeholder icon and splash, the blue
X on a grid. They now show the white TREK mark on a dark, slightly glassy
tile: a soft light from the top left and a sheen over the upper half, in
the app's launch colour #09090b. Android 12+ draws its launch screen on the
same colour instead of light grey.
scripts/generate-app-icons.mjs renders the sources into assets/ from
public/icons/icon-white.svg, and `npm run icons:app` turns them into every
size both platforms ask for through @capacitor/assets. The Android
foreground mark is sized for the adaptive icon's round mask.
The home screen label is TREK: the old "TREK - Plan your trips!" was cut
off under the icon, and the longer title belongs to the store listings.
* fix(native): new lint warnings and the MapLibre protocol type after the dev merge
Awaits that sat in loops in the native-auth tests run together, the hand-off hook marks its navigations as ignored, the native tests drop their non-null assertions, and the offline protocol answers with the data type MapLibre 6.15 expects.
* fix(native): strict types in the address screen, Prettier on the native-auth e2e suite, file-local exports
The address screen's element helper returns the plain element instead of Object.assign's intersection, which strict mode could not represent; the haptics test reads an optional argument as optional; three exports only their own file used are local now.
* fix(native): Prettier on the native client files, rate-limit e2e requests in sequence
Formats the files the client formatting gate listed, and NATIVE-E2E-005 sends its twenty exchange attempts one after another: all at once they reset the test server's connections.
* fix(native): hide passkeys in the app through usePasskeys
The flag in useAccountSettings grew the identical destructuring in both account views past the duplication threshold; the shared passkeys hook already decides when its card is hidden, so the app check lives there now.
* feat(native): everything the App Store and Google Play submissions need
- iOS: microphone usage text for "Take Video", no-export-compliance flag,
ExportOptions.plist for App Store Connect uploads, the unused push
forwarders gone; CI builds with Xcode 26 and lints the property lists.
- Android: version and signing from Gradle properties (unsigned without
them), R8 with keep rules for TREK's and Capacitor's reflective classes,
no Auto Backup of the session cookie, no external file provider path,
template and Firebase leftovers removed, keystores and service accounts
ignored, full-size adaptive icon layers with a monochrome layer; CI also
builds the release APK.
- native-release.yml: signed bundle to a Play testing track and archive to
TestFlight, by hand or on a v* tag, behind the store environment.
- Version handshake: the server reports nativeApi 1, the app refuses a
server below its minimum and tolerates an app older than the offline copy.
- Address screen: privacy policy link, "Try the demo" and "What is a TREK
server?"; the privacy link also in the app's server settings. Three new
native strings in all 27 locales.
- Donation links and the notices asking for one are hidden in the app.
- Store listings for "TREK Travel Planner" in client/fastlane: texts, review
notes with placeholders, privacy and account deletion page drafts, the
feature graphic and icon, a length and image check in CI, and a Playwright
store project with the scripts that turn its captures into screenshots.
- Docs: wiki/Native-Apps.md, README no longer says there is no store app.
* fix(native): read a notice button's href without a weak type
An action button carries no href, so a parameter typed as only an optional href refused the notice DTO; the button type now names its kind as well.
* feat(native): a welcoming onboarding for the address screen
The app's own screen now opens on a welcome: the TREK mark, a line about what
TREK is, and two clear paths — connect the TREK you already open in the browser,
or get TREK Cloud. Both lead to polished screens: the address field with live
validation, a shake and haptic on a bad address and a success tick before the
server takes over; and a TREK Cloud intro with what it offers and a way in.
Screens slide and stagger in, buttons give a tap, and it all respects the safe
areas, light and dark, and reduced motion. Self-hosters are unaffected: cloud is
its own path, never in the way. New native strings are added across all locales
(English placeholders outside en/de, to translate).
* feat(native): a plan picker for TREK Cloud, with live prices
The Get TREK Cloud path now leads to a plan picker that reads the live plans
from the site (/api/plans), so the prices and quotas always match the website.
Monthly and yearly in a segmented toggle, the year marked with its saving, each
plan a card with its price and what it includes. Subscribe is wired to finish on
the web order for now; it becomes an Apple/Google in-app purchase once the store
products exist. New strings across all locales (en and de translated).
* feat(native): light status bar and a Go key on the address screen
The address screen sits on the near-black surface, so set the status bar to draw
its clock and icons in light while it is up; the server's own UI takes over the
style once it loads. The address field's on-screen return key now reads Go. Both
fail quietly where there is no native status bar (web, the simulator).
* i18n(native): translate the onboarding into es, fr, it, nl and pl
The welcome, TREK Cloud and plan-picker strings were English placeholders in
every locale but en and de. The five largest remaining European languages are
now translated in full; the others still carry the English text and are a
follow-up for native speakers.
* feat(native): the in-app TREK Cloud subscription flow
After picking a plan, the app now carries the whole purchase itself when the build
can take one: choose your address (checked for free as you type, against the same
endpoint the website uses), your email, and subscribe. The receipt goes to
/api/iap/redeem, and a Setting up your TREK screen waits on the new address and
loads it the moment it answers.
The purchase sits behind an IapClient seam (src/native/iap.ts): a fake drives the
whole flow in development and preview, the native client reports itself
unavailable until the store plugin and products exist, and until then the plan
picker still finishes on the web, so nothing half-wired faces a customer. New
claim and provisioning strings across all locales (en, de and the five largest
European languages translated).
* i18n(native): translate the app into the remaining 20 languages
The onboarding, plan picker, claim and provisioning strings were English
placeholders outside en, de and the five largest European languages. They are
now translated in full across the other 20 locales (ar, az, br, ca, cs, et, gr,
hu, id, ja, ko, ru, sk, sv, th, tr, uk, vi, zh, zh-TW), placeholders and brand
kept. The app now speaks every language TREK does.
* fix(i18n): add the Hebrew native strings, and correct the LoginPage size baseline
The he locale had every domain but native.ts, which broke i18n parity, the shared
coverage specs and the client parity test once the native strings existed. Add
he/native.ts with all native keys translated. Also correct the LoginPage size
baseline to its current line count.
* i18n(native): excuse the TREK Cloud brand, mark Email same-as-en, exempt the quota counts
The strict i18n checks, which the feature-branch CI does not run, catch three
things now that the native strings exist in every locale: TREK Cloud read as an
untranslated English phrase (it is a product name, like Vacay and Atlas, so add
it to the brand list); Email left identical in Italian, Indonesian and
Vietnamese, where it is the local word too (mark same-as-en) and in Greek (give
it a Greek term); and the GB and AI-document quota strings carrying {n} without
being plural groups (both are figures that never show a singular, like the other
unit-symbol counts in NOT_PLURAL).
* fix(native): typecheck, lint and knip on the native code; wire he's native bundle
The full suite, which the feature-branch CI does not run, catches four things the
native work still had: a non-narrowed union in the claim flow (tsc), a helper
named useFake that the react-hooks rule read as a hook (eslint), two iap types
exported but used only inside the file (knip), and the Hebrew native strings
present as a file but never spread into he's merged bundle (the aggregated key
parity test). All four fixed.
* fix(native): a flat redeem result, so the claim flow typechecks
The discriminated union did not narrow under the native-shell tsconfig, so the
failure code read as absent on the whole type. Use a flat result with optional
instanceUrl and code instead: both are always present on the type, no narrowing
needed, and the ok plus instanceUrl guard still routes success from refusal.
* style: prettier-format the native and i18n changes
The feature-branch CI does not run the formatting check, so the conflict-resolved
files (AboutTab, useAccountSettings, useTripExport), the native shell and iap
module, and the i18n files touched by the translation scripts were never run
through Prettier. Format them all; no behaviour changes.
* chore(native): re-trigger CI on the formatted tree
---------
Co-authored-by: Maurice <mauriceboe@icloud.com>
1059 lines
53 KiB
JSON
1059 lines
53 KiB
JSON
{
|
|
"pairs": [
|
|
{
|
|
"feature": "Accommodation (stay) create/edit",
|
|
"hooks": ["src/components/Planner/stayFormModel.ts"],
|
|
"desktop": ["src/components/Planner/DayDetailPanel.tsx", "src/components/Planner/useDayDetail.ts"],
|
|
"mobile": ["src/mobile/screens/trip/sheets/MAccommodationSheet.tsx"]
|
|
},
|
|
{
|
|
"feature": "Add place to collection",
|
|
"hooks": ["src/components/Collections/addPlaceModel.ts", "src/components/Collections/useAddPlaceToCollection.ts"],
|
|
"desktop": ["src/components/Collections/AddPlaceToCollectionModal.tsx"],
|
|
"mobile": ["src/mobile/screens/collections/MCollAddSheet.tsx"]
|
|
},
|
|
{
|
|
"feature": "Addon manager",
|
|
"hooks": [
|
|
"src/components/Admin/addons/addonModel.ts",
|
|
"src/components/Admin/addons/useAddonManager.ts"
|
|
],
|
|
"desktop": ["src/components/Admin/AddonManager.tsx"],
|
|
"mobile": ["src/mobile/screens/admin/MAdminAddonManager.tsx"]
|
|
},
|
|
{
|
|
"feature": "Addon manager: AI tile",
|
|
"hooks": ["src/components/Admin/addons/useAiAddonTile.ts"],
|
|
"desktop": ["src/components/Admin/addons/AiAddonTile.tsx"],
|
|
"mobile": ["src/mobile/screens/admin/MAdminAddonManager.tsx"]
|
|
},
|
|
{
|
|
"feature": "Admin notification preference matrix",
|
|
"hooks": ["src/components/Admin/useAdminNotificationMatrix.ts", "src/pages/admin/AdminPage.constants.ts"],
|
|
"desktop": ["src/pages/admin/AdminNotificationsPanel.tsx"],
|
|
"mobile": ["src/mobile/screens/admin/MAdminNotifyMatrix.tsx"]
|
|
},
|
|
{
|
|
"feature": "Admin notifications tab",
|
|
"hooks": ["src/components/Admin/useAdminNotificationSettings.ts"],
|
|
"desktop": ["src/pages/admin/AdminNotificationsTab.tsx"],
|
|
"mobile": ["src/mobile/screens/admin/MAdminNotificationsSection.tsx"]
|
|
},
|
|
{
|
|
"feature": "Admin page shell",
|
|
"hooks": ["src/pages/admin/useAdmin.ts"],
|
|
"desktop": ["src/pages/AdminPage.tsx"],
|
|
"mobile": ["src/mobile/screens/admin/MAdmin.tsx"]
|
|
},
|
|
{
|
|
"feature": "Admin settings tab: trekApiModel",
|
|
"hooks": ["src/components/Admin/trekApiModel.ts"],
|
|
"desktop": ["src/pages/admin/TrekApiCard.tsx"],
|
|
"mobile": ["src/mobile/screens/admin/MApiProviderBlocks.tsx"]
|
|
},
|
|
{
|
|
"feature": "Admin settings tab: useAdminSettingsActions",
|
|
"hooks": ["src/components/Admin/useAdminSettingsActions.ts"],
|
|
"desktop": ["src/pages/admin/AdminSettingsTab.tsx"],
|
|
"mobile": ["src/mobile/screens/admin/MAdminSettingsSection.tsx"]
|
|
},
|
|
{
|
|
"feature": "Admin users invite status",
|
|
"hooks": ["src/pages/admin/adminModel.ts"],
|
|
"desktop": ["src/pages/admin/AdminUsersTab.tsx"],
|
|
"mobile": ["src/mobile/screens/admin/MAdminUsersSection.tsx"]
|
|
},
|
|
{
|
|
"feature": "AI assistant chat",
|
|
"hooks": ["src/components/Assistant/useAssistantThread.ts", "src/components/Assistant/useAssistantStatus.ts"],
|
|
"desktop": ["src/components/Assistant/AssistantWindow.tsx"],
|
|
"mobile": ["src/mobile/screens/trip/assistant/MAssistantScreen.tsx"]
|
|
},
|
|
{
|
|
"feature": "AI assistant home chat",
|
|
"hooks": ["src/components/Assistant/useAssistantHome.ts"],
|
|
"desktop": ["src/components/Assistant/AssistantWindow.tsx"],
|
|
"mobile": [
|
|
"src/mobile/screens/assistant/MAssistantHomeScreen.tsx",
|
|
"src/mobile/screens/dashboard/MDashboard.tsx"
|
|
]
|
|
},
|
|
{
|
|
"feature": "Assistant hints",
|
|
"hooks": ["src/components/Assistant/useAssistantHints.ts"],
|
|
"desktop": ["src/components/Assistant/AssistantHeader.tsx", "src/components/Assistant/AssistantLauncher.tsx"],
|
|
"mobile": [
|
|
"src/mobile/screens/trip/assistant/MAssistantScreen.tsx",
|
|
"src/mobile/screens/trip/sheets/MMehrSheet.tsx"
|
|
]
|
|
},
|
|
{
|
|
"feature": "Atlas country/region action sheet",
|
|
"hooks": ["src/pages/atlas/useAtlasCountryActions.ts"],
|
|
"desktop": ["src/pages/AtlasPage.tsx"],
|
|
"mobile": ["src/mobile/screens/atlas/MAtlasCountryPopup.tsx"]
|
|
},
|
|
{
|
|
"feature": "Atlas page: atlasModel",
|
|
"hooks": ["src/pages/atlas/atlasModel.ts"],
|
|
"desktop": [
|
|
"src/components/Atlas/AtlasCountryPlaces.tsx",
|
|
"src/components/shared/CountryFlag.tsx",
|
|
"src/pages/AtlasPage.tsx"
|
|
],
|
|
"mobile": ["src/mobile/screens/atlas/MAtlas.tsx", "src/mobile/screens/atlas/MAtlasBucketSheet.tsx"]
|
|
},
|
|
{
|
|
"feature": "Atlas page: useAtlas",
|
|
"hooks": ["src/pages/atlas/useAtlas.ts"],
|
|
"desktop": ["src/pages/AtlasPage.tsx"],
|
|
"mobile": ["src/mobile/screens/atlas/MAtlas.tsx", "src/mobile/screens/atlas/atlasController.ts"]
|
|
},
|
|
{
|
|
"feature": "Audit log",
|
|
"hooks": ["src/components/Admin/useAuditLog.ts"],
|
|
"desktop": ["src/components/Admin/AuditLogPanel.tsx"],
|
|
"mobile": ["src/mobile/screens/admin/MAdminAuditLogPanel.tsx"]
|
|
},
|
|
{
|
|
"feature": "Backup panel",
|
|
"hooks": ["src/components/Admin/useBackupAdmin.ts"],
|
|
"desktop": ["src/components/Admin/BackupPanel.tsx"],
|
|
"mobile": ["src/mobile/screens/admin/MAdminBackupPanel.tsx"]
|
|
},
|
|
{
|
|
"feature": "Booking forms: linked expense and file attach",
|
|
"hooks": ["src/components/Planner/useBookingExpenseIntent.ts"],
|
|
"desktop": ["src/components/Planner/ReservationModal.tsx", "src/components/Planner/TransportModal.tsx"],
|
|
"mobile": [
|
|
"src/mobile/screens/trip/sheets/MReservationSheet.tsx",
|
|
"src/mobile/screens/trip/sheets/MTransportFormSheet.tsx"
|
|
]
|
|
},
|
|
{
|
|
"feature": "Booking save follow-up: travellers and files before the editor closes",
|
|
"hooks": ["src/components/Planner/useBookingFollowUp.ts"],
|
|
"desktop": ["src/components/Planner/ReservationModal.tsx", "src/components/Planner/TransportModal.tsx"],
|
|
"mobile": [
|
|
"src/mobile/screens/trip/sheets/MReservationSheet.tsx",
|
|
"src/mobile/screens/trip/sheets/MTransportFormSheet.tsx"
|
|
]
|
|
},
|
|
{
|
|
"feature": "Bookings and transports lists",
|
|
"hooks": ["src/components/Planner/bookings/bookingsModel.ts"],
|
|
"desktop": [
|
|
"src/components/Planner/DayDetailPanel.tsx",
|
|
"src/components/Planner/DayPlanSidebar.tsx",
|
|
"src/components/Planner/PlaceInspector.tsx",
|
|
"src/components/Planner/ReservationModal.tsx",
|
|
"src/components/Planner/ReservationsPanel.tsx",
|
|
"src/components/Planner/TransportModal.tsx",
|
|
"src/components/Planner/bookings/BookingCard.tsx",
|
|
"src/components/Planner/bookings/BookingDetailDialog.tsx",
|
|
"src/components/Planner/bookings/BookingDetailHost.tsx",
|
|
"src/components/Planner/bookings/BookingDialogShell.tsx",
|
|
"src/components/Planner/bookings/BookingsHeader.tsx",
|
|
"src/components/Planner/bookings/BookingsList.tsx",
|
|
"src/components/Planner/bookings/BookingsTimeline.tsx",
|
|
"src/components/Planner/bookings/bookingFacts.ts",
|
|
"src/components/Planner/bookings/bookingParts.tsx",
|
|
"src/components/Planner/bookings/timelineModel.ts",
|
|
"src/components/Planner/bookings/useReservationListFilter.ts",
|
|
"src/components/Planner/planCosts.ts",
|
|
"src/pages/sharedTrip/SharedBookingsView.tsx",
|
|
"src/pages/sharedTrip/SharedDayCard.tsx"
|
|
],
|
|
"mobile": ["src/mobile/screens/trip/tabs/MBookingsTab.tsx", "src/mobile/screens/trip/tabs/MTransportsTab.tsx"]
|
|
},
|
|
{
|
|
"feature": "Bottom nav context-aware create action",
|
|
"hooks": ["src/components/Layout/useCreateAction.ts"],
|
|
"desktop": ["src/components/Layout/BottomNav.tsx"],
|
|
"mobile": ["src/mobile/components/MBottomNav.tsx"]
|
|
},
|
|
{
|
|
"feature": "Bulk save selected places to a collection",
|
|
"hooks": ["src/components/Collections/useSaveTripPlacesToList.ts"],
|
|
"desktop": ["src/components/Collections/SaveTripPlacesToListModal.tsx"],
|
|
"mobile": ["src/mobile/screens/trip/places/MPlacesSaveToCollectionSheet.tsx"]
|
|
},
|
|
{
|
|
"feature": "Category manager",
|
|
"hooks": ["src/components/Admin/useCategoryAdmin.ts"],
|
|
"desktop": ["src/components/Admin/CategoryManager.tsx"],
|
|
"mobile": ["src/mobile/screens/admin/MAdminCategoryManager.tsx"]
|
|
},
|
|
{
|
|
"feature": "Collab chat: collabModel",
|
|
"hooks": ["src/components/Collab/collabModel.ts"],
|
|
"desktop": [
|
|
"src/components/Collab/CollabChatMessages.tsx",
|
|
"src/components/Collab/CollabPolls.tsx",
|
|
"src/components/Collab/useCollabChat.ts"
|
|
],
|
|
"mobile": [
|
|
"src/mobile/screens/trip/tabs/MCollabChat.tsx",
|
|
"src/mobile/screens/trip/tabs/MCollabNotes.tsx",
|
|
"src/mobile/screens/trip/tabs/MCollabPolls.tsx"
|
|
]
|
|
},
|
|
{
|
|
"feature": "Collab chat: useCollabChatData",
|
|
"hooks": ["src/components/Collab/useCollabChatData.ts"],
|
|
"desktop": ["src/components/Collab/useCollabChat.ts"],
|
|
"mobile": ["src/mobile/screens/trip/tabs/MCollabChat.tsx"]
|
|
},
|
|
{
|
|
"feature": "Collab notes",
|
|
"hooks": ["src/components/Collab/useCollabNotesData.ts"],
|
|
"desktop": ["src/components/Collab/CollabNotes.tsx"],
|
|
"mobile": ["src/mobile/screens/trip/tabs/MCollabNotes.tsx"]
|
|
},
|
|
{
|
|
"feature": "Collab polls",
|
|
"hooks": ["src/components/Collab/useCollabPolls.ts"],
|
|
"desktop": ["src/components/Collab/CollabPolls.tsx"],
|
|
"mobile": ["src/mobile/screens/trip/tabs/MCollabPolls.tsx"]
|
|
},
|
|
{
|
|
"feature": "Collection list editor",
|
|
"hooks": ["src/components/Collections/useListEditor.ts"],
|
|
"desktop": ["src/components/Collections/ListEditorModal.tsx"],
|
|
"mobile": ["src/mobile/screens/collections/MCollEditSheet.tsx"]
|
|
},
|
|
{
|
|
"feature": "Collection place detail",
|
|
"hooks": ["src/components/Collections/useCollectionPlaceForm.ts"],
|
|
"desktop": ["src/components/Collections/CollectionPlaceDetail.tsx"],
|
|
"mobile": ["src/mobile/screens/collections/MCollPlaceSheet.tsx"]
|
|
},
|
|
{
|
|
"feature": "Collection sharing",
|
|
"hooks": ["src/components/Collections/useCollectionSharing.ts"],
|
|
"desktop": ["src/components/Collections/ShareCollectionModal.tsx"],
|
|
"mobile": ["src/mobile/screens/collections/MCollShareSheet.tsx"]
|
|
},
|
|
{
|
|
"feature": "Collections page: collectionsModel",
|
|
"hooks": ["src/pages/collections/collectionsModel.ts"],
|
|
"desktop": [
|
|
"src/components/Collections/AddPlaceToCollectionModal.tsx",
|
|
"src/components/Collections/CollectionFilterBar.tsx",
|
|
"src/components/Collections/CollectionMap.tsx",
|
|
"src/components/Collections/CollectionPicker.tsx",
|
|
"src/components/Collections/CollectionPlaceDetail.tsx",
|
|
"src/components/Collections/ListEditorModal.tsx",
|
|
"src/components/Collections/MSaveToCollectionSheet.tsx"
|
|
],
|
|
"mobile": [
|
|
"src/mobile/screens/collections/MCollAddSheet.tsx",
|
|
"src/mobile/screens/collections/MCollEditSheet.tsx",
|
|
"src/mobile/screens/collections/MCollPlaceRow.tsx",
|
|
"src/mobile/screens/collections/MCollPlaceSheet.tsx",
|
|
"src/mobile/screens/collections/MCollections.tsx"
|
|
]
|
|
},
|
|
{
|
|
"feature": "Collections page: useCollections",
|
|
"hooks": ["src/pages/collections/useCollections.ts"],
|
|
"desktop": ["src/pages/CollectionsPage.tsx"],
|
|
"mobile": ["src/mobile/screens/collections/MCollections.tsx"]
|
|
},
|
|
{
|
|
"feature": "Collection tours (LIB-03): useCollectionTours, useCollectionTourTakeOver",
|
|
"hooks": [
|
|
"src/components/Tours/collection/useCollectionTours.ts",
|
|
"src/components/Tours/collection/useCollectionTourTakeOver.ts"
|
|
],
|
|
"desktop": ["src/components/Tours/collection/CollectionToursSection.tsx"],
|
|
"mobile": ["src/mobile/screens/collections/MCollTours.tsx"]
|
|
},
|
|
{
|
|
"feature": "Copy collection places to a trip",
|
|
"hooks": ["src/components/Collections/useTripCopyPicker.ts"],
|
|
"desktop": ["src/components/Collections/CopyToTripModal.tsx"],
|
|
"mobile": ["src/mobile/screens/collections/MCollTripPickerSheet.tsx"]
|
|
},
|
|
{
|
|
"feature": "Costs/budget ledger: costsModel",
|
|
"hooks": ["src/components/Budget/costsModel.ts"],
|
|
"desktop": ["src/components/Budget/CostsPanel.tsx"],
|
|
"mobile": ["src/mobile/screens/trip/sheets/MCostSheet.tsx", "src/mobile/screens/trip/tabs/MCostsTab.tsx"]
|
|
},
|
|
{
|
|
"feature": "Costs/budget ledger: useCostsLedger, useSettlementForm, useExpenseLinks",
|
|
"hooks": ["src/components/Budget/useCostsLedger.ts", "src/components/Budget/useSettlementForm.ts", "src/components/Budget/useExpenseLinks.ts"],
|
|
"desktop": ["src/components/Budget/CostsPanel.tsx"],
|
|
"mobile": ["src/mobile/screens/trip/tabs/MCostsTab.tsx"]
|
|
},
|
|
{
|
|
"feature": "Create/edit trip form",
|
|
"hooks": ["src/components/Trips/tripFormModel.ts", "src/components/Trips/useTripCoverPicker.ts"],
|
|
"desktop": ["src/components/Trips/TripFormModal.tsx"],
|
|
"mobile": ["src/mobile/screens/dashboard/MNewTripSheet.tsx"]
|
|
},
|
|
{
|
|
"feature": "Dashboard page",
|
|
"hooks": ["src/pages/dashboard/useDashboard.ts"],
|
|
"desktop": ["src/pages/DashboardPage.tsx"],
|
|
"mobile": ["src/mobile/screens/dashboard/MDashboard.tsx"]
|
|
},
|
|
{
|
|
"feature": "Dashboard residuals: dashboardModel",
|
|
"hooks": ["src/pages/dashboard/dashboardModel.ts"],
|
|
"desktop": ["src/pages/DashboardPage.tsx"],
|
|
"mobile": ["src/mobile/screens/dashboard/MDashWidgets.tsx", "src/mobile/screens/dashboard/MDashboard.tsx"]
|
|
},
|
|
{
|
|
"feature": "Dashboard residuals: useDashboardPlugins",
|
|
"hooks": ["src/components/Dashboard/useDashboardPlugins.ts"],
|
|
"desktop": ["src/pages/DashboardPage.tsx"],
|
|
"mobile": ["src/mobile/screens/dashboard/MDashboard.tsx"]
|
|
},
|
|
{
|
|
"feature": "Dashboard widgets: useCollectionLists",
|
|
"hooks": ["src/components/Dashboard/useCollectionLists.ts"],
|
|
"desktop": ["src/components/Dashboard/CollectionsWidget.tsx"],
|
|
"mobile": ["src/mobile/screens/dashboard/MDashWidgets.tsx"]
|
|
},
|
|
{
|
|
"feature": "Dashboard widgets: useCurrencyConverter, useDashboardTimezones",
|
|
"hooks": [
|
|
"src/components/Dashboard/useCurrencyConverter.ts",
|
|
"src/components/Dashboard/useDashboardTimezones.ts"
|
|
],
|
|
"desktop": ["src/pages/DashboardPage.tsx"],
|
|
"mobile": ["src/mobile/screens/dashboard/MDashWidgets.tsx"]
|
|
},
|
|
{
|
|
"feature": "Day detail",
|
|
"hooks": ["src/components/Planner/dayDetailModel.ts"],
|
|
"desktop": ["src/components/Planner/DayDetailPanel.tsx"],
|
|
"mobile": ["src/mobile/screens/trip/plan/useMPlanTimeline.ts", "src/mobile/screens/trip/sheets/MDaySheet.tsx"]
|
|
},
|
|
{
|
|
"feature": "Day note create/edit/delete",
|
|
"hooks": ["src/hooks/useDayNotes.ts"],
|
|
"desktop": ["src/components/Planner/DayPlanSidebar.tsx"],
|
|
"mobile": ["src/mobile/screens/trip/sheets/MDaySheet.tsx", "src/mobile/screens/trip/sheets/MNoteSheet.tsx"]
|
|
},
|
|
{
|
|
"feature": "Day plan reorder",
|
|
"hooks": ["src/utils/mergedOrder.ts"],
|
|
"desktop": ["src/components/Planner/DayPlanSidebar.tsx"],
|
|
"mobile": ["src/mobile/screens/trip/plan/useMPlanTimeline.ts"]
|
|
},
|
|
{
|
|
"feature": "Day route optimize + Google Maps / CoMaps export",
|
|
"hooks": ["src/components/Planner/dayRoute.ts"],
|
|
"desktop": ["src/components/Planner/DayPlanSidebar.tsx"],
|
|
"mobile": ["src/mobile/screens/trip/plan/useMPlanTimeline.ts", "src/mobile/screens/trip/sheets/MDaySheet.tsx"]
|
|
},
|
|
{
|
|
"feature": "Day weather chip anchor + weather icon map: dayWeather",
|
|
"hooks": ["src/utils/dayWeather.ts"],
|
|
"desktop": ["src/components/Planner/DayPlanSidebar.tsx", "src/pages/TripPlannerPage.tsx"],
|
|
"mobile": ["src/mobile/screens/trip/plan/useMPlanTimeline.ts", "src/mobile/screens/trip/sheets/MDaySheet.tsx"]
|
|
},
|
|
{
|
|
"feature": "Day weather chip anchor + weather icon map: weatherIcons",
|
|
"hooks": ["src/components/Weather/weatherIcons.ts"],
|
|
"desktop": ["src/components/Planner/DayDetailPanel.tsx", "src/components/Weather/WeatherWidget.tsx"],
|
|
"mobile": ["src/mobile/screens/trip/plan/MPlanTimeline.tsx", "src/mobile/screens/trip/sheets/MDaySheet.tsx"]
|
|
},
|
|
{
|
|
"feature": "Default user settings",
|
|
"hooks": ["src/components/Admin/useDefaultUserSettings.ts"],
|
|
"desktop": ["src/components/Admin/DefaultUserSettingsTab.tsx"],
|
|
"mobile": ["src/mobile/screens/admin/MAdminDefaultUserSettings.tsx"]
|
|
},
|
|
{
|
|
"feature": "Dev test notifications panel",
|
|
"hooks": ["src/components/Admin/useDevNotifications.ts"],
|
|
"desktop": ["src/components/Admin/DevNotificationsPanel.tsx"],
|
|
"mobile": ["src/mobile/screens/admin/MAdminDevNotificationsPanel.tsx"]
|
|
},
|
|
{
|
|
"feature": "Document sync leftovers: docSyncModel",
|
|
"hooks": ["src/components/Files/docsync/docSyncModel.ts"],
|
|
"desktop": ["src/components/Files/docsync/DocSyncFlow.tsx", "src/components/Files/docsync/DocSyncPanel.tsx"],
|
|
"mobile": ["src/mobile/screens/trip/tabs/MDocSyncSheet.tsx"]
|
|
},
|
|
{
|
|
"feature": "Document sync leftovers: useScopePicker",
|
|
"hooks": ["src/components/Files/docsync/useScopePicker.ts"],
|
|
"desktop": ["src/components/Files/docsync/DocSyncScopeModal.tsx"],
|
|
"mobile": ["src/mobile/screens/trip/tabs/MDocSyncSheet.tsx"]
|
|
},
|
|
{
|
|
"feature": "Expense editor",
|
|
"hooks": ["src/components/Budget/useExpenseForm.ts"],
|
|
"desktop": ["src/components/Budget/CostsPanel.tsx"],
|
|
"mobile": ["src/mobile/screens/trip/sheets/MCostSheet.tsx"]
|
|
},
|
|
{
|
|
"feature": "GitHub releases panel",
|
|
"hooks": ["src/components/Admin/useGithubReleases.ts", "src/utils/releaseNotes.ts"],
|
|
"desktop": ["src/components/Admin/GitHubPanel.tsx"],
|
|
"mobile": ["src/mobile/screens/admin/MAdminGitHubPanel.tsx"]
|
|
},
|
|
{
|
|
"feature": "Google/Naver shared-list import",
|
|
"hooks": ["src/components/Planner/useListImport.ts"],
|
|
"desktop": ["src/components/Planner/usePlacesSidebar.ts"],
|
|
"mobile": ["src/mobile/screens/trip/sheets/ImpListStep.tsx"]
|
|
},
|
|
{
|
|
"feature": "Places column file routing between the Tours and places imports",
|
|
"hooks": ["src/components/Planner/usePlacesColumnFileImport.ts"],
|
|
"desktop": ["src/components/Planner/usePlacesSidebar.ts"],
|
|
"mobile": ["src/mobile/screens/trip/sheets/MImportSheet.tsx"]
|
|
},
|
|
{
|
|
"feature": "GPX/KML/KMZ file import into places",
|
|
"hooks": ["src/components/Planner/usePlacesFileImport.ts"],
|
|
"desktop": ["src/components/Planner/FileImportModal.tsx"],
|
|
"mobile": ["src/mobile/screens/trip/sheets/ImpFileStep.tsx"]
|
|
},
|
|
{
|
|
"feature": "Journey detail page: JourneyDetailPage.helpers",
|
|
"hooks": ["src/pages/journeyDetail/JourneyDetailPage.helpers.ts"],
|
|
"desktop": [
|
|
"src/components/Journey/JourneyDetailPageAddTripDialog.tsx",
|
|
"src/components/Journey/JourneyDetailPageEntryCard.tsx",
|
|
"src/components/Journey/JourneyDetailPageEntryEditor.tsx",
|
|
"src/components/Journey/JourneyDetailPageGalleryView.tsx",
|
|
"src/components/Journey/JourneyDetailPageMapView.tsx",
|
|
"src/components/Journey/JourneyDetailPagePhotoGrid.tsx",
|
|
"src/components/Journey/JourneyDetailPageProviderPicker.tsx",
|
|
"src/components/Journey/JourneyDetailPageSettingsDialog.tsx",
|
|
"src/components/Journey/JourneyEntryCover.tsx",
|
|
"src/components/Journey/MobileEntryView.tsx",
|
|
"src/pages/JourneyDetailPage.tsx",
|
|
"src/pages/JourneyPublicPage.tsx",
|
|
"src/pages/journeyPublic/useJourneyPublic.ts"
|
|
],
|
|
"mobile": [
|
|
"src/mobile/screens/journey/MJourneyCreateSheet.tsx",
|
|
"src/mobile/screens/journey/MJourneyDetail.tsx",
|
|
"src/mobile/screens/journey/MJourneyEntrySheet.tsx",
|
|
"src/mobile/screens/journey/MJourneySettingsSheet.tsx",
|
|
"src/mobile/screens/journey/mobileJourneyMeta.ts"
|
|
]
|
|
},
|
|
{
|
|
"feature": "Journey day take-over: useJourneyDayImport",
|
|
"hooks": ["src/components/Journey/useJourneyDayImport.ts"],
|
|
"desktop": ["src/components/Journey/JourneyDayImportDialog.tsx"],
|
|
"mobile": ["src/mobile/screens/journey/MJourneyDayImportSheet.tsx"]
|
|
},
|
|
{
|
|
"feature": "Journey day recording: useJourneyRecordingDay",
|
|
"hooks": ["src/components/Journey/useJourneyRecordingDay.ts"],
|
|
"desktop": ["src/components/Journey/JourneyRecordingDialog.tsx"],
|
|
"mobile": ["src/mobile/screens/journey/MJourneyRecordingSheet.tsx"]
|
|
},
|
|
{
|
|
"feature": "Journey detail page: useJourneyDetail",
|
|
"hooks": ["src/pages/journeyDetail/useJourneyDetail.ts"],
|
|
"desktop": ["src/pages/JourneyDetailPage.tsx"],
|
|
"mobile": ["src/mobile/screens/journey/MJourneyDetail.tsx"]
|
|
},
|
|
{
|
|
"feature": "Journey detail screen: useGalleryUpload",
|
|
"hooks": ["src/components/Journey/useGalleryUpload.ts"],
|
|
"desktop": ["src/components/Journey/JourneyDetailPageGalleryView.tsx"],
|
|
"mobile": ["src/mobile/screens/journey/MJourneyDetail.tsx"]
|
|
},
|
|
{
|
|
"feature": "Journey detail screen: useJourneyCarouselSync",
|
|
"hooks": ["src/components/Journey/useJourneyCarouselSync.ts"],
|
|
"desktop": ["src/components/Journey/MobileMapTimeline.tsx"],
|
|
"mobile": ["src/mobile/screens/journey/MJourneyDetail.tsx"]
|
|
},
|
|
{
|
|
"feature": "Journey entry editor",
|
|
"hooks": ["src/components/Journey/useJourneyEntryForm.ts"],
|
|
"desktop": ["src/components/Journey/JourneyDetailPageEntryEditor.tsx"],
|
|
"mobile": ["src/mobile/screens/journey/MJourneyEntrySheet.tsx"]
|
|
},
|
|
{
|
|
"feature": "Journey list page",
|
|
"hooks": ["src/pages/journey/useJourney.ts"],
|
|
"desktop": ["src/pages/JourneyPage.tsx"],
|
|
"mobile": ["src/mobile/screens/journey/MJourney.tsx"]
|
|
},
|
|
{
|
|
"feature": "Journey settings: useJourneySettings",
|
|
"hooks": ["src/components/Journey/useJourneySettings.ts"],
|
|
"desktop": [
|
|
"src/components/Journey/JourneyDetailPageAddTripDialog.tsx",
|
|
"src/components/Journey/JourneyDetailPageSettingsDialog.tsx"
|
|
],
|
|
"mobile": ["src/mobile/screens/journey/MJourneySettingsSheet.tsx"]
|
|
},
|
|
{
|
|
"feature": "Journey settings: useJourneyShareLink",
|
|
"hooks": ["src/components/Journey/useJourneyShareLink.ts"],
|
|
"desktop": ["src/components/Journey/JourneyShareSection.tsx"],
|
|
"mobile": ["src/mobile/screens/journey/MJourneySettingsSheet.tsx"]
|
|
},
|
|
{
|
|
"feature": "Lists sub-tab (packing/todo) persistence",
|
|
"hooks": ["src/hooks/useListsSubTab.ts"],
|
|
"desktop": ["src/pages/tripPlanner/ListsContainer.tsx"],
|
|
"mobile": ["src/mobile/screens/trip/MTripShell.tsx"]
|
|
},
|
|
{
|
|
"feature": "MCP tokens / OAuth sessions admin",
|
|
"hooks": ["src/components/Admin/useMcpTokensAdmin.ts"],
|
|
"desktop": ["src/components/Admin/AdminMcpTokensPanel.tsx"],
|
|
"mobile": ["src/mobile/screens/admin/MAdminMcpTokensPanel.tsx"]
|
|
},
|
|
{
|
|
"feature": "Media lightbox",
|
|
"hooks": ["src/components/Files/useMediaLightbox.ts"],
|
|
"desktop": ["src/components/Files/FileManagerImageLightbox.tsx"],
|
|
"mobile": ["src/mobile/screens/trip/tabs/MFileLightbox.tsx"]
|
|
},
|
|
{
|
|
"feature": "Notifications list row actions",
|
|
"hooks": ["src/components/Notifications/useNotificationItemActions.ts"],
|
|
"desktop": ["src/components/Notifications/InAppNotificationItem.tsx"],
|
|
"mobile": ["src/mobile/screens/notifications/MNotificationRow.tsx"]
|
|
},
|
|
{
|
|
"feature": "Notifications page",
|
|
"hooks": ["src/pages/inAppNotifications/useInAppNotifications.ts"],
|
|
"desktop": ["src/pages/InAppNotificationsPage.tsx"],
|
|
"mobile": ["src/mobile/screens/notifications/MNotifications.tsx"]
|
|
},
|
|
{
|
|
"feature": "OAuth scope group picker",
|
|
"hooks": ["src/components/OAuth/useScopeSelection.ts"],
|
|
"desktop": ["src/components/OAuth/ScopeGroupPicker.tsx"],
|
|
"mobile": ["src/mobile/screens/settings/MScopeGroupPicker.tsx"]
|
|
},
|
|
{
|
|
"feature": "Packing bag card and bag weight summary",
|
|
"hooks": ["src/components/Packing/useBagCardEditor.ts"],
|
|
"desktop": ["src/components/Packing/PackingListPanelBagCard.tsx"],
|
|
"mobile": ["src/mobile/screens/trip/tabs/MBagsSheet.tsx"]
|
|
},
|
|
{
|
|
"feature": "Packing list: packingListModel",
|
|
"hooks": ["src/components/Packing/packingListModel.ts"],
|
|
"desktop": [
|
|
"src/components/Packing/packingPrintDocument.ts",
|
|
"src/components/Packing/usePackingExport.ts",
|
|
"src/components/Packing/usePackingListPanel.ts"
|
|
],
|
|
"mobile": [
|
|
"src/mobile/screens/trip/tabs/MBagsSheet.tsx",
|
|
"src/mobile/screens/trip/tabs/MPackItemSheet.tsx",
|
|
"src/mobile/screens/trip/tabs/MPackingListTab.tsx"
|
|
]
|
|
},
|
|
{
|
|
"feature": "Packing list: usePackingBags, usePackingCategoryAssignees, usePackingItemActions, usePackingTemplates",
|
|
"hooks": [
|
|
"src/components/Packing/usePackingBags.ts",
|
|
"src/components/Packing/usePackingCategoryAssignees.ts",
|
|
"src/components/Packing/usePackingItemActions.ts",
|
|
"src/components/Packing/usePackingTemplates.ts"
|
|
],
|
|
"desktop": ["src/components/Packing/usePackingListPanel.ts"],
|
|
"mobile": ["src/mobile/screens/trip/tabs/MPackingListTab.tsx"]
|
|
},
|
|
{
|
|
"feature": "Packing list: usePackingImport",
|
|
"hooks": ["src/components/Packing/usePackingImport.ts"],
|
|
"desktop": ["src/components/Packing/usePackingListPanel.ts"],
|
|
"mobile": ["src/mobile/screens/trip/tabs/MPackingImportSheet.tsx"]
|
|
},
|
|
{
|
|
"feature": "Packing template manager",
|
|
"hooks": ["src/components/Admin/usePackingTemplateAdmin.ts"],
|
|
"desktop": ["src/components/Admin/PackingTemplateManager.tsx"],
|
|
"mobile": ["src/mobile/screens/admin/MAdminPackingTemplateManager.tsx"]
|
|
},
|
|
{
|
|
"feature": "Per-leg travel mode and connector mode menu",
|
|
"hooks": ["src/components/Planner/useLegModeActions.ts"],
|
|
"desktop": ["src/components/Planner/DayPlanSidebar.tsx"],
|
|
"mobile": ["src/mobile/screens/trip/plan/MPlanTimeline.tsx", "src/mobile/screens/trip/plan/useMPlanTimeline.ts"]
|
|
},
|
|
{
|
|
"feature": "Permissions panel",
|
|
"hooks": ["src/components/Admin/usePermissionsAdmin.ts"],
|
|
"desktop": ["src/components/Admin/PermissionsPanel.tsx"],
|
|
"mobile": ["src/mobile/screens/admin/MAdminPermissionsPanel.tsx"]
|
|
},
|
|
{
|
|
"feature": "Place add/edit form and maps search: usePlaceForm",
|
|
"hooks": ["src/components/Planner/usePlaceForm.ts"],
|
|
"desktop": ["src/components/Planner/PlaceFormModal.tsx"],
|
|
"mobile": [
|
|
"src/mobile/screens/trip/sheets/MPlaceEditSheet.tsx",
|
|
"src/mobile/screens/trip/sheets/PlCategoryPicker.tsx"
|
|
]
|
|
},
|
|
{
|
|
"feature": "Place add/edit form and maps search: usePlaceSearch",
|
|
"hooks": ["src/components/Planner/usePlaceSearch.ts"],
|
|
"desktop": ["src/components/Planner/PlaceFormModal.tsx"],
|
|
"mobile": ["src/mobile/screens/trip/sheets/PlPlaceSearch.tsx"]
|
|
},
|
|
{
|
|
"feature": "Place detail actions",
|
|
"hooks": ["src/components/Planner/usePlaceActions.ts"],
|
|
"desktop": [
|
|
"src/components/Planner/PlaceInspector.tsx",
|
|
"src/pages/tripPlanner/useTripPlannerPage.ts"
|
|
],
|
|
"mobile": ["src/mobile/screens/trip/sheets/MPlaceSheet.tsx"]
|
|
},
|
|
{
|
|
"feature": "Places pool list",
|
|
"hooks": ["src/components/Planner/usePlacesPool.ts"],
|
|
"desktop": ["src/components/Planner/PlacesSidebarHeader.tsx", "src/components/Planner/usePlacesSidebar.ts"],
|
|
"mobile": [
|
|
"src/mobile/screens/trip/places/MPlacesBrowser.tsx",
|
|
"src/mobile/screens/trip/places/MPlacesFilterControls.tsx",
|
|
"src/mobile/screens/trip/places/MPlacesFilterSheet.tsx"
|
|
]
|
|
},
|
|
{
|
|
"feature": "Plugins admin",
|
|
"hooks": [
|
|
"src/components/Admin/plugins/pluginModel.ts",
|
|
"src/components/Admin/plugins/usePluginDetail.ts",
|
|
"src/components/Admin/plugins/usePluginsAdmin.ts"
|
|
],
|
|
"desktop": ["src/components/Admin/AdminPluginsPanel.tsx"],
|
|
"mobile": ["src/mobile/screens/admin/MAdminPluginsPanel.tsx"]
|
|
},
|
|
{
|
|
"feature": "Public transit for one leg, between two city walks from the first one's end, and a journey late for the next walk",
|
|
"hooks": ["src/components/Planner/useTransitLegPlanner.ts"],
|
|
"desktop": ["src/components/Planner/DayPlanSidebar.tsx"],
|
|
"mobile": ["src/mobile/screens/trip/plan/useMPlanTimeline.ts"]
|
|
},
|
|
{
|
|
"feature": "A tour's start and end in the day plan, its end worked out from its time, and an end that runs into the next timed item",
|
|
"hooks": ["src/components/Tours/tourDayTime.ts"],
|
|
"desktop": ["src/components/Planner/DayPlanSidebar.tsx"],
|
|
"mobile": ["src/mobile/screens/trip/plan/useMPlanTimeline.ts"]
|
|
},
|
|
{
|
|
"feature": "A multi-day tour put on a day: the whole tour there, or a stage a day from that day on",
|
|
"hooks": ["src/components/Tours/stages/stageSpread.ts"],
|
|
"desktop": ["src/components/Tours/stages/TourDayChoiceDialog.tsx", "src/components/Tours/stages/TourDayAddButton.tsx"],
|
|
"mobile": ["src/mobile/screens/trip/sheets/MTourDayChoiceSheet.tsx"]
|
|
},
|
|
{
|
|
"feature": "Reservation form incl. hotel accommodation creation",
|
|
"hooks": ["src/components/Planner/reservationFormModel.ts", "src/components/Planner/useReservationForm.ts"],
|
|
"desktop": ["src/components/Planner/ReservationModal.tsx"],
|
|
"mobile": ["src/mobile/screens/trip/sheets/MReservationSheet.tsx"]
|
|
},
|
|
{
|
|
"feature": "Road-trip add-stop draft",
|
|
"hooks": ["src/components/Roadtrip/useStopDraftForm.ts"],
|
|
"desktop": ["src/components/Roadtrip/RoadtripStopPopup.tsx"],
|
|
"mobile": ["src/mobile/screens/trip/roadtrip/MRtDraftSheet.tsx"]
|
|
},
|
|
{
|
|
"feature": "Road-trip stay length draft",
|
|
"hooks": ["src/components/Roadtrip/useStayDraft.ts"],
|
|
"desktop": ["src/components/Roadtrip/RoadtripStayModal.tsx"],
|
|
"mobile": ["src/mobile/screens/trip/roadtrip/MRtStaySheet.tsx"]
|
|
},
|
|
{
|
|
"feature": "Settings / Demo account locks",
|
|
"hooks": ["src/components/Demo/useDemoLock.ts"],
|
|
"desktop": [
|
|
"src/components/Settings/AccountDemoLock.tsx",
|
|
"src/components/Settings/DisplaySettingsTab.tsx",
|
|
"src/components/Settings/IntegrationsTab.tsx",
|
|
"src/components/Settings/ai/AiConnectionSection.tsx"
|
|
],
|
|
"mobile": [
|
|
"src/mobile/screens/settings/MAiConnectionSection.tsx",
|
|
"src/mobile/screens/settings/MSettingsGeneral.tsx",
|
|
"src/mobile/screens/settings/MSettingsMcp.tsx"
|
|
]
|
|
},
|
|
{
|
|
"feature": "Settings / Account",
|
|
"hooks": ["src/components/Settings/AccountDemoLock.tsx", "src/components/Settings/useAccountSettings.ts"],
|
|
"desktop": ["src/components/Settings/AccountTab.tsx"],
|
|
"mobile": ["src/mobile/screens/settings/MSettingsAccount.tsx"]
|
|
},
|
|
{
|
|
"feature": "Settings / Account / Native app server",
|
|
"hooks": ["src/components/Settings/useNativeServer.ts"],
|
|
"desktop": ["src/components/Settings/NativeServerSection.tsx"],
|
|
"mobile": ["src/mobile/screens/settings/MSettingsServer.tsx"]
|
|
},
|
|
{
|
|
"feature": "Settings / Account / Passkeys",
|
|
"hooks": ["src/components/Settings/usePasskeys.ts"],
|
|
"desktop": ["src/components/Settings/PasskeysSection.tsx"],
|
|
"mobile": ["src/mobile/screens/settings/MSettingsAccount.tsx"]
|
|
},
|
|
{
|
|
"feature": "Settings / Appearance",
|
|
"hooks": ["src/components/Settings/appearanceModel.ts", "src/components/Settings/useAppearanceEditor.ts"],
|
|
"desktop": ["src/components/Settings/AppearanceSettingsTab.tsx"],
|
|
"mobile": ["src/mobile/screens/settings/MSettingsAppearance.tsx"]
|
|
},
|
|
{
|
|
"feature": "Settings / General/Display",
|
|
"hooks": ["src/components/Settings/useSettingSaver.ts"],
|
|
"desktop": ["src/components/Settings/DisplaySettingsTab.tsx"],
|
|
"mobile": ["src/mobile/screens/settings/MSettingsGeneral.tsx"]
|
|
},
|
|
{
|
|
"feature": "Settings / Integrations / AI assistant",
|
|
"hooks": ["src/components/Settings/ai/useAiConnections.ts"],
|
|
"desktop": ["src/components/Settings/ai/AiConnectionSection.tsx"],
|
|
"mobile": ["src/mobile/screens/settings/MAiConnectionSection.tsx"]
|
|
},
|
|
{
|
|
"feature": "Settings / Integrations / AI parsing",
|
|
"hooks": ["src/components/Settings/useLlmConnection.ts"],
|
|
"desktop": ["src/components/Settings/LlmConnectionSection.tsx"],
|
|
"mobile": ["src/mobile/screens/settings/MLlmConnectionSection.tsx"]
|
|
},
|
|
{
|
|
"feature": "Settings / Integrations / AirTrail",
|
|
"hooks": ["src/components/Settings/useAirTrailSettings.ts"],
|
|
"desktop": ["src/components/Settings/AirTrailConnectionSection.tsx"],
|
|
"mobile": ["src/mobile/screens/settings/MAirTrailConnectionSection.tsx"]
|
|
},
|
|
{
|
|
"feature": "Settings / Integrations / MCP",
|
|
"hooks": ["src/components/Settings/useMcpIntegration.ts"],
|
|
"desktop": ["src/components/Settings/IntegrationsTab.tsx"],
|
|
"mobile": ["src/mobile/screens/settings/MSettingsMcp.tsx"]
|
|
},
|
|
{
|
|
"feature": "Settings / Integrations / Photo providers",
|
|
"hooks": ["src/components/Settings/usePhotoProviderConnections.ts"],
|
|
"desktop": ["src/components/Settings/PhotoProvidersSection.tsx"],
|
|
"mobile": ["src/mobile/screens/settings/MPhotoProvidersSection.tsx"]
|
|
},
|
|
{
|
|
"feature": "Settings / Map: mapSettingsModel",
|
|
"hooks": ["src/components/Settings/mapSettingsModel.ts"],
|
|
"desktop": ["src/components/Settings/MapSettingsTab.tsx"],
|
|
"mobile": ["src/mobile/screens/settings/MSettingsMap.tsx"]
|
|
},
|
|
{
|
|
"feature": "Settings / Map: useMapSettingsForm",
|
|
"hooks": ["src/components/Settings/useMapSettingsForm.ts"],
|
|
"desktop": ["src/components/Settings/MapSettingsTab.tsx"],
|
|
"mobile": ["src/mobile/screens/settings/MSettingsMap.tsx"]
|
|
},
|
|
{
|
|
"feature": "Settings / Notifications",
|
|
"hooks": ["src/components/Settings/useNotificationSettings.ts"],
|
|
"desktop": ["src/components/Settings/NotificationsTab.tsx"],
|
|
"mobile": ["src/mobile/screens/settings/MSettingsNotifications.tsx"]
|
|
},
|
|
{
|
|
"feature": "Settings / Plugins: usePluginActivity",
|
|
"hooks": ["src/components/Settings/usePluginActivity.ts"],
|
|
"desktop": ["src/components/Settings/PluginActivityPanel.tsx"],
|
|
"mobile": ["src/mobile/screens/settings/MSettingsPlugins.tsx"]
|
|
},
|
|
{
|
|
"feature": "Settings / Plugins: usePluginUserSettings",
|
|
"hooks": ["src/components/Plugins/usePluginUserSettings.ts"],
|
|
"desktop": ["src/components/Settings/PluginSettingsTab.tsx"],
|
|
"mobile": ["src/mobile/screens/settings/MSettingsPlugins.tsx"]
|
|
},
|
|
{
|
|
"feature": "Settings page",
|
|
"hooks": ["src/pages/settings/useSettings.ts"],
|
|
"desktop": ["src/pages/SettingsPage.tsx"],
|
|
"mobile": ["src/mobile/screens/settings/MSettings.tsx"]
|
|
},
|
|
{
|
|
"feature": "Settings shell: visible tabs + integrations gating",
|
|
"hooks": ["src/components/Settings/useIntegrationGates.ts"],
|
|
"desktop": ["src/components/Settings/IntegrationsTab.tsx"],
|
|
"mobile": ["src/mobile/screens/settings/MSettingsIntegrations.tsx"]
|
|
},
|
|
{
|
|
"feature": "Storage backends admin: useBackendForm",
|
|
"hooks": ["src/components/Admin/storage/useBackendForm.ts"],
|
|
"desktop": ["src/components/Admin/storage/BackendForm.tsx"],
|
|
"mobile": ["src/mobile/screens/admin/MAdminStoragePanel.tsx"]
|
|
},
|
|
{
|
|
"feature": "Storage backends admin: useStoragePanel",
|
|
"hooks": ["src/components/Admin/storage/useStoragePanel.ts"],
|
|
"desktop": ["src/components/Admin/storage/AdminStoragePanel.tsx"],
|
|
"mobile": ["src/mobile/screens/admin/MAdminStoragePanel.tsx"]
|
|
},
|
|
{
|
|
"feature": "To-do list and task add/edit form: useTaskForm",
|
|
"hooks": ["src/components/Todo/useTaskForm.ts"],
|
|
"desktop": ["src/components/Todo/TodoListPanel.tsx"],
|
|
"mobile": ["src/mobile/screens/trip/tabs/MTaskSheet.tsx"]
|
|
},
|
|
{
|
|
"feature": "To-do list and task add/edit form: useTodoList",
|
|
"hooks": ["src/components/Todo/useTodoList.ts"],
|
|
"desktop": ["src/components/Todo/TodoListPanel.tsx"],
|
|
"mobile": ["src/mobile/screens/trip/tabs/MTodoListTab.tsx"]
|
|
},
|
|
{
|
|
"feature": "Toast presenter queue",
|
|
"hooks": ["src/components/shared/useToastQueue.ts"],
|
|
"desktop": ["src/components/shared/Toast.tsx"],
|
|
"mobile": ["src/mobile/components/MToastHost.tsx"]
|
|
},
|
|
{
|
|
"feature": "Tours list filter",
|
|
"hooks": ["src/components/Tours/tourPresentation.ts"],
|
|
"desktop": [
|
|
"src/components/Tours/TourDetailDialog.tsx",
|
|
"src/components/Tours/planner/TourPlannerPanels.tsx",
|
|
"src/components/Tours/tourParts.tsx"
|
|
],
|
|
"mobile": ["src/mobile/screens/trip/places/MToursSelectionList.tsx"]
|
|
},
|
|
{
|
|
"feature": "Tours list facets",
|
|
"hooks": ["src/components/Tours/useTourListFilters.ts"],
|
|
"desktop": ["src/components/Tours/ToursSidebar.tsx"],
|
|
"mobile": ["src/mobile/screens/trip/places/MPlacesBrowser.tsx"]
|
|
},
|
|
{
|
|
"feature": "Transport booking detail view: reservationFiles",
|
|
"hooks": ["src/utils/reservationFiles.ts"],
|
|
"desktop": [
|
|
"src/components/Planner/DayPlanSidebarTransportDetailModal.tsx",
|
|
"src/components/Planner/ReservationsPanel.tsx",
|
|
"src/components/Planner/bookings/BookingDetailHost.tsx"
|
|
],
|
|
"mobile": [
|
|
"src/mobile/screens/trip/sheets/MTransportSheet.tsx",
|
|
"src/mobile/screens/trip/tabs/MBookingsTab.tsx",
|
|
"src/mobile/screens/trip/tabs/MTransportsTab.tsx"
|
|
]
|
|
},
|
|
{
|
|
"feature": "Transport booking detail view: transportDetailModel",
|
|
"hooks": ["src/components/Planner/transportDetailModel.ts"],
|
|
"desktop": ["src/components/Planner/DayPlanSidebarTransportDetailModal.tsx"],
|
|
"mobile": ["src/mobile/screens/trip/sheets/MTransportSheet.tsx"]
|
|
},
|
|
{
|
|
"feature": "Transport booking form: bookingFormModel",
|
|
"hooks": ["src/components/Planner/bookingFormModel.ts"],
|
|
"desktop": [
|
|
"src/components/Planner/ReservationModal.tsx",
|
|
"src/components/Planner/TransportModal.tsx",
|
|
"src/components/Planner/useBookingFileAttach.ts"
|
|
],
|
|
"mobile": [
|
|
"src/mobile/screens/trip/sheets/MReservationSheet.tsx",
|
|
"src/mobile/screens/trip/sheets/MTransportFormSheet.tsx"
|
|
]
|
|
},
|
|
{
|
|
"feature": "Transport booking form: transportEndpoints, useTransportForm",
|
|
"hooks": ["src/components/Planner/transportEndpoints.ts", "src/components/Planner/useTransportForm.ts"],
|
|
"desktop": ["src/components/Planner/TransportModal.tsx"],
|
|
"mobile": ["src/mobile/screens/trip/sheets/MTransportFormSheet.tsx"]
|
|
},
|
|
{
|
|
"feature": "Trip export",
|
|
"hooks": ["src/components/Planner/useTripExport.ts"],
|
|
"desktop": ["src/components/Planner/TripExportModal.tsx"],
|
|
"mobile": ["src/mobile/screens/trip/sheets/MExportSheet.tsx"]
|
|
},
|
|
{
|
|
"feature": "Trip files: fileActions",
|
|
"hooks": ["src/components/Files/fileActions.ts"],
|
|
"desktop": ["src/components/Files/FileManagerAssignModal.tsx", "src/components/Files/useFileManager.ts"],
|
|
"mobile": [
|
|
"src/mobile/screens/trip/tabs/MFileLinkSheet.tsx",
|
|
"src/mobile/screens/trip/tabs/MFileMenuSheet.tsx",
|
|
"src/mobile/screens/trip/tabs/MFilesTab.tsx"
|
|
]
|
|
},
|
|
{
|
|
"feature": "Trip files: fileListRules",
|
|
"hooks": ["src/components/Files/fileListRules.ts"],
|
|
"desktop": ["src/components/Files/FileManagerRow.tsx", "src/components/Files/useFileManager.ts"],
|
|
"mobile": ["src/mobile/screens/trip/tabs/MFileLinkSheet.tsx", "src/mobile/screens/trip/tabs/filesModel.ts"]
|
|
},
|
|
{
|
|
"feature": "Trip files: useFileTrash",
|
|
"hooks": ["src/components/Files/useFileTrash.ts"],
|
|
"desktop": ["src/components/Files/useFileManager.ts"],
|
|
"mobile": ["src/mobile/screens/trip/tabs/MFileTrashSheet.tsx"]
|
|
},
|
|
{
|
|
"feature": "Trip loading splash",
|
|
"hooks": ["src/components/shared/useTripSplashBeats.ts"],
|
|
"desktop": ["src/components/shared/TripLoadingSplash.tsx"],
|
|
"mobile": ["src/mobile/screens/trip/MTripLoadingSplash.tsx"]
|
|
},
|
|
{
|
|
"feature": "Trip planner page",
|
|
"hooks": ["src/pages/tripPlanner/useTripPlanner.ts"],
|
|
"desktop": ["src/pages/tripPlanner/useTripPlannerPage.ts"],
|
|
"mobile": ["src/mobile/screens/trip/MTripShell.tsx"]
|
|
},
|
|
{
|
|
"feature": "Trip sheet wiring: transportEditorOpeners",
|
|
"hooks": ["src/pages/tripPlanner/transportEditorOpeners.ts"],
|
|
"desktop": ["src/pages/TripPlannerPage.tsx", "src/pages/tripPlanner/usePlannerDialogs.ts"],
|
|
"mobile": ["src/mobile/screens/trip/sheets/MTripSheets.tsx"]
|
|
},
|
|
{
|
|
"feature": "Trip sheet wiring: tripCover, useBookingExpenseEditor",
|
|
"hooks": ["src/pages/tripPlanner/tripCover.ts", "src/pages/tripPlanner/useBookingExpenseEditor.ts"],
|
|
"desktop": ["src/pages/TripPlannerPage.tsx"],
|
|
"mobile": ["src/mobile/screens/trip/sheets/MTripSheets.tsx"]
|
|
},
|
|
{
|
|
"feature": "User modals/sheets",
|
|
"hooks": ["src/components/Admin/useAdminUserActions.ts"],
|
|
"desktop": ["src/pages/admin/AdminUserModals.tsx"],
|
|
"mobile": ["src/mobile/screens/admin/MAdminSheets.tsx"]
|
|
},
|
|
{
|
|
"feature": "Vacay calendar logging logic: useVacayCalendarLogic",
|
|
"hooks": ["src/components/Vacay/useVacayCalendarLogic.ts"],
|
|
"desktop": ["src/components/Vacay/VacayCalendar.tsx", "src/components/Vacay/VacayPersons.tsx"],
|
|
"mobile": ["src/mobile/screens/vacay/useMVacay.ts"]
|
|
},
|
|
{
|
|
"feature": "Vacay calendar logging logic: vacayFormat",
|
|
"hooks": ["src/components/Vacay/vacayFormat.ts"],
|
|
"desktop": ["src/components/Vacay/VacayStats.tsx"],
|
|
"mobile": ["src/mobile/screens/vacay/MVacay.tsx"]
|
|
},
|
|
{
|
|
"feature": "Vacay fusion invite",
|
|
"hooks": ["src/components/Vacay/useVacayUserPicker.ts"],
|
|
"desktop": ["src/components/Vacay/VacayPersons.tsx", "src/components/Vacay/VacaySharedCalendars.tsx"],
|
|
"mobile": ["src/mobile/screens/vacay/MVacayInviteSheet.tsx", "src/mobile/screens/vacay/MVacayShareSheet.tsx"]
|
|
},
|
|
{
|
|
"feature": "Vacay page",
|
|
"hooks": ["src/pages/vacay/useVacay.ts"],
|
|
"desktop": ["src/pages/VacayPage.tsx"],
|
|
"mobile": ["src/mobile/screens/vacay/useMVacay.ts"]
|
|
},
|
|
{
|
|
"feature": "Vacay read-only calendar sharing",
|
|
"hooks": ["src/components/Vacay/useVacayShareActions.ts"],
|
|
"desktop": ["src/components/Vacay/VacaySharedCalendars.tsx"],
|
|
"mobile": ["src/mobile/screens/vacay/MVacayShareSheet.tsx", "src/mobile/screens/vacay/useMVacay.ts"]
|
|
},
|
|
{
|
|
"feature": "Vacay settings",
|
|
"hooks": ["src/components/Vacay/useVacaySettings.ts"],
|
|
"desktop": ["src/components/Vacay/VacaySettings.tsx"],
|
|
"mobile": ["src/mobile/screens/vacay/MVacaySettingsSheet.tsx"]
|
|
},
|
|
{
|
|
"feature": "Paddle regions admin card",
|
|
"hooks": ["src/components/Admin/paddle/usePaddleRegionsAdmin.ts", "src/components/Admin/paddle/paddleRegionsModel.ts"],
|
|
"desktop": ["src/components/Admin/paddle/PaddleRegionsPanel.tsx"],
|
|
"mobile": ["src/mobile/screens/admin/MAdminPaddleRegionsPanel.tsx"]
|
|
},
|
|
{
|
|
"feature": "School holiday catalog admin card",
|
|
"hooks": ["src/components/Admin/useSchoolHolidayCatalog.ts"],
|
|
"desktop": ["src/components/Admin/SchoolHolidayCatalog.tsx"],
|
|
"mobile": ["src/mobile/screens/admin/MAdminSchoolHolidayCatalog.tsx"]
|
|
},
|
|
{
|
|
"feature": "Trip settings: members, guests, public and invite link",
|
|
"hooks": ["src/components/Trips/useTripShare.ts"],
|
|
"desktop": ["src/components/Trips/TripShareDialog.tsx"],
|
|
"mobile": ["src/mobile/screens/trip/sheets/MTripSettingsSheet.tsx"]
|
|
}
|
|
],
|
|
"mobileOnly": {
|
|
"src/mobile/screens/admin/MAdminOidcCard.tsx": "Markup only; the OIDC card of MAdminSettingsSection, with the form state from useAdmin and the save from its useAdminSettingsActions handed in through props.",
|
|
"src/mobile/screens/admin/MAdminResetMfaSheet.tsx": "Markup only; the 2FA reset confirm that MAdminSheets opens, with the reset handed in through props from its useAdminUserActions.",
|
|
"src/mobile/screens/admin/MAdminUi.tsx": "Phone only admin UI primitives (button, card, field, input, secret input, sheet frame).",
|
|
"src/mobile/screens/admin/MPluginVersionDate.tsx": "Markup only; the published date of a plugin version in MAdminPluginsPanel, formatted with the user's date format through useFormatDate.",
|
|
"src/mobile/screens/admin/MStorageReclaimCard.tsx": "Markup only; renders the reclaim view and handlers that MAdminStoragePanel takes from useStoragePanel, the twin of StorageReclaimSection.",
|
|
"src/mobile/screens/atlas/MAtlasSearch.tsx": "Phone full screen country search overlay; options, suggestions and selection come through props from MAtlas.",
|
|
"src/mobile/screens/atlas/MAtlasStatsCard.tsx": "Markup only; renders the AtlasStats that MAtlas passes in.",
|
|
"src/mobile/screens/collections/MCollCategoryPicker.tsx": "Phone only category dropdown; value and categories come through props from the collection sheets.",
|
|
"src/mobile/screens/collections/MCollInvites.tsx": "Markup only; the invites and accept and decline come through props from useCollections via MCollections.",
|
|
"src/mobile/screens/collections/MCollLabelsSheet.tsx": "Phone label sheet; create, update, delete and assign come through props from useCollections.",
|
|
"src/mobile/screens/collections/MCollLinksEditor.tsx": "Markup only; link rows and the change handler come through props from the collection sheets.",
|
|
"src/mobile/screens/collections/MCollListPickerSheet.tsx": "Phone list picker sheet; the move or copy action comes through onPick from useCollections.",
|
|
"src/mobile/screens/collections/MCollSheetKit.tsx": "Phone only sheet UI primitives for the collections screens (header, footer, pill, eyebrow).",
|
|
"src/mobile/screens/collections/collectionsMobileModel.ts": "Visual constants only the phone collections screens use (category and status specs, swatches, cover gradient).",
|
|
"src/mobile/screens/dashboard/MUserMenu.tsx": "Phone avatar menu with a three state theme cycle the desktop navbar does not have.",
|
|
"src/mobile/screens/journey/MDawarichDaySheet.tsx": "Markup only; the phone frame the Dawarich day sheets (route and stays) render their shared review in.",
|
|
"src/mobile/screens/settings/MConfirmSheet.tsx": "Phone only bottom sheet confirm dialog used across the mobile screens.",
|
|
"src/mobile/screens/settings/MDawarichConnectionSection.tsx": "Already shares hooks/useDawarichConnection with components/Settings/DawarichConnectionSection.tsx.",
|
|
"src/mobile/screens/settings/MMobileDashOrder.tsx": "Phone only setting that orders the mobile dashboard blocks; the desktop has no such setting.",
|
|
"src/mobile/screens/settings/MMobileNavCustomizer.tsx": "Phone only editor for the mobile bottom nav, built on components/Settings/useMobileNavEditor.",
|
|
"src/mobile/screens/settings/MSetPickerSheet.tsx": "Phone only option picker bottom sheet, a generic UI primitive.",
|
|
"src/mobile/screens/settings/MSettingsAbout.tsx": "Markup only about card with static links and no state.",
|
|
"src/mobile/screens/settings/MSettingsOffline.tsx": "Already shares components/Settings/useOfflineSettings with components/Settings/OfflineTab.tsx.",
|
|
"src/mobile/screens/settings/MSettingsUi.tsx": "Phone only settings UI primitives (card, row, input, button, segments, hint).",
|
|
"src/mobile/screens/settings/MWebPushCard.tsx": "Already shares hooks/useWebPush with components/Settings/WebPushCard.tsx.",
|
|
"src/mobile/screens/trip/dockTabs.ts": "Phone only helper that picks which trip tabs get a seat in the mobile dock.",
|
|
"src/mobile/screens/trip/lib/dayNotes.ts": "Phone only helper that splits a leading time off a day note for the plan timeline.",
|
|
"src/mobile/screens/trip/map/MMapArea.tsx": "Phone map stage framing; already shares usePoiExplore and useMergedMapPois with the desktop trip planner.",
|
|
"src/mobile/screens/trip/map/MPlacesFilterPill.tsx": "Phone only map control for the active places filter count, built on the shared MapTogglePill.",
|
|
"src/mobile/screens/trip/places/MPlacesBulkCategorySheet.tsx": "Markup only; categories and the pick handler come through props from MPlacesBrowser.",
|
|
"src/mobile/screens/trip/places/MPlacesToursModeSwitch.tsx": "Markup only places or tours toggle; value and onChange come through props from MPlacesBrowser.",
|
|
"src/mobile/screens/trip/places/placesBrowserModel.ts": "Phone pool helpers over the shared utils/placesFilter, placeSearch and plannedPlaces.",
|
|
"src/mobile/screens/trip/plan/MPlanTimelineRows.tsx": "Markup only timeline rows; row data comes from MPlanTimeline and planTimelineModel.",
|
|
"src/mobile/screens/trip/plan/planTimelineModel.ts": "Phone plan timeline row builder over the shared utils/dayMerge, dayOrder and dayTourProjection.",
|
|
"src/mobile/screens/trip/plan/useMPlanDaySwipe.ts": "Phone only touch swipe gesture for switching days.",
|
|
"src/mobile/screens/trip/plan/useMPlanDragReorder.ts": "Phone only long press drag gesture; the reorder itself runs through the handler it is given.",
|
|
"src/mobile/screens/trip/roadtrip/MRoadtripRows.tsx": "Markup only road trip rows over the shared Roadtrip models the desktop sidebar rows also use.",
|
|
"src/mobile/screens/trip/roadtrip/MRoadtripTab.tsx": "Phone road trip tab over the shared roadtripRowModel, stopBookings and nightBookend RoadtripSidebar uses.",
|
|
"src/mobile/screens/trip/roadtrip/MRtAlternativesBar.tsx": "Markup only; state from useMRtAlternatives, text from the shared alternativeOverlays.",
|
|
"src/mobile/screens/trip/roadtrip/MRtCorridorBar.tsx": "Markup only; its corridor state comes through props from useMRtCorridor.",
|
|
"src/mobile/screens/trip/roadtrip/MRtCorridorSheet.tsx": "Phone corridor search sheet over useMRtCorridor and the planner's shared corridor state.",
|
|
"src/mobile/screens/trip/roadtrip/MRtInfoSheet.tsx": "Read only figures sheet that already shares useHotelBookends, dayWindow and parseAvoid with RoadtripLimitsCard.",
|
|
"src/mobile/screens/trip/roadtrip/MRtKindSheet.tsx": "Thin sheet over planner.setRoadtripStopKind that already shares STOP_KINDS with StopKindPicker.",
|
|
"src/mobile/screens/trip/roadtrip/MRtStopSheet.tsx": "Phone only stop detail sheet over the shared roadtripRowModel, stayReading and planner writers.",
|
|
"src/mobile/screens/trip/roadtrip/stageBadges.ts": "Badge helpers for the phone stage header and alternatives bar, which have no desktop counterpart.",
|
|
"src/mobile/screens/trip/roadtrip/useMRoadtrip.ts": "Phone stage screen adapter over the shared roadtripRowModel plus a live clock tick.",
|
|
"src/mobile/screens/trip/roadtrip/useMRtAlternatives.ts": "Tap to preview, confirm to write layer over the planner's shared route alternatives.",
|
|
"src/mobile/screens/trip/roadtrip/useMRtCorridor.ts": "Phone reach and anchor layer over the planner's shared corridor state.",
|
|
"src/mobile/screens/trip/sheets/MBookingFields.tsx": "Markup only: the booking code, notes, traveler and route stop fields both phone booking sheets draw.",
|
|
"src/mobile/screens/trip/sheets/MBookingFilesCosts.tsx": "Phone booking sheet footer that composes PlFileAttach and MLinkedCosts.",
|
|
"src/mobile/screens/trip/sheets/MBrowseActionsSheet.tsx": "Phone action sheet for a pool place that calls planner handlers and the shared placeToSaveTarget.",
|
|
"src/mobile/screens/trip/sheets/MDaysSheet.tsx": "Button based day reorder sheet over planner.handleReorderDays; the desktop reorders by drag.",
|
|
"src/mobile/screens/trip/sheets/MLinkedCosts.tsx": "Already shares useExpenseLinks with the desktop BookingCostsSection; only markup and a search filter are local.",
|
|
"src/mobile/screens/trip/sheets/MTripSheetUi.tsx": "Phone sheet UI primitives (eyebrow, headers, stat boxes, action circles) and a time display helper.",
|
|
"src/mobile/screens/trip/sheets/PlFileAttach.tsx": "Markup only; pending files and link actions come through props from the phone form sheets.",
|
|
"src/mobile/screens/trip/sheets/PlSheetChrome.tsx": "Phone form sheet chrome primitives (header, footer, field classes).",
|
|
"src/mobile/screens/trip/sheets/PlTimeFields.tsx": "Phone time fields that already share timeCollisions with the desktop PlaceFormModal.",
|
|
"src/mobile/screens/trip/tabs/MCollabTab.tsx": "Phone collab sub tab router that reuses the desktop CollabLinks component.",
|
|
"src/mobile/screens/trip/tabs/MListsTab.tsx": "Phone router between the packing and to-do bodies, with no logic of its own.",
|
|
"src/mobile/screens/trip/tabs/MReceiptScanButton.tsx": "Already shares useReceiptScan and ReceiptScanModal with the desktop CostsPanel.",
|
|
"src/mobile/screens/trip/tabs/MReservationCardParts.tsx": "Markup only: the title, actions, date, files and delete sheet parts both phone booking tabs draw.",
|
|
"src/mobile/screens/trip/tabs/MTripTabPanel.tsx": "Phone tab router that mounts the per tab screens and plugin frames, with no logic of its own.",
|
|
"src/mobile/screens/trip/tabs/listsModel.ts": "Priority colour and label constants only the phone to-do list and task sheet use.",
|
|
"src/mobile/screens/trip/tabs/tabChrome.tsx": "Phone tab chrome primitives (scroller, section headers, fields, traveler chips, plugin slots).",
|
|
"src/mobile/screens/trip/tabs/tabModel.ts": "Phone tab prop type and status colour tokens only the phone tabs use.",
|
|
"src/mobile/screens/trip/tabs/transportsModel.ts": "Phone transport card readers (metadata, day and time cells) for MTransportsTab and MBookingsTab.",
|
|
"src/mobile/screens/vacay/MVacayMonth.tsx": "Markup only; its day cell colours come from the phone vacayDayModel.",
|
|
"src/mobile/screens/vacay/vacayDayModel.ts": "Phone day cell colour model for MVacayMonth; the desktop card styles its cells inline."
|
|
}
|
|
}
|