@lowdefy/shell 3.23.2 → 7.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +183 -183
- package/README.md +364 -2
- package/app/(t0,t1,t2,t3,t4)/[...path].js +38 -0
- package/app/(t0,t1,t2,t3,t4)/_layout.js +48 -0
- package/app/(t0,t1,t2,t3,t4)/index.js +38 -0
- package/app/+native-intent.js +39 -0
- package/app/_layout.js +36 -0
- package/app.config.ts +183 -0
- package/appLinks.js +65 -0
- package/applyShellPlugins.js +43 -0
- package/authCallbackIntentFilters.js +46 -0
- package/babel.config.js +25 -0
- package/checkShellConfig.js +172 -0
- package/checkShellPlugins.js +74 -0
- package/getPrivacyManifest.js +39 -0
- package/metro.config.js +73 -0
- package/native/LowdefyAppShortcuts.swift.template +84 -0
- package/native/withAppShortcuts.js +60 -0
- package/native-fingerprint.json +16 -0
- package/package.json +120 -40
- package/profiles.js +607 -0
- package/readShellConfig.js +36 -0
- package/resolveShellPlugins.js +109 -0
- package/runtimeVersion.js +112 -0
- package/scripts/checkReleaseBundle.mjs +358 -0
- package/scripts/createDayjsLocales.mjs +67 -0
- package/scripts/createShellAssets.mjs +54 -0
- package/scripts/createShellVersion.mjs +83 -0
- package/scripts/createTypeManifest.mjs +205 -0
- package/shell.dev.json +11 -0
- package/shellVariant.js +126 -0
- package/src/ShellContext.js +32 -0
- package/src/actions/CopyToClipboard.js +29 -0
- package/src/actions/CopyToClipboard.test.js +33 -0
- package/src/actions/GeolocationCurrentPosition.js +61 -0
- package/src/actions/GeolocationCurrentPosition.test.js +79 -0
- package/src/actions/GetLocalStorage.js +36 -0
- package/src/actions/RemoveLocalStorage.js +31 -0
- package/src/actions/ScrollTo.js +66 -0
- package/src/actions/ScrollTo.test.js +83 -0
- package/src/actions/SetFocus.js +33 -0
- package/src/actions/SetFocus.test.js +49 -0
- package/src/actions/SetLocalStorage.js +34 -0
- package/src/actions/localStorage.test.js +68 -0
- package/src/actions/measureInScrollView.js +36 -0
- package/src/actions/nativeActions.js +41 -0
- package/src/auth/AuthButton.js +44 -0
- package/src/auth/AuthGate.js +57 -0
- package/src/auth/AuthLink.js +43 -0
- package/src/auth/LockScreen.js +67 -0
- package/src/auth/LockScreen.test.js +37 -0
- package/src/auth/SignInScreen.js +268 -0
- package/src/auth/SignInScreen.test.js +187 -0
- package/src/auth/createAppAuth.js +325 -0
- package/src/auth/createAppAuth.test.js +424 -0
- package/src/auth/createAuthApi.js +115 -0
- package/src/auth/createAuthApi.test.js +138 -0
- package/src/auth/createCoreAuth.js +96 -0
- package/src/auth/createCoreAuth.test.js +188 -0
- package/src/auth/createDeviceKey.js +62 -0
- package/src/auth/createDeviceKey.test.js +54 -0
- package/src/auth/createSessionStores.js +45 -0
- package/src/auth/createTokenStore.js +103 -0
- package/src/auth/createTokenStore.test.js +116 -0
- package/src/auth/getAuthSettings.js +24 -0
- package/src/auth/getAuthView.js +39 -0
- package/src/auth/getAuthView.test.js +52 -0
- package/src/auth/getSheetReturnUrl.js +35 -0
- package/src/auth/getTokenStoreOptions.js +46 -0
- package/src/auth/isBackgroundShell.js +26 -0
- package/src/auth/isSheetReturnLink.js +35 -0
- package/src/auth/parseQuery.js +39 -0
- package/src/auth/purgeAppData.js +80 -0
- package/src/auth/purgeAppData.test.js +104 -0
- package/src/auth/shouldLock.js +26 -0
- package/src/auth/signInWithSheet.js +97 -0
- package/src/auth/signInWithSheet.test.js +205 -0
- package/src/auth/styles.js +78 -0
- package/src/auth/unregisterPushToken.js +62 -0
- package/src/auth/unregisterPushToken.test.js +67 -0
- package/src/auth/usesBiometricUnlock.js +23 -0
- package/src/auth/watchSession.js +47 -0
- package/src/auth/withoutCookies.js +26 -0
- package/src/cache/createSqliteCacheStore.js +113 -0
- package/src/cache/createSqliteCacheStore.test.js +93 -0
- package/src/cache/getCacheKey.js +25 -0
- package/src/cache/getLastCacheKeyName.js +22 -0
- package/src/components/AppProvider.js +118 -0
- package/src/components/Frame.js +116 -0
- package/src/components/Frame.test.js +101 -0
- package/src/components/LoadingScreen.js +35 -0
- package/src/components/MenuButton.js +121 -0
- package/src/components/MenuButton.test.js +74 -0
- package/src/components/MessageScreen.js +51 -0
- package/src/components/NavigationTheme.js +33 -0
- package/src/components/NoConnectionBanner.js +51 -0
- package/src/components/NoConnectionBanner.test.js +73 -0
- package/src/components/OtherPageScreen.js +95 -0
- package/src/components/OtherPageScreen.test.js +74 -0
- package/src/components/PageScreen.js +254 -0
- package/src/components/PageScreen.test.js +492 -0
- package/src/components/RouteErrorScreen.js +47 -0
- package/src/components/ShellRoot.js +34 -0
- package/src/components/ShellRoot.test.js +62 -0
- package/src/components/ShellThemeProvider.js +45 -0
- package/src/components/SwitchToTab.js +36 -0
- package/src/components/SwitchToTab.test.js +63 -0
- package/src/components/TabIconImages.js +72 -0
- package/src/components/UpdateScreen.js +40 -0
- package/src/components/getNavigationTheme.js +44 -0
- package/src/components/getNavigationTheme.test.js +41 -0
- package/src/components/styles.js +50 -0
- package/src/components/useSurfaceTokens.js +47 -0
- package/src/config/getAppApiBase.js +34 -0
- package/src/config/getShellConfig.js +37 -0
- package/src/config/getShellConfig.test.js +80 -0
- package/src/createShellApp.js +126 -0
- package/src/dev/DevShell.js +239 -0
- package/src/dev/DevShell.test.js +233 -0
- package/src/dev/connect/ConfirmSheet.js +71 -0
- package/src/dev/connect/ConnectScreen.js +117 -0
- package/src/dev/connect/QrScanner.js +89 -0
- package/src/dev/connection/createDevShellConfig.js +47 -0
- package/src/dev/connection/createDevTransport.js +51 -0
- package/src/dev/connection/createDevTransport.test.js +87 -0
- package/src/dev/connection/createServerList.js +48 -0
- package/src/dev/connection/isLoopbackHost.js +25 -0
- package/src/dev/connection/pairedShellApp.test.js +104 -0
- package/src/dev/connection/parseDevLink.js +66 -0
- package/src/dev/connection/parseDevLink.test.js +97 -0
- package/src/dev/connection/parseQuery.js +33 -0
- package/src/dev/connection/parseServerInput.js +40 -0
- package/src/dev/connection/parseServerUrl.js +45 -0
- package/src/dev/devStyles.js +97 -0
- package/src/dev/index.js +21 -0
- package/src/dev/inject/createDeviceInjections.js +188 -0
- package/src/dev/inject/createDeviceInjections.test.js +224 -0
- package/src/dev/inject/createOfflineFetch.js +35 -0
- package/src/dev/inject/createOfflineFetch.test.js +68 -0
- package/src/dev/inject/injectPush.js +60 -0
- package/src/dev/inject/injectShare.js +55 -0
- package/src/dev/inject/withInjectedDevice.js +98 -0
- package/src/dev/menu/BlockGallery.js +33 -0
- package/src/dev/menu/DevMenu.js +121 -0
- package/src/dev/menu/createLogBuffer.js +83 -0
- package/src/dev/menu/watchShake.js +52 -0
- package/src/dev/menu/watchShake.test.js +61 -0
- package/src/dev/recorder/createNativeRecorder.js +204 -0
- package/src/dev/recorder/createNativeRecorder.test.js +307 -0
- package/src/dev/redirectDevLink.js +30 -0
- package/src/dev/redirectDevLink.test.js +49 -0
- package/src/dev/steps/createStepRunner.js +184 -0
- package/src/dev/steps/createStepRunner.test.js +262 -0
- package/src/dev/steps/findBlock.js +78 -0
- package/src/dev/steps/isContextSettled.js +37 -0
- package/src/dev/steps/waitForSettle.js +39 -0
- package/src/dev/steps/waitUntil.js +40 -0
- package/src/dev/tab/DevTabClient.js +97 -0
- package/src/dev/tab/answerEval.js +39 -0
- package/src/dev/tab/answerInspect.js +45 -0
- package/src/dev/tab/createDevTabClient.js +272 -0
- package/src/dev/tab/createDevTabClient.test.js +317 -0
- package/src/dev/tab/describeTabError.js +35 -0
- package/src/dev/tab/devClientMarker.js +22 -0
- package/src/dev/tab/devClientMarker.test.js +23 -0
- package/src/dev/tab/findPageContext.js +43 -0
- package/src/dev/tab/getShownPage.js +42 -0
- package/src/dev/tab/readEventStream.js +68 -0
- package/src/dev/tab/reloadApp.js +42 -0
- package/src/dev/tab/reloadApp.test.js +115 -0
- package/src/device/DeviceHosts.js +32 -0
- package/src/device/basic/createFilesFeature.js +41 -0
- package/src/device/basic/createHapticsFeature.js +46 -0
- package/src/device/basic/createKeepAwakeFeature.js +37 -0
- package/src/device/basic/createPhotosFeature.js +40 -0
- package/src/device/basic/createRequestQueueFeature.js +37 -0
- package/src/device/basic/createShareFeature.js +63 -0
- package/src/device/basic/createShareFeature.test.js +47 -0
- package/src/device/basic/createSpeechFeature.js +43 -0
- package/src/device/basic/createUploadFeature.js +41 -0
- package/src/device/basic/toImagePickerOptions.js +41 -0
- package/src/device/basic/toPickedFile.js +54 -0
- package/src/device/calendar/index.js +68 -0
- package/src/device/contacts/index.js +67 -0
- package/src/device/createDevice.js +65 -0
- package/src/device/device.js +27 -0
- package/src/device/field/MapView.js +93 -0
- package/src/device/field/ScanCodeSheet.js +86 -0
- package/src/device/field/ScannerView.js +52 -0
- package/src/device/field/createAudioFeature.js +70 -0
- package/src/device/field/createBrightnessFeature.js +40 -0
- package/src/device/field/createCameraFeature.js +56 -0
- package/src/device/field/createDocumentScannerFeature.js +51 -0
- package/src/device/field/createLocationFeature.js +39 -0
- package/src/device/field/createScanRequests.js +55 -0
- package/src/device/field/index.js +39 -0
- package/src/device/field/scanRequests.js +22 -0
- package/src/device/injected.js +60 -0
- package/src/device/injected.test.js +39 -0
- package/src/device/nfc/index.js +89 -0
- package/src/device/nfc/toNfcRecord.js +44 -0
- package/src/device/nfc/toNfcRecord.test.js +48 -0
- package/src/device/tracking/createBacklog.js +63 -0
- package/src/device/tracking/createBacklog.test.js +47 -0
- package/src/device/tracking/index.js +211 -0
- package/src/device/tracking/index.test.js +110 -0
- package/src/host/createDeviceStore.js +32 -0
- package/src/host/createMemoryStore.js +32 -0
- package/src/host/createNetworkStatus.js +94 -0
- package/src/host/createNetworkStatus.test.js +94 -0
- package/src/host/createRouterAdapter.js +33 -0
- package/src/host/createShellFetch.js +62 -0
- package/src/host/createShellFetch.test.js +165 -0
- package/src/host/createShellGlobals.js +62 -0
- package/src/host/createShellHost.js +83 -0
- package/src/host/createShellHost.test.js +36 -0
- package/src/host/getOrigin.js +31 -0
- package/src/host/isNetworkError.js +24 -0
- package/src/host/isOnline.js +22 -0
- package/src/host/networkStatus.js +24 -0
- package/src/host/readServerError.js +45 -0
- package/src/host/readServerError.test.js +85 -0
- package/src/host/reportShellError.js +47 -0
- package/src/host/reportShellError.test.js +79 -0
- package/src/host/withNetworkErrors.js +38 -0
- package/src/host/withNetworkErrors.test.js +61 -0
- package/src/host/withShellHeader.js +25 -0
- package/src/host/withShellHeader.test.js +28 -0
- package/src/js/evaluateJsEntries.js +43 -0
- package/src/js/evaluateJsEntries.test.js +48 -0
- package/src/locale/createShellLocale.js +112 -0
- package/src/locale/createShellLocale.test.js +74 -0
- package/src/locale/dayjsLocales.js +165 -0
- package/src/locale/getDeviceLocales.js +23 -0
- package/src/locale/loadDayjsLocale.js +32 -0
- package/src/locale/resolveActiveLocale.js +46 -0
- package/src/locale/resolveActiveLocale.test.js +40 -0
- package/src/native/backgroundFetch.js +97 -0
- package/src/native/callEndpoint.js +63 -0
- package/src/native/createAppEventTrigger.js +70 -0
- package/src/native/currentApp.js +49 -0
- package/src/native/getPagePath.js +32 -0
- package/src/native/openPath.js +55 -0
- package/src/native/openPath.test.js +39 -0
- package/src/native/parseShellLink.js +38 -0
- package/src/native/parseShellLink.test.js +29 -0
- package/src/native/startAppServices.js +94 -0
- package/src/native/startAppServices.test.js +97 -0
- package/src/native/startShareIn.js +59 -0
- package/src/native/startShortcuts.js +88 -0
- package/src/native/startShortcuts.test.js +59 -0
- package/src/native/toSharePayload.js +47 -0
- package/src/native/toSharePayload.test.js +47 -0
- package/src/native/whenAppReady.js +48 -0
- package/src/navigation/SlotContext.js +24 -0
- package/src/navigation/frameSlots.js +27 -0
- package/src/navigation/getFrame.js +30 -0
- package/src/navigation/getInitialScreenOptions.js +63 -0
- package/src/navigation/getInitialScreenOptions.test.js +66 -0
- package/src/navigation/getPresentation.js +28 -0
- package/src/navigation/getSlotRootPath.js +27 -0
- package/src/navigation/getStackOptions.js +185 -0
- package/src/navigation/getTabHref.js +45 -0
- package/src/navigation/getTabIcons.js +43 -0
- package/src/navigation/isPageUnderHeader.js +46 -0
- package/src/navigation/navigation.test.js +342 -0
- package/src/navigation/toAppLinkPath.js +43 -0
- package/src/navigation/toAppLinkPath.test.js +53 -0
- package/src/navigation/toRouterHref.js +29 -0
- package/src/notifications/createNotificationsFeature.js +61 -0
- package/src/notifications/getCategoryAction.js +31 -0
- package/src/notifications/handleNotificationResponse.js +82 -0
- package/src/notifications/registerPushToken.js +71 -0
- package/src/notifications/startNotifications.js +114 -0
- package/src/notifications/toCategoryActions.js +42 -0
- package/src/notifications/toNotificationEvent.js +36 -0
- package/src/notifications/toScheduleRequest.js +62 -0
- package/src/plugins/appTypes.js +28 -0
- package/src/plugins/prefixTypes.js +28 -0
- package/src/plugins/shellPlugins.json +15 -0
- package/src/plugins/typeManifest.js +789 -0
- package/src/plugins/types.js +64 -0
- package/src/plugins/types.test.js +173 -0
- package/src/polyfills/installGetRandomValues.js +28 -0
- package/src/queue/createRequestQueue.js +198 -0
- package/src/queue/createRequestQueue.test.js +215 -0
- package/src/queue/createSqliteQueueStore.js +121 -0
- package/src/queue/summarizeQueue.js +39 -0
- package/src/session/createAppSession.js +323 -0
- package/src/session/createAppSession.test.js +391 -0
- package/src/session/getPageView.js +59 -0
- package/src/session/getPageView.test.js +137 -0
- package/src/sync/encodePagePath.js +27 -0
- package/src/sync/fetchPage.js +72 -0
- package/src/sync/fetchPage.test.js +84 -0
- package/src/sync/fetchRoot.js +43 -0
- package/src/sync/fetchUser.js +33 -0
- package/src/sync/runLimited.js +36 -0
- package/src/sync/toRootConfig.js +35 -0
- package/src/test/createFakeNetwork.js +40 -0
- package/src/test/createFakeSecureStore.js +40 -0
- package/src/test/createFakeServer.js +98 -0
- package/src/test/createMemoryCacheStore.js +59 -0
- package/src/test/createNetworkError.js +24 -0
- package/src/test/expoImage.js +42 -0
- package/src/test/expoNotifications.js +40 -0
- package/src/test/expoQuickActions.js +22 -0
- package/src/test/expoSpeechRecognition.js +31 -0
- package/src/test/expoTaskManager.js +25 -0
- package/src/test/expoUi.js +55 -0
- package/src/test/expoUiBottomSheet.js +64 -0
- package/src/test/expoUiDateTimePicker.js +26 -0
- package/src/test/expoUiMenu.js +46 -0
- package/src/test/expoUiSegmentedControl.js +47 -0
- package/src/test/expoUiSwiftUi.js +62 -0
- package/src/test/expoUiSwiftUiModifiers.js +23 -0
- package/src/test/expoWebBrowser.js +23 -0
- package/src/test/fixtures.js +98 -0
- package/src/test/nativeModule.js +33 -0
- package/src/test/renderPageScreen.js +109 -0
- package/src/types/checkTypeSet.js +39 -0
- package/src/types/collectPageTypes.js +49 -0
- package/src/types/collectPageTypes.test.js +90 -0
- package/src/types/findMissingPageTypes.js +40 -0
- package/src/version/compareVersions.js +38 -0
- package/src/version/isShellTooOld.js +30 -0
- package/src/version/shellVersion.js +21 -0
- package/src/version/shellVersion.test.js +32 -0
- package/src/widgets/fetchWidgetData.js +59 -0
- package/src/widgets/index.js +156 -0
- package/src/widgets/refreshWidgets.js +31 -0
- package/withExcludedNativeModules.js +93 -0
- package/dist/location.js +0 -33
- package/dist/public/apple-touch-icon.png +0 -0
- package/dist/public/icon-32.png +0 -0
- package/dist/public/icon-512.png +0 -0
- package/dist/public/icon.svg +0 -17
- package/dist/public/logo-dark-theme.png +0 -0
- package/dist/public/logo-light-theme.png +0 -0
- package/dist/public/logo-square-dark-theme.png +0 -0
- package/dist/public/logo-square-light-theme.png +0 -0
- package/dist/public/manifest.webmanifest +0 -16
- package/dist/shell/246.93432ff68186aae6c87b.js +0 -2
- package/dist/shell/246.93432ff68186aae6c87b.js.LICENSE.txt +0 -8
- package/dist/shell/454.b597ca21366afda000af.js +0 -2
- package/dist/shell/454.b597ca21366afda000af.js.LICENSE.txt +0 -14
- package/dist/shell/484.d645e6c09079f45ce044.js +0 -1
- package/dist/shell/706.a66931e02a549fd269bd.js +0 -2
- package/dist/shell/706.a66931e02a549fd269bd.js.LICENSE.txt +0 -8
- package/dist/shell/9.78be8c1b6c3986f404fc.js +0 -2
- package/dist/shell/9.78be8c1b6c3986f404fc.js.LICENSE.txt +0 -45
- package/dist/shell/922.43b7a3ebe22ef05b3049.js +0 -2
- package/dist/shell/922.43b7a3ebe22ef05b3049.js.LICENSE.txt +0 -14
- package/dist/shell/index.html +0 -57
- package/dist/shell/main.bde87d1433f0625faed6.js +0 -1
- package/dist/shell/runtime.1ead93159ba56c05b969.js +0 -1
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2020-2026 Lowdefy, Inc
|
|
3
|
+
|
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
you may not use this file except in compliance with the License.
|
|
6
|
+
You may obtain a copy of the License at
|
|
7
|
+
|
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
|
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
See the License for the specific language governing permissions and
|
|
14
|
+
limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
// Generated by scripts/createDayjsLocales.mjs from the dayjs package the shell carries. Do not edit.
|
|
18
|
+
|
|
19
|
+
const dayjsLocales = {
|
|
20
|
+
af: () => require('dayjs/locale/af.js'),
|
|
21
|
+
am: () => require('dayjs/locale/am.js'),
|
|
22
|
+
ar: () => require('dayjs/locale/ar.js'),
|
|
23
|
+
'ar-dz': () => require('dayjs/locale/ar-dz.js'),
|
|
24
|
+
'ar-iq': () => require('dayjs/locale/ar-iq.js'),
|
|
25
|
+
'ar-kw': () => require('dayjs/locale/ar-kw.js'),
|
|
26
|
+
'ar-ly': () => require('dayjs/locale/ar-ly.js'),
|
|
27
|
+
'ar-ma': () => require('dayjs/locale/ar-ma.js'),
|
|
28
|
+
'ar-sa': () => require('dayjs/locale/ar-sa.js'),
|
|
29
|
+
'ar-tn': () => require('dayjs/locale/ar-tn.js'),
|
|
30
|
+
az: () => require('dayjs/locale/az.js'),
|
|
31
|
+
be: () => require('dayjs/locale/be.js'),
|
|
32
|
+
bg: () => require('dayjs/locale/bg.js'),
|
|
33
|
+
bi: () => require('dayjs/locale/bi.js'),
|
|
34
|
+
bm: () => require('dayjs/locale/bm.js'),
|
|
35
|
+
bn: () => require('dayjs/locale/bn.js'),
|
|
36
|
+
'bn-bd': () => require('dayjs/locale/bn-bd.js'),
|
|
37
|
+
bo: () => require('dayjs/locale/bo.js'),
|
|
38
|
+
br: () => require('dayjs/locale/br.js'),
|
|
39
|
+
bs: () => require('dayjs/locale/bs.js'),
|
|
40
|
+
ca: () => require('dayjs/locale/ca.js'),
|
|
41
|
+
cs: () => require('dayjs/locale/cs.js'),
|
|
42
|
+
cv: () => require('dayjs/locale/cv.js'),
|
|
43
|
+
cy: () => require('dayjs/locale/cy.js'),
|
|
44
|
+
da: () => require('dayjs/locale/da.js'),
|
|
45
|
+
de: () => require('dayjs/locale/de.js'),
|
|
46
|
+
'de-at': () => require('dayjs/locale/de-at.js'),
|
|
47
|
+
'de-ch': () => require('dayjs/locale/de-ch.js'),
|
|
48
|
+
dv: () => require('dayjs/locale/dv.js'),
|
|
49
|
+
el: () => require('dayjs/locale/el.js'),
|
|
50
|
+
en: () => require('dayjs/locale/en.js'),
|
|
51
|
+
'en-au': () => require('dayjs/locale/en-au.js'),
|
|
52
|
+
'en-ca': () => require('dayjs/locale/en-ca.js'),
|
|
53
|
+
'en-gb': () => require('dayjs/locale/en-gb.js'),
|
|
54
|
+
'en-ie': () => require('dayjs/locale/en-ie.js'),
|
|
55
|
+
'en-il': () => require('dayjs/locale/en-il.js'),
|
|
56
|
+
'en-in': () => require('dayjs/locale/en-in.js'),
|
|
57
|
+
'en-nz': () => require('dayjs/locale/en-nz.js'),
|
|
58
|
+
'en-sg': () => require('dayjs/locale/en-sg.js'),
|
|
59
|
+
'en-tt': () => require('dayjs/locale/en-tt.js'),
|
|
60
|
+
eo: () => require('dayjs/locale/eo.js'),
|
|
61
|
+
es: () => require('dayjs/locale/es.js'),
|
|
62
|
+
'es-do': () => require('dayjs/locale/es-do.js'),
|
|
63
|
+
'es-mx': () => require('dayjs/locale/es-mx.js'),
|
|
64
|
+
'es-pr': () => require('dayjs/locale/es-pr.js'),
|
|
65
|
+
'es-us': () => require('dayjs/locale/es-us.js'),
|
|
66
|
+
et: () => require('dayjs/locale/et.js'),
|
|
67
|
+
eu: () => require('dayjs/locale/eu.js'),
|
|
68
|
+
fa: () => require('dayjs/locale/fa.js'),
|
|
69
|
+
fi: () => require('dayjs/locale/fi.js'),
|
|
70
|
+
fo: () => require('dayjs/locale/fo.js'),
|
|
71
|
+
fr: () => require('dayjs/locale/fr.js'),
|
|
72
|
+
'fr-ca': () => require('dayjs/locale/fr-ca.js'),
|
|
73
|
+
'fr-ch': () => require('dayjs/locale/fr-ch.js'),
|
|
74
|
+
fy: () => require('dayjs/locale/fy.js'),
|
|
75
|
+
ga: () => require('dayjs/locale/ga.js'),
|
|
76
|
+
gd: () => require('dayjs/locale/gd.js'),
|
|
77
|
+
gl: () => require('dayjs/locale/gl.js'),
|
|
78
|
+
'gom-latn': () => require('dayjs/locale/gom-latn.js'),
|
|
79
|
+
gu: () => require('dayjs/locale/gu.js'),
|
|
80
|
+
he: () => require('dayjs/locale/he.js'),
|
|
81
|
+
hi: () => require('dayjs/locale/hi.js'),
|
|
82
|
+
hr: () => require('dayjs/locale/hr.js'),
|
|
83
|
+
ht: () => require('dayjs/locale/ht.js'),
|
|
84
|
+
hu: () => require('dayjs/locale/hu.js'),
|
|
85
|
+
'hy-am': () => require('dayjs/locale/hy-am.js'),
|
|
86
|
+
id: () => require('dayjs/locale/id.js'),
|
|
87
|
+
is: () => require('dayjs/locale/is.js'),
|
|
88
|
+
it: () => require('dayjs/locale/it.js'),
|
|
89
|
+
'it-ch': () => require('dayjs/locale/it-ch.js'),
|
|
90
|
+
ja: () => require('dayjs/locale/ja.js'),
|
|
91
|
+
jv: () => require('dayjs/locale/jv.js'),
|
|
92
|
+
ka: () => require('dayjs/locale/ka.js'),
|
|
93
|
+
kk: () => require('dayjs/locale/kk.js'),
|
|
94
|
+
km: () => require('dayjs/locale/km.js'),
|
|
95
|
+
kn: () => require('dayjs/locale/kn.js'),
|
|
96
|
+
ko: () => require('dayjs/locale/ko.js'),
|
|
97
|
+
ku: () => require('dayjs/locale/ku.js'),
|
|
98
|
+
ky: () => require('dayjs/locale/ky.js'),
|
|
99
|
+
lb: () => require('dayjs/locale/lb.js'),
|
|
100
|
+
lo: () => require('dayjs/locale/lo.js'),
|
|
101
|
+
lt: () => require('dayjs/locale/lt.js'),
|
|
102
|
+
lv: () => require('dayjs/locale/lv.js'),
|
|
103
|
+
me: () => require('dayjs/locale/me.js'),
|
|
104
|
+
mi: () => require('dayjs/locale/mi.js'),
|
|
105
|
+
mk: () => require('dayjs/locale/mk.js'),
|
|
106
|
+
ml: () => require('dayjs/locale/ml.js'),
|
|
107
|
+
mn: () => require('dayjs/locale/mn.js'),
|
|
108
|
+
mr: () => require('dayjs/locale/mr.js'),
|
|
109
|
+
ms: () => require('dayjs/locale/ms.js'),
|
|
110
|
+
'ms-my': () => require('dayjs/locale/ms-my.js'),
|
|
111
|
+
mt: () => require('dayjs/locale/mt.js'),
|
|
112
|
+
my: () => require('dayjs/locale/my.js'),
|
|
113
|
+
nb: () => require('dayjs/locale/nb.js'),
|
|
114
|
+
ne: () => require('dayjs/locale/ne.js'),
|
|
115
|
+
nl: () => require('dayjs/locale/nl.js'),
|
|
116
|
+
'nl-be': () => require('dayjs/locale/nl-be.js'),
|
|
117
|
+
nn: () => require('dayjs/locale/nn.js'),
|
|
118
|
+
'oc-lnc': () => require('dayjs/locale/oc-lnc.js'),
|
|
119
|
+
'pa-in': () => require('dayjs/locale/pa-in.js'),
|
|
120
|
+
pl: () => require('dayjs/locale/pl.js'),
|
|
121
|
+
pt: () => require('dayjs/locale/pt.js'),
|
|
122
|
+
'pt-br': () => require('dayjs/locale/pt-br.js'),
|
|
123
|
+
rn: () => require('dayjs/locale/rn.js'),
|
|
124
|
+
ro: () => require('dayjs/locale/ro.js'),
|
|
125
|
+
ru: () => require('dayjs/locale/ru.js'),
|
|
126
|
+
rw: () => require('dayjs/locale/rw.js'),
|
|
127
|
+
sd: () => require('dayjs/locale/sd.js'),
|
|
128
|
+
se: () => require('dayjs/locale/se.js'),
|
|
129
|
+
si: () => require('dayjs/locale/si.js'),
|
|
130
|
+
sk: () => require('dayjs/locale/sk.js'),
|
|
131
|
+
sl: () => require('dayjs/locale/sl.js'),
|
|
132
|
+
sq: () => require('dayjs/locale/sq.js'),
|
|
133
|
+
sr: () => require('dayjs/locale/sr.js'),
|
|
134
|
+
'sr-cyrl': () => require('dayjs/locale/sr-cyrl.js'),
|
|
135
|
+
ss: () => require('dayjs/locale/ss.js'),
|
|
136
|
+
sv: () => require('dayjs/locale/sv.js'),
|
|
137
|
+
'sv-fi': () => require('dayjs/locale/sv-fi.js'),
|
|
138
|
+
sw: () => require('dayjs/locale/sw.js'),
|
|
139
|
+
ta: () => require('dayjs/locale/ta.js'),
|
|
140
|
+
te: () => require('dayjs/locale/te.js'),
|
|
141
|
+
tet: () => require('dayjs/locale/tet.js'),
|
|
142
|
+
tg: () => require('dayjs/locale/tg.js'),
|
|
143
|
+
th: () => require('dayjs/locale/th.js'),
|
|
144
|
+
tk: () => require('dayjs/locale/tk.js'),
|
|
145
|
+
'tl-ph': () => require('dayjs/locale/tl-ph.js'),
|
|
146
|
+
tlh: () => require('dayjs/locale/tlh.js'),
|
|
147
|
+
tr: () => require('dayjs/locale/tr.js'),
|
|
148
|
+
tzl: () => require('dayjs/locale/tzl.js'),
|
|
149
|
+
tzm: () => require('dayjs/locale/tzm.js'),
|
|
150
|
+
'tzm-latn': () => require('dayjs/locale/tzm-latn.js'),
|
|
151
|
+
'ug-cn': () => require('dayjs/locale/ug-cn.js'),
|
|
152
|
+
uk: () => require('dayjs/locale/uk.js'),
|
|
153
|
+
ur: () => require('dayjs/locale/ur.js'),
|
|
154
|
+
uz: () => require('dayjs/locale/uz.js'),
|
|
155
|
+
'uz-latn': () => require('dayjs/locale/uz-latn.js'),
|
|
156
|
+
vi: () => require('dayjs/locale/vi.js'),
|
|
157
|
+
'x-pseudo': () => require('dayjs/locale/x-pseudo.js'),
|
|
158
|
+
yo: () => require('dayjs/locale/yo.js'),
|
|
159
|
+
zh: () => require('dayjs/locale/zh.js'),
|
|
160
|
+
'zh-cn': () => require('dayjs/locale/zh-cn.js'),
|
|
161
|
+
'zh-hk': () => require('dayjs/locale/zh-hk.js'),
|
|
162
|
+
'zh-tw': () => require('dayjs/locale/zh-tw.js'),
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
export default dayjsLocales;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2020-2026 Lowdefy, Inc
|
|
3
|
+
|
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
you may not use this file except in compliance with the License.
|
|
6
|
+
You may obtain a copy of the License at
|
|
7
|
+
|
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
|
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
See the License for the specific language governing permissions and
|
|
14
|
+
limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
// The device's locale, which Hermes' Intl reads from the platform (iOS's NSLocale, Android's
|
|
18
|
+
// default Locale).
|
|
19
|
+
function getDeviceLocales() {
|
|
20
|
+
return [Intl.DateTimeFormat().resolvedOptions().locale];
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export default getDeviceLocales;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2020-2026 Lowdefy, Inc
|
|
3
|
+
|
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
you may not use this file except in compliance with the License.
|
|
6
|
+
You may obtain a copy of the License at
|
|
7
|
+
|
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
|
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
See the License for the specific language governing permissions and
|
|
14
|
+
limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import dayjs from 'dayjs';
|
|
18
|
+
|
|
19
|
+
import dayjsLocales from './dayjsLocales.js';
|
|
20
|
+
|
|
21
|
+
// Makes a dayjs locale the one _dayjs formats with, loading its data the first time. The dayjs
|
|
22
|
+
// instance is the one @lowdefy/operators-dayjs imports. An id dayjs does not ship leaves the
|
|
23
|
+
// locale as it is, as on the web.
|
|
24
|
+
function loadDayjsLocale(id) {
|
|
25
|
+
if (!Object.hasOwn(dayjsLocales, id)) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
dayjsLocales[id]();
|
|
29
|
+
dayjs.locale(id);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export default loadDayjsLocale;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2020-2026 Lowdefy, Inc
|
|
3
|
+
|
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
you may not use this file except in compliance with the License.
|
|
6
|
+
You may obtain a copy of the License at
|
|
7
|
+
|
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
|
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
See the License for the specific language governing permissions and
|
|
14
|
+
limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
// The first device locale the app supports, by exact code, then by language.
|
|
18
|
+
function pickBest({ candidates, supported }) {
|
|
19
|
+
for (const candidate of candidates) {
|
|
20
|
+
if (supported.includes(candidate)) return candidate;
|
|
21
|
+
const language = candidate.split('-')[0];
|
|
22
|
+
const match = supported.find((code) => code.split('-')[0] === language);
|
|
23
|
+
if (match) return match;
|
|
24
|
+
}
|
|
25
|
+
return undefined;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* The app's active locale, as the web client picks it (useLocale): the person's choice (SetLocale)
|
|
30
|
+
* when the app supports it, else the device's locale the app supports best, else the app's
|
|
31
|
+
* default. Undefined for an app without i18n.
|
|
32
|
+
*
|
|
33
|
+
* @param {Object} params
|
|
34
|
+
* @param {string[]} params.deviceLocales The device's locales, preferred first.
|
|
35
|
+
* @param {Object} params.i18n The app's i18n config: `{ defaultLocale, locales }`.
|
|
36
|
+
* @param {string} params.preference A locale code, or 'auto'.
|
|
37
|
+
*/
|
|
38
|
+
function resolveActiveLocale({ deviceLocales, i18n, preference }) {
|
|
39
|
+
const supported = (i18n.locales ?? []).map((locale) => locale.code);
|
|
40
|
+
if (preference !== 'auto' && supported.includes(preference)) {
|
|
41
|
+
return preference;
|
|
42
|
+
}
|
|
43
|
+
return pickBest({ candidates: deviceLocales, supported }) ?? i18n.defaultLocale;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export default resolveActiveLocale;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2020-2026 Lowdefy, Inc
|
|
3
|
+
|
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
you may not use this file except in compliance with the License.
|
|
6
|
+
You may obtain a copy of the License at
|
|
7
|
+
|
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
|
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
See the License for the specific language governing permissions and
|
|
14
|
+
limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import resolveActiveLocale from './resolveActiveLocale.js';
|
|
18
|
+
|
|
19
|
+
const i18n = {
|
|
20
|
+
defaultLocale: 'en-US',
|
|
21
|
+
locales: [{ code: 'en-US' }, { code: 'af-ZA' }, { code: 'pt-BR' }],
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
test('resolveActiveLocale takes the person choice when the app supports it', () => {
|
|
25
|
+
expect(resolveActiveLocale({ deviceLocales: ['pt-BR'], i18n, preference: 'af-ZA' })).toBe(
|
|
26
|
+
'af-ZA'
|
|
27
|
+
);
|
|
28
|
+
expect(resolveActiveLocale({ deviceLocales: ['pt-BR'], i18n, preference: 'de-DE' })).toBe(
|
|
29
|
+
'pt-BR'
|
|
30
|
+
);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
test('resolveActiveLocale matches the device locale by code, then by language', () => {
|
|
34
|
+
expect(resolveActiveLocale({ deviceLocales: ['pt-BR'], i18n, preference: 'auto' })).toBe('pt-BR');
|
|
35
|
+
expect(resolveActiveLocale({ deviceLocales: ['pt-PT'], i18n, preference: 'auto' })).toBe('pt-BR');
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
test('resolveActiveLocale falls back to the app default', () => {
|
|
39
|
+
expect(resolveActiveLocale({ deviceLocales: ['ja-JP'], i18n, preference: 'auto' })).toBe('en-US');
|
|
40
|
+
});
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2020-2026 Lowdefy, Inc
|
|
3
|
+
|
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
you may not use this file except in compliance with the License.
|
|
6
|
+
You may obtain a copy of the License at
|
|
7
|
+
|
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
|
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
See the License for the specific language governing permissions and
|
|
14
|
+
limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import * as BackgroundTask from 'expo-background-task';
|
|
18
|
+
import * as Notifications from 'expo-notifications';
|
|
19
|
+
import * as TaskManager from 'expo-task-manager';
|
|
20
|
+
import { type } from '@lowdefy/helpers';
|
|
21
|
+
|
|
22
|
+
import callEndpoint from './callEndpoint.js';
|
|
23
|
+
import { getCurrentApp } from './currentApp.js';
|
|
24
|
+
import refreshWidgets from '../widgets/refreshWidgets.js';
|
|
25
|
+
import reportShellError from '../host/reportShellError.js';
|
|
26
|
+
|
|
27
|
+
const TASK = 'lowdefy-background-fetch';
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* One background fetch run, with the app closed: calls mobile.background.endpointId with
|
|
31
|
+
* { reason: 'background' } and applies its answer ({ badge?, refreshWidgets? }), sends the offline
|
|
32
|
+
* queue and refreshes the cached root and pages. No page or app event runs.
|
|
33
|
+
*
|
|
34
|
+
* @param {Object} app The open app (currentApp.js).
|
|
35
|
+
*/
|
|
36
|
+
async function runBackgroundFetch(app) {
|
|
37
|
+
const background = app.session.getState().root?.background;
|
|
38
|
+
if (type.isNone(background)) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const answer = await callEndpoint({
|
|
42
|
+
app,
|
|
43
|
+
endpointId: background.endpointId,
|
|
44
|
+
payload: { reason: 'background' },
|
|
45
|
+
});
|
|
46
|
+
if (type.isNumber(answer?.badge)) {
|
|
47
|
+
await Notifications.setBadgeCountAsync(answer.badge);
|
|
48
|
+
}
|
|
49
|
+
await Promise.all([
|
|
50
|
+
app.requestQueue.replay(),
|
|
51
|
+
app.session.sync(),
|
|
52
|
+
answer?.refreshWidgets === false ? null : refreshWidgets(),
|
|
53
|
+
]);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Defined when the bundle loads, so a launch in the background finds it.
|
|
57
|
+
TaskManager.defineTask(TASK, async () => {
|
|
58
|
+
const app = await getCurrentApp();
|
|
59
|
+
try {
|
|
60
|
+
await runBackgroundFetch(app);
|
|
61
|
+
return BackgroundTask.BackgroundTaskResult.Success;
|
|
62
|
+
} catch (error) {
|
|
63
|
+
reportShellError({ error, session: app.session });
|
|
64
|
+
return BackgroundTask.BackgroundTaskResult.Failed;
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Registers background fetch while the app's root has mobile.background, at its interval in
|
|
70
|
+
* minutes (the phone decides the real timing), and unregisters it otherwise.
|
|
71
|
+
*
|
|
72
|
+
* @param {Object} params
|
|
73
|
+
* @param {Object} params.app The open app (currentApp.js).
|
|
74
|
+
* @returns {() => void} Stops following the root.
|
|
75
|
+
*/
|
|
76
|
+
function startBackgroundFetch({ app }) {
|
|
77
|
+
let applied;
|
|
78
|
+
async function applyRoot() {
|
|
79
|
+
const background = app.session.getState().root?.background ?? null;
|
|
80
|
+
if (background === applied) return;
|
|
81
|
+
applied = background;
|
|
82
|
+
const registered = await TaskManager.isTaskRegisteredAsync(TASK);
|
|
83
|
+
if (background === null) {
|
|
84
|
+
if (registered) await BackgroundTask.unregisterTaskAsync(TASK);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
await BackgroundTask.registerTaskAsync(TASK, { minimumInterval: background.interval });
|
|
88
|
+
}
|
|
89
|
+
const unsubscribe = app.session.subscribe(() => {
|
|
90
|
+
applyRoot().catch(() => {});
|
|
91
|
+
});
|
|
92
|
+
applyRoot().catch(() => {});
|
|
93
|
+
return unsubscribe;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export { runBackgroundFetch };
|
|
97
|
+
export default startBackgroundFetch;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2020-2026 Lowdefy, Inc
|
|
3
|
+
|
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
you may not use this file except in compliance with the License.
|
|
6
|
+
You may obtain a copy of the License at
|
|
7
|
+
|
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
|
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
See the License for the specific language governing permissions and
|
|
14
|
+
limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { decodeErrorBody, getAuthorizationHeaders } from '@lowdefy/client-core';
|
|
18
|
+
import { serializer, type } from '@lowdefy/helpers';
|
|
19
|
+
|
|
20
|
+
import readServerError from '../host/readServerError.js';
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Calls one of the app's API endpoints from the shell itself, with the session token: push token
|
|
24
|
+
* registration, notification buttons, uploads, widget sources, background fetch and background
|
|
25
|
+
* location. No page is involved, so no build id is sent (endpoints are the stable contract across
|
|
26
|
+
* builds). Returns the endpoint's response; throws when the server refuses the call (the error
|
|
27
|
+
* carries the HTTP `status`) or the endpoint rejects or errors.
|
|
28
|
+
*
|
|
29
|
+
* @param {Object} params
|
|
30
|
+
* @param {Object} params.app The open app ({ apiBase, fetch, tokenStore }, currentApp.js).
|
|
31
|
+
* @param {string} params.endpointId
|
|
32
|
+
* @param {Object} [params.payload]
|
|
33
|
+
*/
|
|
34
|
+
async function callEndpoint({ app, endpointId, payload = {} }) {
|
|
35
|
+
const res = await app.fetch(`${app.apiBase}/api/endpoints/${endpointId}`, {
|
|
36
|
+
method: 'POST',
|
|
37
|
+
headers: {
|
|
38
|
+
'Content-Type': 'application/json',
|
|
39
|
+
...getAuthorizationHeaders({ host: { authTransport: 'bearer', tokenStore: app.tokenStore } }),
|
|
40
|
+
},
|
|
41
|
+
body: JSON.stringify({ payload: serializer.serialize(payload) }),
|
|
42
|
+
});
|
|
43
|
+
if (!res.ok) {
|
|
44
|
+
throw await readServerError({
|
|
45
|
+
res,
|
|
46
|
+
message: `Endpoint "${endpointId}" answered ${res.status}.`,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
const body = await res.json();
|
|
50
|
+
if (body.success === false) {
|
|
51
|
+
throw (
|
|
52
|
+
decodeErrorBody(body.error) ??
|
|
53
|
+
new Error(
|
|
54
|
+
type.isString(body.error?.message)
|
|
55
|
+
? body.error.message
|
|
56
|
+
: `Endpoint "${endpointId}" answered ${body.status}.`
|
|
57
|
+
)
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
return serializer.deserialize(body.response);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export default callEndpoint;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2020-2026 Lowdefy, Inc
|
|
3
|
+
|
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
you may not use this file except in compliance with the License.
|
|
6
|
+
You may obtain a copy of the License at
|
|
7
|
+
|
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
|
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
See the License for the specific language governing permissions and
|
|
14
|
+
limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { LowdefyInternalError } from '@lowdefy/errors';
|
|
18
|
+
|
|
19
|
+
import reportShellError from '../host/reportShellError.js';
|
|
20
|
+
|
|
21
|
+
const RETRY_MS = 300;
|
|
22
|
+
const MAX_TRIES = 100;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Runs one of the app's mobile.events (onNotification, onNotificationAction, onShare, onShortcut,
|
|
26
|
+
* onGeofence, onRequestQueue) with an event object. The app context is made when the first page
|
|
27
|
+
* renders, so an event that arrives before it (a notification tap that launched the app) waits for
|
|
28
|
+
* it, trying every 300 ms for up to 30 seconds. Never throws: an app event's failure is reported by
|
|
29
|
+
* the engine's own error handling, and an event that never ran (no app context came, or the engine
|
|
30
|
+
* itself threw) is reported here.
|
|
31
|
+
*
|
|
32
|
+
* @param {Object} params
|
|
33
|
+
* @param {Object} params.session The app session (createAppSession).
|
|
34
|
+
*/
|
|
35
|
+
function createAppEventTrigger({ session }) {
|
|
36
|
+
return function triggerAppEvent({ name, event }) {
|
|
37
|
+
let tries = 0;
|
|
38
|
+
return new Promise((resolve) => {
|
|
39
|
+
function attempt() {
|
|
40
|
+
const appContext = session.getState().lowdefy?.appContext;
|
|
41
|
+
if (appContext === undefined || appContext === null) {
|
|
42
|
+
tries += 1;
|
|
43
|
+
if (tries > MAX_TRIES) {
|
|
44
|
+
reportShellError({
|
|
45
|
+
error: new LowdefyInternalError(
|
|
46
|
+
`App event "${name}" was dropped: no page created the app context within ${
|
|
47
|
+
(RETRY_MS * MAX_TRIES) / 1000
|
|
48
|
+
} seconds.`
|
|
49
|
+
),
|
|
50
|
+
session,
|
|
51
|
+
});
|
|
52
|
+
resolve(null);
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
setTimeout(attempt, RETRY_MS);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
Promise.resolve(appContext._internal.triggerPageEvent({ name, event }))
|
|
59
|
+
.catch((error) => {
|
|
60
|
+
reportShellError({ error, session });
|
|
61
|
+
return null;
|
|
62
|
+
})
|
|
63
|
+
.then(resolve);
|
|
64
|
+
}
|
|
65
|
+
attempt();
|
|
66
|
+
});
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export default createAppEventTrigger;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2020-2026 Lowdefy, Inc
|
|
3
|
+
|
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
you may not use this file except in compliance with the License.
|
|
6
|
+
You may obtain a copy of the License at
|
|
7
|
+
|
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
|
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
See the License for the specific language governing permissions and
|
|
14
|
+
limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
// The app the shell has open, for native work that starts outside React: a notification button
|
|
18
|
+
// pressed with the app in the background, a background fetch, a geofence crossing. AppProvider sets
|
|
19
|
+
// it once the app's auth and session exist; work started before then waits for it.
|
|
20
|
+
let current = null;
|
|
21
|
+
let waiting = [];
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* @param {Object|null} app { apiBase, auth, fetch, router, session, shell, tokenStore,
|
|
25
|
+
* triggerAppEvent }, or null when the app closes (a sign-out opens it afresh).
|
|
26
|
+
*/
|
|
27
|
+
function setCurrentApp(app) {
|
|
28
|
+
current = app;
|
|
29
|
+
if (app !== null) {
|
|
30
|
+
waiting.splice(0).forEach((resolve) => resolve(app));
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// The open app, once there is one.
|
|
35
|
+
function getCurrentApp() {
|
|
36
|
+
if (current !== null) {
|
|
37
|
+
return Promise.resolve(current);
|
|
38
|
+
}
|
|
39
|
+
return new Promise((resolve) => {
|
|
40
|
+
waiting.push(resolve);
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// The open app, or null: for work that only makes sense while one is open.
|
|
45
|
+
function peekCurrentApp() {
|
|
46
|
+
return current;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export { getCurrentApp, peekCurrentApp, setCurrentApp };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2020-2026 Lowdefy, Inc
|
|
3
|
+
|
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
you may not use this file except in compliance with the License.
|
|
6
|
+
You may obtain a copy of the License at
|
|
7
|
+
|
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
|
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
See the License for the specific language governing permissions and
|
|
14
|
+
limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* The path of a page in the app's root page index, or null when the caller cannot open it.
|
|
19
|
+
*
|
|
20
|
+
* @param {Object} params
|
|
21
|
+
* @param {Object} params.root The mobile root.
|
|
22
|
+
* @param {string} params.pageId
|
|
23
|
+
*/
|
|
24
|
+
function getPagePath({ pageId, root }) {
|
|
25
|
+
const entry = (root?.pageIndex ?? []).find((item) => item.pageId === pageId);
|
|
26
|
+
if (entry === undefined) {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
return entry.path.startsWith('/') ? entry.path : `/${entry.path}`;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export default getPagePath;
|