+
+ );
+}
diff --git a/client/src/components/Planner/BookingImportModal.tsx b/client/src/components/Planner/BookingImportModal.tsx
index aa84b9eef..8955e12ce 100644
--- a/client/src/components/Planner/BookingImportModal.tsx
+++ b/client/src/components/Planner/BookingImportModal.tsx
@@ -1,4 +1,5 @@
import { createPortal } from 'react-dom'
+import { useSharedImportStore } from '../../native/sharedFiles'
import { useState, useRef, useEffect } from 'react'
import { Upload, X } from 'lucide-react'
import { useTranslation } from '../../i18n'
@@ -35,6 +36,12 @@ export default function BookingImportModal({ isOpen, onClose, tripId, kind }: Bo
const mouseDownTarget = useRef(null)
const [files, setFiles] = useState([])
+ // A booking document shared to TREK lands here already chosen.
+ useEffect(() => {
+ if (!isOpen) return
+ const shared = useSharedImportStore.getState().file
+ if (shared) setFiles([useSharedImportStore.getState().take() ?? shared])
+ }, [isOpen])
const [isDragOver, setIsDragOver] = useState(false)
const [loading, setLoading] = useState(false)
const [error, setError] = useState('')
diff --git a/client/src/mobile/screens/trip/MTripShell.tsx b/client/src/mobile/screens/trip/MTripShell.tsx
index cc69e8551..95526dd92 100644
--- a/client/src/mobile/screens/trip/MTripShell.tsx
+++ b/client/src/mobile/screens/trip/MTripShell.tsx
@@ -9,6 +9,7 @@ import { pickDockTabs } from './dockTabs'
import MBadge from '../../components/MBadge'
import MIconBtn from '../../components/MIconBtn'
import { useActivePill } from '../../components/useActivePill'
+import { useSharedImportStore } from '../../../native/sharedFiles'
import MPlanTimeline from './plan/MPlanTimeline'
import MMapArea from './map/MMapArea'
import MPlacesBrowser from './places/MPlacesBrowser'
@@ -291,6 +292,14 @@ export default function MTripShell({
})
}, [planner.selectedDayId, days, dayRail])
// The active day's pill glides to the next chip rather than jumping there.
+ // A booking document shared to TREK, and this trip picked for it: open the import.
+ const sharedTripId = useSharedImportStore(s => s.tripId)
+ useEffect(() => {
+ if (sharedTripId == null || sharedTripId !== Number(tripId)) return
+ planner.setBookingImportKind('bookings')
+ planner.setShowBookingImport(true)
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [sharedTripId, tripId])
const dayPill = useActivePill(dayRail, '[aria-current="true"]', [planner.selectedDayId, days, dayRail, language])
const trTab = planner.activeTab
diff --git a/client/src/native/nativeApp.test.ts b/client/src/native/nativeApp.test.ts
index ba0cae970..f85b54f9d 100644
--- a/client/src/native/nativeApp.test.ts
+++ b/client/src/native/nativeApp.test.ts
@@ -23,6 +23,7 @@ vi.mock('./capabilities', () => ({
loadNativeCapabilities: vi.fn(async () => ({})),
}));
vi.mock('./geolocation', () => ({ installNativeGeolocation: vi.fn() }));
+vi.mock('./sharedFiles', () => ({ startSharedFiles: vi.fn(async () => {}) }));
vi.mock('../mobile/overlayStack', () => ({ closeTopOverlay: vi.fn(() => false) }));
function backButtonHandler(): (event: { canGoBack: boolean }) => void {
diff --git a/client/src/native/nativeApp.ts b/client/src/native/nativeApp.ts
index efe7feff8..091d439bf 100644
--- a/client/src/native/nativeApp.ts
+++ b/client/src/native/nativeApp.ts
@@ -9,6 +9,7 @@ import { installNativeGeolocation } from './geolocation';
import { keepOfflineShellFresh } from './offlineShell';
import { isNativeApp, isNativeIos } from './platform';
import { reportNativeFailure } from './reportFailure';
+import { startSharedFiles } from './sharedFiles';
import { isUnimplemented } from './trekShell';
/** Long enough that the warm-up never competes with the first screen's requests. */
@@ -27,6 +28,8 @@ export function startNativeApp(): void {
void checkAppUpdate(fetchServerFeatures);
// The app's own location under navigator.geolocation, where the binary has it.
void loadNativeCapabilities().then(() => installNativeGeolocation());
+ // Booking documents shared to TREK, waiting for a trip to import into.
+ void startSharedFiles();
// A tap on the status bar scrolls the list under it back to the top, as in
// every iOS app (the status-bar plugin fires statusTap on iOS).
diff --git a/client/src/native/sharedFiles.test.ts b/client/src/native/sharedFiles.test.ts
new file mode 100644
index 000000000..e7b41566d
--- /dev/null
+++ b/client/src/native/sharedFiles.test.ts
@@ -0,0 +1,53 @@
+import { beforeEach, describe, expect, it, vi } from 'vitest';
+import { hasNativeFeature } from './capabilities';
+import { startSharedFiles, toFile, useSharedImportStore } from './sharedFiles';
+import { TrekShell } from './trekShell';
+
+vi.mock('./capabilities', () => ({ hasNativeFeature: vi.fn(), loadNativeCapabilities: vi.fn(async () => ({})) }));
+vi.mock('./trekShell', () => ({
+ TrekShell: { addListener: vi.fn(async () => ({ remove: async () => {} })), takeSharedFile: vi.fn() },
+ isUnimplemented: () => false,
+}));
+
+const PDF = { name: 'booking.pdf', mimeType: 'application/pdf', data: btoa('%PDF-1.4 hello') };
+
+beforeEach(() => {
+ useSharedImportStore.setState({ file: null, tripId: null });
+ vi.mocked(hasNativeFeature).mockReturnValue(true);
+ vi.mocked(TrekShell.takeSharedFile).mockReset().mockResolvedValue({ file: null });
+});
+
+describe('shared booking documents', () => {
+ it('turns the base64 the native side sends into a File', async () => {
+ const file = toFile(PDF);
+ expect(file.name).toBe('booking.pdf');
+ expect(file.type).toBe('application/pdf');
+ expect(await file.text()).toBe('%PDF-1.4 hello');
+ });
+
+ it('picks up a document shared before the UI ran, and the next ones as they come', async () => {
+ vi.mocked(TrekShell.takeSharedFile).mockResolvedValue({ file: PDF });
+ await startSharedFiles();
+ expect(useSharedImportStore.getState().file?.name).toBe('booking.pdf');
+
+ const listener = vi.mocked(TrekShell.addListener).mock.calls[0][1] as (p: typeof PDF) => void;
+ listener({ ...PDF, name: 'train.ics', mimeType: 'text/calendar' });
+ expect(useSharedImportStore.getState().file?.name).toBe('train.ics');
+ });
+
+ it('hands the file over once a trip is picked, and empties the queue', () => {
+ useSharedImportStore.getState().setFile(toFile(PDF));
+ useSharedImportStore.getState().chooseTrip(7);
+ expect(useSharedImportStore.getState().tripId).toBe(7);
+ expect(useSharedImportStore.getState().take()?.name).toBe('booking.pdf');
+ expect(useSharedImportStore.getState()).toMatchObject({ file: null, tripId: null });
+ });
+
+ it('does nothing in a binary without the feature', async () => {
+ vi.mocked(hasNativeFeature).mockReturnValue(false);
+ vi.mocked(TrekShell.addListener).mockClear();
+ await startSharedFiles();
+ expect(TrekShell.addListener).not.toHaveBeenCalled();
+ expect(TrekShell.takeSharedFile).not.toHaveBeenCalled();
+ });
+});
diff --git a/client/src/native/sharedFiles.ts b/client/src/native/sharedFiles.ts
new file mode 100644
index 000000000..830b9c00f
--- /dev/null
+++ b/client/src/native/sharedFiles.ts
@@ -0,0 +1,55 @@
+import { create } from 'zustand';
+import { hasNativeFeature, loadNativeCapabilities } from './capabilities';
+import { reportNativeFailure } from './reportFailure';
+import { TrekShell, isUnimplemented, type SharedFilePayload } from './trekShell';
+
+/**
+ * Booking documents shared to TREK ("Open in TREK" on a PDF, a calendar entry,
+ * a Wallet pass or a mail). The native side hands them over as base64
+ * (TrekShell.takeSharedFile and the sharedFile event); here they become a File
+ * waiting for a trip: NativeImportSheet asks which one, and the trip's booking
+ * import opens with the file already chosen (BookingImportModal).
+ */
+interface SharedImportState {
+ file: File | null;
+ /** The trip the user picked for it; the planner of that trip takes it from here. */
+ tripId: number | null;
+ setFile: (file: File | null) => void;
+ chooseTrip: (tripId: number) => void;
+ /** The booking import took the file: the queue is empty again. */
+ take: () => File | null;
+}
+
+export const useSharedImportStore = create((set, get) => ({
+ file: null,
+ tripId: null,
+ setFile: (file) => set({ file, tripId: null }),
+ chooseTrip: (tripId) => set({ tripId }),
+ take: () => {
+ const { file } = get();
+ set({ file: null, tripId: null });
+ return file;
+ },
+}));
+
+export function toFile(payload: SharedFilePayload): File {
+ const binary = atob(payload.data);
+ const bytes = new Uint8Array(binary.length);
+ for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
+ return new File([bytes], payload.name || 'booking', { type: payload.mimeType || 'application/octet-stream' });
+}
+
+/** Picks up a document shared before the UI ran, and listens for the next ones. */
+export async function startSharedFiles(): Promise {
+ await loadNativeCapabilities();
+ if (!hasNativeFeature('sharedFiles')) return;
+ const accept = (payload: SharedFilePayload | null) => {
+ if (payload?.data) useSharedImportStore.getState().setFile(toFile(payload));
+ };
+ void TrekShell.addListener('sharedFile', accept);
+ try {
+ accept((await TrekShell.takeSharedFile()).file);
+ } catch (err) {
+ if (!isUnimplemented(err)) reportNativeFailure(err);
+ }
+}
diff --git a/client/src/native/trekShell.ts b/client/src/native/trekShell.ts
index afe9c0ad9..097323b60 100644
--- a/client/src/native/trekShell.ts
+++ b/client/src/native/trekShell.ts
@@ -49,6 +49,20 @@ export interface TrekShellPlugin {
event: 'location',
listener: (payload: NativeLocationPayload) => void
): Promise<{ remove: () => Promise }>;
+ addListener(
+ event: 'sharedFile',
+ listener: (payload: SharedFilePayload) => void
+ ): Promise<{ remove: () => Promise }>;
+ /** Feature sharedFiles: the booking document shared to TREK before the UI ran. */
+ takeSharedFile(): Promise<{ file: SharedFilePayload | null }>;
+}
+
+/** A document shared to TREK, as the native side reads it. */
+export interface SharedFilePayload {
+ name: string;
+ mimeType: string;
+ /** base64 */
+ data: string;
}
/** A position, or an error shaped like GeolocationPositionError (1 denied, 2 unavailable). */
diff --git a/shared/src/i18n/ar/native.ts b/shared/src/i18n/ar/native.ts
index f445c5288..0ded8f83f 100644
--- a/shared/src/i18n/ar/native.ts
+++ b/shared/src/i18n/ar/native.ts
@@ -80,6 +80,8 @@ const native: TranslationStrings = {
'native.lock.settingTitle': 'قفل التطبيق',
'native.lock.setting': 'القفل باستخدام Face ID أو رمز المرور',
'native.lock.settingHint': 'يطلب ذلك عند فتح TREK وبعد نصف دقيقة في الخلفية، ويخفي التطبيق في مبدّل التطبيقات.',
+ 'native.share.title': 'الاستيراد إلى أي رحلة؟',
+ 'native.share.noTrips': 'لا توجد رحلة بعد. أنشئ رحلة أولًا ثم شارك المستند مجددًا.',
};
export default native;
diff --git a/shared/src/i18n/az/native.ts b/shared/src/i18n/az/native.ts
index aeba3db30..1c5b8b7f5 100644
--- a/shared/src/i18n/az/native.ts
+++ b/shared/src/i18n/az/native.ts
@@ -82,6 +82,8 @@ const native: TranslationStrings = {
'native.lock.setting': 'Face ID və ya kodla kilidlə',
'native.lock.settingHint':
'TREK açılanda və arxa fonda yarım dəqiqədən sonra soruşur, tətbiqi tətbiq dəyişdiricisində gizlədir.',
+ 'native.share.title': 'Hansı səyahətə idxal edilsin?',
+ 'native.share.noTrips': 'Hələ səyahət yoxdur. Əvvəlcə birini yaradın, sonra sənədi yenidən paylaşın.',
};
export default native;
diff --git a/shared/src/i18n/br/native.ts b/shared/src/i18n/br/native.ts
index 6005fb0b4..7a540640d 100644
--- a/shared/src/i18n/br/native.ts
+++ b/shared/src/i18n/br/native.ts
@@ -82,6 +82,8 @@ const native: TranslationStrings = {
'native.lock.setting': 'Bloquear com Face ID ou código',
'native.lock.settingHint':
'Pede ao abrir o TREK e após meio minuto em segundo plano, e oculta o app no seletor de apps.',
+ 'native.share.title': 'Importar para qual viagem?',
+ 'native.share.noTrips': 'Ainda não há viagens. Crie uma primeiro e compartilhe o documento de novo.',
};
export default native;
diff --git a/shared/src/i18n/ca/native.ts b/shared/src/i18n/ca/native.ts
index 6f7420077..c007e6386 100644
--- a/shared/src/i18n/ca/native.ts
+++ b/shared/src/i18n/ca/native.ts
@@ -82,6 +82,8 @@ const native: TranslationStrings = {
'native.lock.setting': 'Bloqueja amb Face ID o codi',
'native.lock.settingHint':
'Ho demana en obrir TREK i després de mig minut en segon pla, i amaga l’app al selector d’apps.',
+ 'native.share.title': 'A quin viatge vols importar-ho?',
+ 'native.share.noTrips': 'Encara no hi ha cap viatge. Crea’n un i torna a compartir el document.',
};
export default native;
diff --git a/shared/src/i18n/cs/native.ts b/shared/src/i18n/cs/native.ts
index b063a899f..73fba6fa8 100644
--- a/shared/src/i18n/cs/native.ts
+++ b/shared/src/i18n/cs/native.ts
@@ -82,6 +82,8 @@ const native: TranslationStrings = {
'native.lock.setting': 'Zamknout pomocí Face ID nebo kódu',
'native.lock.settingHint':
'Zeptá se při otevření TREK a po půl minutě na pozadí a skryje aplikaci v přepínači aplikací.',
+ 'native.share.title': 'Importovat do které cesty?',
+ 'native.share.noTrips': 'Zatím žádná cesta. Nejdřív nějakou vytvořte a pak dokument sdílejte znovu.',
};
export default native;
diff --git a/shared/src/i18n/de/native.ts b/shared/src/i18n/de/native.ts
index 4aac52592..39444941e 100644
--- a/shared/src/i18n/de/native.ts
+++ b/shared/src/i18n/de/native.ts
@@ -83,6 +83,8 @@ const native: TranslationStrings = {
'native.lock.setting': 'Mit Face ID oder Code sperren',
'native.lock.settingHint':
'Fragt beim Öffnen und nach einer halben Minute im Hintergrund nach und verbirgt TREK im App-Umschalter.',
+ 'native.share.title': 'In welchen Trip importieren?',
+ 'native.share.noTrips': 'Noch kein Trip. Lege zuerst einen an und teile das Dokument dann erneut.',
};
export default native;
diff --git a/shared/src/i18n/en/native.ts b/shared/src/i18n/en/native.ts
index 31f603099..35b668677 100644
--- a/shared/src/i18n/en/native.ts
+++ b/shared/src/i18n/en/native.ts
@@ -82,6 +82,8 @@ const native: TranslationStrings = {
'native.lock.setting': 'Lock with Face ID or passcode',
'native.lock.settingHint':
'Asks when TREK opens and after half a minute in the background, and hides the app in the app switcher.',
+ 'native.share.title': 'Import into which trip?',
+ 'native.share.noTrips': 'No trip yet. Create one first, then share the document again.',
};
export default native;
diff --git a/shared/src/i18n/es/native.ts b/shared/src/i18n/es/native.ts
index 4279a01f8..d54810e8a 100644
--- a/shared/src/i18n/es/native.ts
+++ b/shared/src/i18n/es/native.ts
@@ -83,6 +83,8 @@ const native: TranslationStrings = {
'native.lock.setting': 'Bloquear con Face ID o código',
'native.lock.settingHint':
'Lo pide al abrir TREK y tras medio minuto en segundo plano, y oculta la app en el selector de apps.',
+ 'native.share.title': '¿En qué viaje importar?',
+ 'native.share.noTrips': 'Aún no hay viajes. Crea uno primero y vuelve a compartir el documento.',
};
export default native;
diff --git a/shared/src/i18n/et/native.ts b/shared/src/i18n/et/native.ts
index 39facd3c5..98ecfb60b 100644
--- a/shared/src/i18n/et/native.ts
+++ b/shared/src/i18n/et/native.ts
@@ -82,6 +82,8 @@ const native: TranslationStrings = {
'native.lock.setting': 'Lukusta Face ID või pääsukoodiga',
'native.lock.settingHint':
'Küsib TREK-i avamisel ja pärast poolt minutit taustal ning peidab rakenduse rakenduste vahetajas.',
+ 'native.share.title': 'Millisesse reisi importida?',
+ 'native.share.noTrips': 'Reise veel pole. Loo esmalt üks ja jaga dokumenti uuesti.',
};
export default native;
diff --git a/shared/src/i18n/fr/native.ts b/shared/src/i18n/fr/native.ts
index 5329ee437..4a4fd48d7 100644
--- a/shared/src/i18n/fr/native.ts
+++ b/shared/src/i18n/fr/native.ts
@@ -83,6 +83,8 @@ const native: TranslationStrings = {
'native.lock.setting': 'Verrouiller avec Face ID ou code',
'native.lock.settingHint':
'Le demande à l’ouverture de TREK et après une demi-minute en arrière-plan, et masque l’app dans le sélecteur d’apps.',
+ 'native.share.title': 'Importer dans quel voyage ?',
+ 'native.share.noTrips': 'Pas encore de voyage. Créez-en un, puis partagez à nouveau le document.',
};
export default native;
diff --git a/shared/src/i18n/gr/native.ts b/shared/src/i18n/gr/native.ts
index 312b9dbbb..f666f08ee 100644
--- a/shared/src/i18n/gr/native.ts
+++ b/shared/src/i18n/gr/native.ts
@@ -85,6 +85,8 @@ const native: TranslationStrings = {
'native.lock.setting': 'Κλείδωμα με Face ID ή κωδικό',
'native.lock.settingHint':
'Ζητείται κατά το άνοιγμα του TREK και μετά από μισό λεπτό στο παρασκήνιο, και η εφαρμογή κρύβεται στην εναλλαγή εφαρμογών.',
+ 'native.share.title': 'Εισαγωγή σε ποιο ταξίδι;',
+ 'native.share.noTrips': 'Δεν υπάρχει ακόμα ταξίδι. Δημιουργήστε ένα πρώτα και κοινοποιήστε ξανά το έγγραφο.',
};
export default native;
diff --git a/shared/src/i18n/he/native.ts b/shared/src/i18n/he/native.ts
index e201b220d..da74576c8 100644
--- a/shared/src/i18n/he/native.ts
+++ b/shared/src/i18n/he/native.ts
@@ -80,6 +80,8 @@ const native: TranslationStrings = {
'native.lock.settingTitle': 'נעילת אפליקציה',
'native.lock.setting': 'נעילה עם Face ID או קוד',
'native.lock.settingHint': 'מבקש בעת פתיחת TREK ואחרי חצי דקה ברקע, ומסתיר את האפליקציה במחליף האפליקציות.',
+ 'native.share.title': 'לייבא לאיזה טיול?',
+ 'native.share.noTrips': 'אין עדיין טיול. צרו טיול ואז שתפו את המסמך שוב.',
};
export default native;
diff --git a/shared/src/i18n/hu/native.ts b/shared/src/i18n/hu/native.ts
index 29dec6f7e..194b29540 100644
--- a/shared/src/i18n/hu/native.ts
+++ b/shared/src/i18n/hu/native.ts
@@ -84,6 +84,8 @@ const native: TranslationStrings = {
'native.lock.setting': 'Zárolás Face ID-val vagy kóddal',
'native.lock.settingHint':
'Rákérdez a TREK megnyitásakor és fél perc háttérben töltött idő után, és elrejti az alkalmazást az alkalmazásváltóban.',
+ 'native.share.title': 'Melyik utazásba importáljuk?',
+ 'native.share.noTrips': 'Még nincs utazás. Előbb hozz létre egyet, aztán oszd meg újra a dokumentumot.',
};
export default native;
diff --git a/shared/src/i18n/id/native.ts b/shared/src/i18n/id/native.ts
index 8df8c449d..47e658e33 100644
--- a/shared/src/i18n/id/native.ts
+++ b/shared/src/i18n/id/native.ts
@@ -83,6 +83,8 @@ const native: TranslationStrings = {
'native.lock.setting': 'Kunci dengan Face ID atau kode sandi',
'native.lock.settingHint':
'Meminta saat TREK dibuka dan setelah setengah menit di latar belakang, serta menyembunyikan aplikasi di pengalih aplikasi.',
+ 'native.share.title': 'Impor ke perjalanan mana?',
+ 'native.share.noTrips': 'Belum ada perjalanan. Buat satu dulu, lalu bagikan dokumennya lagi.',
};
export default native;
diff --git a/shared/src/i18n/it/native.ts b/shared/src/i18n/it/native.ts
index f245287a4..7891b8ec8 100644
--- a/shared/src/i18n/it/native.ts
+++ b/shared/src/i18n/it/native.ts
@@ -83,6 +83,8 @@ const native: TranslationStrings = {
'native.lock.setting': 'Blocca con Face ID o codice',
'native.lock.settingHint':
'Lo chiede all’apertura di TREK e dopo mezzo minuto in background, e nasconde l’app nel selettore delle app.',
+ 'native.share.title': 'Importare in quale viaggio?',
+ 'native.share.noTrips': 'Ancora nessun viaggio. Creane uno, poi condividi di nuovo il documento.',
};
export default native;
diff --git a/shared/src/i18n/ja/native.ts b/shared/src/i18n/ja/native.ts
index 47c78932e..1c87a190d 100644
--- a/shared/src/i18n/ja/native.ts
+++ b/shared/src/i18n/ja/native.ts
@@ -83,6 +83,8 @@ const native: TranslationStrings = {
'native.lock.setting': 'Face IDまたはパスコードでロック',
'native.lock.settingHint':
'TREKを開いたときと、バックグラウンドで30秒経過したあとに確認し、アプリスイッチャーでは内容を隠します。',
+ 'native.share.title': 'どの旅行に取り込みますか?',
+ 'native.share.noTrips': 'まだ旅行がありません。先に作成してから、もう一度ドキュメントを共有してください。',
};
export default native;
diff --git a/shared/src/i18n/ko/native.ts b/shared/src/i18n/ko/native.ts
index 806778b9c..522ba27aa 100644
--- a/shared/src/i18n/ko/native.ts
+++ b/shared/src/i18n/ko/native.ts
@@ -81,6 +81,8 @@ const native: TranslationStrings = {
'native.lock.setting': 'Face ID 또는 암호로 잠금',
'native.lock.settingHint':
'TREK을 열 때와 백그라운드에서 30초가 지난 후에 확인하며, 앱 전환기에서는 내용을 숨깁니다.',
+ 'native.share.title': '어느 여행으로 가져올까요?',
+ 'native.share.noTrips': '아직 여행이 없습니다. 먼저 여행을 만든 뒤 문서를 다시 공유하세요.',
};
export default native;
diff --git a/shared/src/i18n/nl/native.ts b/shared/src/i18n/nl/native.ts
index 77194910e..430a3bbef 100644
--- a/shared/src/i18n/nl/native.ts
+++ b/shared/src/i18n/nl/native.ts
@@ -82,6 +82,8 @@ const native: TranslationStrings = {
'native.lock.setting': 'Vergrendelen met Face ID of toegangscode',
'native.lock.settingHint':
'Vraagt erom bij het openen van TREK en na een halve minuut op de achtergrond, en verbergt de app in de appkiezer.',
+ 'native.share.title': 'In welke reis importeren?',
+ 'native.share.noTrips': 'Nog geen reis. Maak er eerst een aan en deel het document dan opnieuw.',
};
export default native;
diff --git a/shared/src/i18n/pl/native.ts b/shared/src/i18n/pl/native.ts
index 31c9153de..8b17f18f1 100644
--- a/shared/src/i18n/pl/native.ts
+++ b/shared/src/i18n/pl/native.ts
@@ -82,6 +82,8 @@ const native: TranslationStrings = {
'native.lock.setting': 'Blokuj za pomocą Face ID lub kodu',
'native.lock.settingHint':
'Pyta przy otwieraniu TREK i po pół minuty w tle oraz ukrywa aplikację w przełączniku aplikacji.',
+ 'native.share.title': 'Do której podróży zaimportować?',
+ 'native.share.noTrips': 'Nie ma jeszcze podróży. Najpierw utwórz podróż, a potem udostępnij dokument ponownie.',
};
export default native;
diff --git a/shared/src/i18n/ru/native.ts b/shared/src/i18n/ru/native.ts
index f08233c3e..976e0a0dd 100644
--- a/shared/src/i18n/ru/native.ts
+++ b/shared/src/i18n/ru/native.ts
@@ -83,6 +83,8 @@ const native: TranslationStrings = {
'native.lock.setting': 'Блокировать с Face ID или кодом',
'native.lock.settingHint':
'Запрашивается при открытии TREK и через полминуты в фоне, а в переключателе приложений содержимое скрыто.',
+ 'native.share.title': 'В какую поездку импортировать?',
+ 'native.share.noTrips': 'Поездок пока нет. Сначала создайте поездку, затем снова поделитесь документом.',
};
export default native;
diff --git a/shared/src/i18n/sk/native.ts b/shared/src/i18n/sk/native.ts
index 85a19799d..a140f0352 100644
--- a/shared/src/i18n/sk/native.ts
+++ b/shared/src/i18n/sk/native.ts
@@ -82,6 +82,8 @@ const native: TranslationStrings = {
'native.lock.setting': 'Zamknúť pomocou Face ID alebo kódu',
'native.lock.settingHint':
'Opýta sa pri otvorení TREK a po pol minúte na pozadí a skryje aplikáciu v prepínači aplikácií.',
+ 'native.share.title': 'Importovať do ktorej cesty?',
+ 'native.share.noTrips': 'Zatiaľ žiadna cesta. Najprv nejakú vytvorte a potom dokument zdieľajte znova.',
};
export default native;
diff --git a/shared/src/i18n/sv/native.ts b/shared/src/i18n/sv/native.ts
index 51c460c96..fe3787c79 100644
--- a/shared/src/i18n/sv/native.ts
+++ b/shared/src/i18n/sv/native.ts
@@ -83,6 +83,8 @@ const native: TranslationStrings = {
'native.lock.setting': 'Lås med Face ID eller lösenkod',
'native.lock.settingHint':
'Frågar när TREK öppnas och efter en halv minut i bakgrunden, och döljer appen i appväxlaren.',
+ 'native.share.title': 'Importera till vilken resa?',
+ 'native.share.noTrips': 'Ingen resa ännu. Skapa en först och dela sedan dokumentet igen.',
};
export default native;
diff --git a/shared/src/i18n/th/native.ts b/shared/src/i18n/th/native.ts
index 176131319..5d11811cb 100644
--- a/shared/src/i18n/th/native.ts
+++ b/shared/src/i18n/th/native.ts
@@ -80,6 +80,8 @@ const native: TranslationStrings = {
'native.lock.settingTitle': 'ล็อกแอป',
'native.lock.setting': 'ล็อกด้วย Face ID หรือรหัส',
'native.lock.settingHint': 'ถามเมื่อเปิด TREK และหลังจากอยู่เบื้องหลังครึ่งนาที และซ่อนแอปในตัวสลับแอป',
+ 'native.share.title': 'นำเข้าไปยังทริปไหน',
+ 'native.share.noTrips': 'ยังไม่มีทริป สร้างทริปก่อนแล้วแชร์เอกสารอีกครั้ง',
};
export default native;
diff --git a/shared/src/i18n/tr/native.ts b/shared/src/i18n/tr/native.ts
index 06e87ba05..deebeaf4e 100644
--- a/shared/src/i18n/tr/native.ts
+++ b/shared/src/i18n/tr/native.ts
@@ -83,6 +83,8 @@ const native: TranslationStrings = {
'native.lock.setting': 'Face ID veya parola ile kilitle',
'native.lock.settingHint':
'TREK açılırken ve arka planda yarım dakika sonra sorar, uygulamayı uygulama değiştiricide gizler.',
+ 'native.share.title': 'Hangi geziye aktarılsın?',
+ 'native.share.noTrips': 'Henüz gezi yok. Önce bir gezi oluşturun, sonra belgeyi yeniden paylaşın.',
};
export default native;
diff --git a/shared/src/i18n/uk/native.ts b/shared/src/i18n/uk/native.ts
index 64dc63398..d2bb8f289 100644
--- a/shared/src/i18n/uk/native.ts
+++ b/shared/src/i18n/uk/native.ts
@@ -82,6 +82,8 @@ const native: TranslationStrings = {
'native.lock.setting': 'Блокувати за допомогою Face ID або коду',
'native.lock.settingHint':
'Запитує під час відкриття TREK і після пів хвилини у фоні, а в перемикачі застосунків вміст приховано.',
+ 'native.share.title': 'До якої подорожі імпортувати?',
+ 'native.share.noTrips': 'Подорожей ще немає. Спершу створіть подорож, а потім знову поділіться документом.',
};
export default native;
diff --git a/shared/src/i18n/vi/native.ts b/shared/src/i18n/vi/native.ts
index 5902d6590..c8134c429 100644
--- a/shared/src/i18n/vi/native.ts
+++ b/shared/src/i18n/vi/native.ts
@@ -83,6 +83,8 @@ const native: TranslationStrings = {
'native.lock.setting': 'Khóa bằng Face ID hoặc mật mã',
'native.lock.settingHint':
'Hỏi khi mở TREK và sau nửa phút chạy nền, đồng thời ẩn ứng dụng trong trình chuyển ứng dụng.',
+ 'native.share.title': 'Nhập vào chuyến đi nào?',
+ 'native.share.noTrips': 'Chưa có chuyến đi nào. Hãy tạo một chuyến trước rồi chia sẻ lại tài liệu.',
};
export default native;
diff --git a/shared/src/i18n/zh-TW/native.ts b/shared/src/i18n/zh-TW/native.ts
index 71ba73f2c..e781ff8f3 100644
--- a/shared/src/i18n/zh-TW/native.ts
+++ b/shared/src/i18n/zh-TW/native.ts
@@ -80,6 +80,8 @@ const native: TranslationStrings = {
'native.lock.settingTitle': 'App 鎖定',
'native.lock.setting': '使用 Face ID 或密碼鎖定',
'native.lock.settingHint': '開啟 TREK 時以及在背景停留半分鐘後會要求驗證,並在 App 切換器中隱藏內容。',
+ 'native.share.title': '要匯入到哪個行程?',
+ 'native.share.noTrips': '還沒有行程。請先建立一個,然後再次分享該文件。',
};
export default native;
diff --git a/shared/src/i18n/zh/native.ts b/shared/src/i18n/zh/native.ts
index b7f9e74ec..3e6a8cc2d 100644
--- a/shared/src/i18n/zh/native.ts
+++ b/shared/src/i18n/zh/native.ts
@@ -80,6 +80,8 @@ const native: TranslationStrings = {
'native.lock.settingTitle': '应用锁',
'native.lock.setting': '使用面容 ID 或密码锁定',
'native.lock.settingHint': '打开 TREK 时以及在后台停留半分钟后会要求验证,并在应用切换器中隐藏内容。',
+ 'native.share.title': '导入到哪个行程?',
+ 'native.share.noTrips': '还没有行程。请先创建一个,然后再次分享该文档。',
};
export default native;