@microsoft/power-apps-native-host 0.2.25 → 0.3.3
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/README.md +21 -10
- package/compatibility/current.json +31 -4
- package/lib/NOTICE.txt +1325 -24
- package/lib/commonjs/auth/AuthContext.js +110 -33
- package/lib/commonjs/bridge/NativePowerAppsBridge.js +11 -18
- package/lib/commonjs/bridge/PowerPagesBridge.js +27 -8
- package/lib/commonjs/bridge/bridgeState.js +40 -0
- package/lib/commonjs/config/babelConfig.js +13 -0
- package/lib/commonjs/config/expoConfig.js +71 -0
- package/lib/commonjs/config/metroConfig.js +70 -0
- package/lib/commonjs/config/metroLogger.js +182 -0
- package/lib/commonjs/config/tamaguiConfig.js +98 -0
- package/lib/commonjs/connections/ConnectionSetupScreen.js +459 -80
- package/lib/commonjs/connections/PowerPlatformConnectionApi.js +946 -0
- package/lib/commonjs/connections/connectionMetadata.js +127 -0
- package/lib/commonjs/connections/connectionState.js +96 -0
- package/lib/commonjs/connections/disambiguate.js +19 -11
- package/lib/commonjs/connections/resolveConnections.js +348 -0
- package/lib/commonjs/connections/types.js +106 -0
- package/lib/commonjs/{platform → connections}/useConnectionRefs.js +130 -65
- package/lib/commonjs/connections/useConnectionSetup.js +111 -52
- package/lib/commonjs/controls/FilePicker.js +6 -0
- package/lib/commonjs/controls/ImagePicker.js +8 -0
- package/lib/commonjs/index.js +167 -4
- package/lib/commonjs/logger.js +9 -6
- package/lib/commonjs/offline/createOfflineHostActivationCallbacks.js +61 -0
- package/lib/commonjs/offline/useOfflineIntegrationWithStartupGate.js +48 -0
- package/lib/commonjs/offline/useOfflineIntegrationWithStartupGate.web.js +13 -0
- package/lib/commonjs/platform/DataverseDataSources.js +18 -0
- package/lib/commonjs/platform/DataverseGlobalDiscoveryApi.js +94 -0
- package/lib/commonjs/platform/GlobalDiscovery.js +51 -0
- package/lib/commonjs/platform/PowerPlatformEnvironmentApi.js +6 -106
- package/lib/commonjs/provider/PowerAppsHostProvider.js +157 -25
- package/lib/commonjs/provider/PowerAppsProvider.js +178 -134
- package/lib/commonjs/provider/SessionDetailsGesture.js +208 -0
- package/lib/commonjs/telemetry/OfflineSdkTelemetry.js +95 -0
- package/lib/commonjs/telemetry/OfflineSdkTelemetry.web.js +9 -0
- package/lib/commonjs/telemetry/index.js +22 -3
- package/lib/module/auth/AuthContext.js +110 -33
- package/lib/module/bridge/NativePowerAppsBridge.js +12 -19
- package/lib/module/bridge/PowerPagesBridge.js +27 -8
- package/lib/module/bridge/bridgeState.js +34 -0
- package/lib/module/config/babelConfig.js +9 -0
- package/lib/module/config/expoConfig.js +67 -0
- package/lib/module/config/metroConfig.js +65 -0
- package/lib/module/config/metroLogger.js +175 -0
- package/lib/module/config/tamaguiConfig.js +93 -0
- package/lib/module/connections/ConnectionSetupScreen.js +460 -81
- package/lib/module/connections/PowerPlatformConnectionApi.js +932 -0
- package/lib/module/connections/connectionMetadata.js +112 -0
- package/lib/module/connections/connectionState.js +82 -0
- package/lib/module/connections/disambiguate.js +19 -12
- package/lib/module/connections/resolveConnections.js +343 -0
- package/lib/module/connections/types.js +91 -0
- package/lib/module/{platform → connections}/useConnectionRefs.js +131 -66
- package/lib/module/connections/useConnectionSetup.js +113 -54
- package/lib/module/controls/FilePicker.js +6 -0
- package/lib/module/controls/ImagePicker.js +8 -0
- package/lib/module/index.js +14 -4
- package/lib/module/logger.js +8 -6
- package/lib/module/offline/createOfflineHostActivationCallbacks.js +55 -0
- package/lib/module/offline/useOfflineIntegrationWithStartupGate.js +44 -0
- package/lib/module/offline/useOfflineIntegrationWithStartupGate.web.js +9 -0
- package/lib/module/platform/DataverseDataSources.js +13 -0
- package/lib/module/platform/DataverseGlobalDiscoveryApi.js +89 -0
- package/lib/module/platform/GlobalDiscovery.js +45 -0
- package/lib/module/platform/PowerPlatformEnvironmentApi.js +5 -104
- package/lib/module/provider/PowerAppsHostProvider.js +160 -28
- package/lib/module/provider/PowerAppsProvider.js +182 -138
- package/lib/module/provider/SessionDetailsGesture.js +203 -0
- package/lib/module/telemetry/OfflineSdkTelemetry.js +91 -0
- package/lib/module/telemetry/OfflineSdkTelemetry.web.js +5 -0
- package/lib/module/telemetry/index.js +15 -4
- package/lib/typescript/commonjs/auth/AuthContext.d.ts +3 -1
- package/lib/typescript/commonjs/auth/AuthContext.web.d.ts +1 -0
- package/lib/typescript/commonjs/bridge/bridgeState.d.ts +5 -0
- package/lib/typescript/commonjs/config/babelConfig.d.ts +12 -0
- package/lib/typescript/commonjs/config/expoConfig.d.ts +21 -0
- package/lib/typescript/commonjs/config/metroConfig.d.ts +6 -0
- package/lib/typescript/commonjs/config/metroLogger.d.ts +21 -0
- package/lib/typescript/commonjs/config/tamaguiConfig.d.ts +1792 -0
- package/lib/typescript/commonjs/connections/ConnectionSetupScreen.d.ts +28 -7
- package/lib/typescript/commonjs/{platform → connections}/PowerPlatformConnectionApi.d.ts +52 -43
- package/lib/typescript/commonjs/connections/connectionMetadata.d.ts +66 -0
- package/lib/typescript/commonjs/connections/connectionState.d.ts +16 -0
- package/lib/typescript/commonjs/connections/disambiguate.d.ts +4 -2
- package/lib/typescript/commonjs/{platform → connections}/resolveConnections.d.ts +22 -20
- package/lib/typescript/commonjs/connections/types.d.ts +129 -1
- package/lib/typescript/commonjs/{platform → connections}/useConnectionRefs.d.ts +36 -25
- package/lib/typescript/commonjs/connections/useConnectionSetup.d.ts +12 -8
- package/lib/typescript/commonjs/controls/FilePicker.d.ts +7 -1
- package/lib/typescript/commonjs/controls/ImagePicker.d.ts +9 -1
- package/lib/typescript/commonjs/index.d.ts +18 -10
- package/lib/typescript/commonjs/logger.d.ts +4 -4
- package/lib/typescript/commonjs/offline/createOfflineHostActivationCallbacks.d.ts +12 -0
- package/lib/typescript/commonjs/offline/useOfflineIntegrationWithStartupGate.d.ts +15 -0
- package/lib/typescript/commonjs/offline/useOfflineIntegrationWithStartupGate.web.d.ts +6 -0
- package/lib/typescript/commonjs/platform/DataverseDataSources.d.ts +28 -0
- package/lib/typescript/commonjs/platform/DataverseGlobalDiscoveryApi.d.ts +3 -0
- package/lib/typescript/commonjs/platform/GlobalDiscovery.d.ts +4 -0
- package/lib/typescript/commonjs/platform/PowerPlatformEnvironmentApi.d.ts +3 -74
- package/lib/typescript/commonjs/provider/PowerAppsHostProvider.d.ts +29 -18
- package/lib/typescript/commonjs/provider/PowerAppsProvider.d.ts +54 -9
- package/lib/typescript/commonjs/provider/SessionDetailsGesture.d.ts +13 -0
- package/lib/typescript/commonjs/telemetry/OfflineSdkTelemetry.d.ts +15 -0
- package/lib/typescript/commonjs/telemetry/OfflineSdkTelemetry.web.d.ts +2 -0
- package/lib/typescript/commonjs/telemetry/index.d.ts +13 -1
- package/lib/typescript/module/auth/AuthContext.d.ts +3 -1
- package/lib/typescript/module/auth/AuthContext.web.d.ts +1 -0
- package/lib/typescript/module/bridge/bridgeState.d.ts +5 -0
- package/lib/typescript/module/config/babelConfig.d.ts +12 -0
- package/lib/typescript/module/config/expoConfig.d.ts +21 -0
- package/lib/typescript/module/config/metroConfig.d.ts +6 -0
- package/lib/typescript/module/config/metroLogger.d.ts +21 -0
- package/lib/typescript/module/config/tamaguiConfig.d.ts +1792 -0
- package/lib/typescript/module/connections/ConnectionSetupScreen.d.ts +28 -7
- package/lib/typescript/module/{platform → connections}/PowerPlatformConnectionApi.d.ts +52 -43
- package/lib/typescript/module/connections/connectionMetadata.d.ts +66 -0
- package/lib/typescript/module/connections/connectionState.d.ts +16 -0
- package/lib/typescript/module/connections/disambiguate.d.ts +4 -2
- package/lib/typescript/module/{platform → connections}/resolveConnections.d.ts +22 -20
- package/lib/typescript/module/connections/types.d.ts +129 -1
- package/lib/typescript/module/{platform → connections}/useConnectionRefs.d.ts +36 -25
- package/lib/typescript/module/connections/useConnectionSetup.d.ts +12 -8
- package/lib/typescript/module/controls/FilePicker.d.ts +7 -1
- package/lib/typescript/module/controls/ImagePicker.d.ts +9 -1
- package/lib/typescript/module/index.d.ts +18 -10
- package/lib/typescript/module/logger.d.ts +4 -4
- package/lib/typescript/module/offline/createOfflineHostActivationCallbacks.d.ts +12 -0
- package/lib/typescript/module/offline/useOfflineIntegrationWithStartupGate.d.ts +15 -0
- package/lib/typescript/module/offline/useOfflineIntegrationWithStartupGate.web.d.ts +6 -0
- package/lib/typescript/module/platform/DataverseDataSources.d.ts +28 -0
- package/lib/typescript/module/platform/DataverseGlobalDiscoveryApi.d.ts +3 -0
- package/lib/typescript/module/platform/GlobalDiscovery.d.ts +4 -0
- package/lib/typescript/module/platform/PowerPlatformEnvironmentApi.d.ts +3 -74
- package/lib/typescript/module/provider/PowerAppsHostProvider.d.ts +29 -18
- package/lib/typescript/module/provider/PowerAppsProvider.d.ts +54 -9
- package/lib/typescript/module/provider/SessionDetailsGesture.d.ts +13 -0
- package/lib/typescript/module/telemetry/OfflineSdkTelemetry.d.ts +15 -0
- package/lib/typescript/module/telemetry/OfflineSdkTelemetry.web.d.ts +2 -0
- package/lib/typescript/module/telemetry/index.d.ts +13 -1
- package/package.json +52 -13
- package/scripts/build-codegen-package.js +283 -0
- package/scripts/start-web.mjs +9 -5
- package/scripts/upgrade/runtime.js +139 -24
- package/scripts/upgrade-authoring.js +274 -180
- package/scripts/upgrade.js +10 -16
- package/src/config/generated-config.d.ts +4 -0
- package/src/config/index.d.ts +3 -0
- package/src/config/tsconfig.json +26 -0
- package/lib/commonjs/platform/PowerPlatformConnectionApi.js +0 -606
- package/lib/commonjs/platform/resolveConnections.js +0 -264
- package/lib/module/platform/PowerPlatformConnectionApi.js +0 -595
- package/lib/module/platform/resolveConnections.js +0 -259
|
@@ -27,25 +27,29 @@
|
|
|
27
27
|
* </PowerAppsProvider>
|
|
28
28
|
*/
|
|
29
29
|
|
|
30
|
-
import React, {
|
|
30
|
+
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
|
31
31
|
import { AppState, Platform, ScrollView, StyleSheet, Text } from 'react-native';
|
|
32
32
|
import { GestureHandlerRootView } from 'react-native-gesture-handler';
|
|
33
33
|
import { createTamagui, TamaguiProvider } from '@tamagui/core';
|
|
34
34
|
import { PortalProvider } from '@tamagui/portal';
|
|
35
35
|
import { defaultConfig as tamaguiDefaultConfig } from '@tamagui/config/v5';
|
|
36
36
|
import { ToastProvider, ToastViewport } from '@tamagui/toast';
|
|
37
|
-
import {
|
|
37
|
+
import { QueryClientProvider, focusManager, onlineManager } from '@tanstack/react-query';
|
|
38
38
|
import NetInfo from '@react-native-community/netinfo';
|
|
39
39
|
import { AuthProvider, useAuth } from '../auth/AuthContext';
|
|
40
40
|
import { PowerAppsHostProvider } from './PowerAppsHostProvider';
|
|
41
|
-
import {
|
|
41
|
+
import { powerPlatformScope } from "../platform/PowerPlatformEnvironmentApi.js";
|
|
42
42
|
import { ThemeProvider } from "../theme/ThemeProvider.js";
|
|
43
43
|
import { ErrorBoundary } from "../ErrorBoundary.js";
|
|
44
44
|
import { isDevPlayer } from "../utils/isDevPlayer.js";
|
|
45
|
+
import * as Application from 'expo-application';
|
|
45
46
|
import Constants from 'expo-constants';
|
|
46
|
-
import { configureAppLogger, getAppLogger, Logger, OneDsTelemetryProvider, resolveDeviceId, resolveTelemetryLocation, regionToClusterCategory, suppressKnownWarnings } from '@microsoft/power-apps-native-common';
|
|
47
|
+
import { ApplicationInsightsTelemetryProvider, configureAppLogger, configureCustomerTelemetryLogger, getAppLogger, Logger, OneDsTelemetryProvider, resolveDeviceId, resolveTelemetryLocation, regionToClusterCategory, suppressKnownWarnings } from '@microsoft/power-apps-native-common';
|
|
47
48
|
suppressKnownWarnings();
|
|
48
|
-
import {
|
|
49
|
+
import { createHostQueryClient } from "../offline/createOfflineHostActivationCallbacks.js";
|
|
50
|
+
import { useOfflineIntegrationWithStartupGate } from '../offline/useOfflineIntegrationWithStartupGate';
|
|
51
|
+
import { SessionDetailsGesture } from "./SessionDetailsGesture.js";
|
|
52
|
+
import { configureOfflineSdkTelemetry } from '../telemetry/OfflineSdkTelemetry';
|
|
49
53
|
|
|
50
54
|
// ---- React-Query wiring (runs once at module load) ----
|
|
51
55
|
|
|
@@ -56,7 +60,6 @@ onlineManager.setEventListener(setOnline => {
|
|
|
56
60
|
if (Platform.OS === 'web' && typeof window !== 'undefined') {
|
|
57
61
|
const updateOnlineState = () => setOnline(window.navigator.onLine);
|
|
58
62
|
window.addEventListener('online', updateOnlineState);
|
|
59
|
-
window.addEventListener('offline', updateOnlineState);
|
|
60
63
|
updateOnlineState();
|
|
61
64
|
return () => {
|
|
62
65
|
window.removeEventListener('online', updateOnlineState);
|
|
@@ -81,86 +84,14 @@ focusManager.setEventListener(handleFocus => {
|
|
|
81
84
|
// The bare @tamagui/config/v5 preset is only a last-resort fallback for tests
|
|
82
85
|
// and storybook — it will not resolve custom $surface* tokens.
|
|
83
86
|
const defaultTamaguiConfig = createTamagui(tamaguiDefaultConfig);
|
|
84
|
-
|
|
85
|
-
// Whether the offline SDK will actually orchestrate for this app. Mirrors the
|
|
86
|
-
// resolution that @microsoft/power-apps-native-offline's useOfflineIntegration
|
|
87
|
-
// performs (offlineProfile prop → expo manifest `extra.__offlineProfile`;
|
|
88
|
-
// enabled defaults true unless the profile's `appConfig.enabled` is explicitly
|
|
89
|
-
// false), but computed synchronously here because the QueryClient's networkMode
|
|
90
|
-
// must be fixed BEFORE the first query runs. The SDK's own `isEnabled` is only
|
|
91
|
-
// known deep inside the tree (below QueryClientProvider), which is too late to
|
|
92
|
-
// configure the client without a race. Kept deliberately narrow: it only
|
|
93
|
-
// decides networkMode below.
|
|
94
|
-
function isOfflineEnabled(offlineProfile) {
|
|
95
|
-
if (Platform.OS === 'web') return false;
|
|
96
|
-
// Only honour the prop when it carries a profileId — this mirrors the SDK's
|
|
97
|
-
// useOfflineIntegration, which ignores a profileId-less prop and falls through
|
|
98
|
-
// to the manifest. Without this guard a truthy-but-invalid prop (no profileId)
|
|
99
|
-
// short-circuits to `false` here while the SDK still resolves enabled from the
|
|
100
|
-
// manifest, leaving networkMode on 'online' (blank offline lists).
|
|
101
|
-
const propProfile = offlineProfile;
|
|
102
|
-
let profile = propProfile && propProfile.profileId ? propProfile : undefined;
|
|
103
|
-
if (!profile) {
|
|
104
|
-
const fromManifest = Constants.expoConfig?.extra?.__offlineProfile;
|
|
105
|
-
if (fromManifest && typeof fromManifest === 'object' && fromManifest.profileId) {
|
|
106
|
-
profile = fromManifest;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
if (profile) {
|
|
110
|
-
// Honour an explicit `appConfig.enabled: false`. This mirrors the SDK's
|
|
111
|
-
// useOfflineIntegration, whose validateConfig classifies `enabled === false`
|
|
112
|
-
// as "explicitly-disabled" and stays inert. A host shell's placeholder
|
|
113
|
-
// profile (e.g. Power Apps Dev Player's offline-profile.json, enabled:false)
|
|
114
|
-
// must NOT flip networkMode to 'always' for the loaded app — otherwise every
|
|
115
|
-
// scanned app gets paused queries / blank lists. Any other resolved profile
|
|
116
|
-
// (enabled true, or omitted → SDK defaults to true) enables offline.
|
|
117
|
-
const appConfig = profile.appConfig;
|
|
118
|
-
if (appConfig && appConfig.enabled === false) {
|
|
119
|
-
return false;
|
|
120
|
-
}
|
|
121
|
-
return true;
|
|
122
|
-
}
|
|
123
|
-
return false;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
// Builds the app's QueryClient. networkMode is gated on whether offline is
|
|
127
|
-
// actually enabled:
|
|
128
|
-
// • Offline enabled → 'always': the host is offline-first, so reads/writes are
|
|
129
|
-
// served by the offline SDK from local SQLite regardless of connectivity.
|
|
130
|
-
// onlineManager is wired to NetInfo (above) for refetchOnReconnect, but that
|
|
131
|
-
// same wiring makes the default 'online' mode PAUSE every query/mutation while
|
|
132
|
-
// offline (queryFn never runs → blank lists with WiFi off). 'always' makes
|
|
133
|
-
// React Query ignore connectivity for both the initial attempt AND retries, so
|
|
134
|
-
// local-SQLite reads/writes never get paused. ('offlineFirst' would still pause
|
|
135
|
-
// *retries* offline — wrong for a purely-local SDK where a transient first
|
|
136
|
-
// attempt error, e.g. SDK-not-ready at cold boot, would leave the query stuck
|
|
137
|
-
// 'paused' until reconnect.)
|
|
138
|
-
// • Offline disabled → undefined: React Query keeps its default 'online' mode,
|
|
139
|
-
// i.e. the exact pre-offline behaviour for online-only apps.
|
|
140
|
-
function createQueryClient(offlineEnabled) {
|
|
141
|
-
const networkMode = offlineEnabled ? 'always' : undefined;
|
|
142
|
-
return new QueryClient({
|
|
143
|
-
defaultOptions: {
|
|
144
|
-
queries: {
|
|
145
|
-
staleTime: 60_000,
|
|
146
|
-
retry: 2,
|
|
147
|
-
networkMode
|
|
148
|
-
},
|
|
149
|
-
mutations: {
|
|
150
|
-
retry: 0,
|
|
151
|
-
networkMode
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
});
|
|
155
|
-
}
|
|
156
87
|
function hasConfiguredValue(value) {
|
|
157
88
|
return typeof value === 'string' && value.trim().length > 0;
|
|
158
89
|
}
|
|
159
90
|
function hasEntries(value) {
|
|
160
91
|
return Boolean(value && typeof value === 'object' && Object.keys(value).length > 0);
|
|
161
92
|
}
|
|
162
|
-
function requiresPowerPlatformAuth(powerConfig
|
|
163
|
-
return Boolean(hasConfiguredValue(powerConfig.appId) || hasConfiguredValue(powerConfig.environmentId) || hasEntries(powerConfig.connectionReferences) || hasEntries(powerConfig.databaseReferences)
|
|
93
|
+
function requiresPowerPlatformAuth(powerConfig) {
|
|
94
|
+
return Boolean(hasConfiguredValue(powerConfig.appId) || hasConfiguredValue(powerConfig.environmentId) || hasEntries(powerConfig.connectionReferences) || hasEntries(powerConfig.databaseReferences));
|
|
164
95
|
}
|
|
165
96
|
function MissingClientIdErrorScreen() {
|
|
166
97
|
return /*#__PURE__*/_jsxs(ScrollView, {
|
|
@@ -177,11 +108,58 @@ function MissingClientIdErrorScreen() {
|
|
|
177
108
|
})]
|
|
178
109
|
});
|
|
179
110
|
}
|
|
111
|
+
function MissingAppIdErrorScreen() {
|
|
112
|
+
return /*#__PURE__*/_jsxs(ScrollView, {
|
|
113
|
+
contentContainerStyle: styles.errorContainer,
|
|
114
|
+
children: [/*#__PURE__*/_jsx(Text, {
|
|
115
|
+
style: styles.errorTitle,
|
|
116
|
+
children: "App ID is missing"
|
|
117
|
+
}), /*#__PURE__*/_jsx(Text, {
|
|
118
|
+
style: styles.errorBody,
|
|
119
|
+
children: "This mobile app does not include an app ID. Push the mobile app to the Power Platform environment, rebuild it, and try again."
|
|
120
|
+
})]
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
function MissingEnvironmentIdErrorScreen() {
|
|
124
|
+
return /*#__PURE__*/_jsxs(ScrollView, {
|
|
125
|
+
contentContainerStyle: styles.errorContainer,
|
|
126
|
+
children: [/*#__PURE__*/_jsx(Text, {
|
|
127
|
+
style: styles.errorTitle,
|
|
128
|
+
children: "Environment ID is missing"
|
|
129
|
+
}), /*#__PURE__*/_jsx(Text, {
|
|
130
|
+
style: styles.errorBody,
|
|
131
|
+
children: "This mobile app does not include an environment ID. Push the mobile app to the Power Platform environment, rebuild it, and try again."
|
|
132
|
+
})]
|
|
133
|
+
});
|
|
134
|
+
}
|
|
180
135
|
|
|
181
136
|
// ---- Types ----
|
|
182
137
|
|
|
183
138
|
/** Shape of power.config.json consumed by the provider. */
|
|
184
139
|
|
|
140
|
+
function readAppInsightsConfig(value) {
|
|
141
|
+
if (!value || typeof value !== 'object') return undefined;
|
|
142
|
+
const config = value;
|
|
143
|
+
const minSeverity = config.minSeverity;
|
|
144
|
+
return {
|
|
145
|
+
enabled: config.enabled === true,
|
|
146
|
+
connectionString: typeof config.connectionString === 'string' ? config.connectionString : '',
|
|
147
|
+
appId: typeof config.appId === 'string' ? config.appId : '',
|
|
148
|
+
...(typeof config.appVersion === 'string' ? {
|
|
149
|
+
appVersion: config.appVersion
|
|
150
|
+
} : {}),
|
|
151
|
+
...(typeof config.environment === 'string' ? {
|
|
152
|
+
environment: config.environment
|
|
153
|
+
} : {}),
|
|
154
|
+
...(minSeverity === 'verbose' || minSeverity === 'info' || minSeverity === 'warning' || minSeverity === 'error' ? {
|
|
155
|
+
minSeverity
|
|
156
|
+
} : {}),
|
|
157
|
+
...(typeof config.includeUserId === 'boolean' ? {
|
|
158
|
+
includeUserId: config.includeUserId
|
|
159
|
+
} : {})
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
|
|
185
163
|
// ---- Inner component ----
|
|
186
164
|
// Separate from PowerAppsProvider only because useAuth() must be called inside
|
|
187
165
|
// AuthProvider. All auth-dependent wiring lives here.
|
|
@@ -192,53 +170,49 @@ function InnerProviders({
|
|
|
192
170
|
schemaMap,
|
|
193
171
|
renderOAuthWebView,
|
|
194
172
|
onDisambiguationNeeded,
|
|
173
|
+
onConnectionConsent,
|
|
174
|
+
onResourceConsent,
|
|
175
|
+
onConnectionConsentDeclined,
|
|
195
176
|
offlineProfile,
|
|
177
|
+
onOfflineEnabledChange,
|
|
196
178
|
children
|
|
197
179
|
}) {
|
|
198
180
|
const {
|
|
199
181
|
acquireToken,
|
|
200
182
|
isSignedIn,
|
|
201
|
-
hasRealAccount
|
|
183
|
+
hasRealAccount,
|
|
184
|
+
isAuthReady,
|
|
185
|
+
signOut
|
|
202
186
|
} = useAuth();
|
|
203
|
-
const connectionReferences = useMemo(() => powerConfig.connectionReferences ?? {}, [powerConfig.connectionReferences]);
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
// Adapter over the host's fetchInstanceUrl: the offline SDK's contract passes a
|
|
207
|
-
// 4th `signal?: AbortSignal` arg (which fetchInstanceUrl treats as bearerToken)
|
|
208
|
-
// and expects a `string | null` return, so drop the extra arg and normalise
|
|
209
|
-
// `undefined` -> `null`.
|
|
210
|
-
const resolveInstanceUrlForOffline = useCallback(async (environmentId, region, acqToken, _signal) => {
|
|
211
|
-
const url = await fetchInstanceUrl(environmentId, region, acqToken);
|
|
212
|
-
return url ?? null;
|
|
213
|
-
}, []);
|
|
214
|
-
|
|
215
|
-
// Gate offline engagement on a REAL account (`hasRealAccount`), not the
|
|
216
|
-
// `isSignedIn` flag — `isSignedIn` is inflated by noAuthMode (login-bypassed /
|
|
217
|
-
// demo sessions report signed-in but have no account, so `acquireToken` always
|
|
218
|
-
// returns null). Passing the inflated flag makes the SDK orchestrator engage
|
|
219
|
-
// and then spin in a perpetual "waiting-for-auth" 3s retry loop (each retry
|
|
220
|
-
// re-renders the provider subtree). With no obtainable token offline cannot
|
|
221
|
-
// sync anyway, so we only engage once a usable token exists.
|
|
222
|
-
const offline = useOfflineIntegration({
|
|
187
|
+
const connectionReferences = useMemo(() => isDevPlayer ? powerConfig.connectionReferences ?? {} : {}, [powerConfig.connectionReferences, isDevPlayer]);
|
|
188
|
+
const runtimeSchemaMap = useMemo(() => isDevPlayer ? schemaMap : {}, [schemaMap, isDevPlayer]);
|
|
189
|
+
const offline = useOfflineIntegrationWithStartupGate({
|
|
223
190
|
powerConfig,
|
|
224
191
|
offlineProfile,
|
|
225
192
|
acquireToken,
|
|
226
|
-
|
|
227
|
-
|
|
193
|
+
hasRealAccount,
|
|
194
|
+
isAuthReady
|
|
228
195
|
});
|
|
196
|
+
useEffect(() => {
|
|
197
|
+
onOfflineEnabledChange(offline.isEnabled);
|
|
198
|
+
}, [offline.isEnabled, onOfflineEnabledChange]);
|
|
229
199
|
return /*#__PURE__*/_jsxs(PowerAppsHostProvider, {
|
|
230
200
|
acquireToken: acquireToken,
|
|
231
201
|
isSignedIn: isSignedIn,
|
|
202
|
+
onSignOut: signOut,
|
|
232
203
|
appId: powerConfig.appId ?? undefined,
|
|
233
204
|
environmentId: powerConfig.environmentId ?? '',
|
|
234
205
|
region: powerConfig.region ?? 'prod',
|
|
235
206
|
connectionReferences: connectionReferences,
|
|
236
|
-
schemaMap:
|
|
237
|
-
databaseReferences: powerConfig.databaseReferences,
|
|
207
|
+
schemaMap: runtimeSchemaMap,
|
|
208
|
+
databaseReferences: isDevPlayer ? powerConfig.databaseReferences : undefined,
|
|
238
209
|
isvClientId: msalConfig.clientId,
|
|
239
210
|
renderOAuthWebView: renderOAuthWebView,
|
|
240
211
|
onDisambiguationNeeded: onDisambiguationNeeded,
|
|
241
|
-
|
|
212
|
+
onConnectionConsent: onConnectionConsent,
|
|
213
|
+
onResourceConsent: onResourceConsent,
|
|
214
|
+
onConnectionConsentDeclined: onConnectionConsentDeclined,
|
|
215
|
+
children: [offline.shouldMountChildren && children, offline.StatusOverlay && /*#__PURE__*/_jsx(offline.StatusOverlay, {})]
|
|
242
216
|
});
|
|
243
217
|
}
|
|
244
218
|
|
|
@@ -253,6 +227,7 @@ function InnerProviders({
|
|
|
253
227
|
* root layout.
|
|
254
228
|
*/
|
|
255
229
|
export function PowerAppsProvider({
|
|
230
|
+
appConfig,
|
|
256
231
|
msalConfig,
|
|
257
232
|
intuneConfig,
|
|
258
233
|
powerConfig,
|
|
@@ -265,8 +240,14 @@ export function PowerAppsProvider({
|
|
|
265
240
|
followSystemTheme = true,
|
|
266
241
|
renderOAuthWebView,
|
|
267
242
|
onDisambiguationNeeded,
|
|
243
|
+
onConnectionConsent,
|
|
244
|
+
onResourceConsent,
|
|
245
|
+
onConnectionConsentDeclined,
|
|
268
246
|
appName,
|
|
269
247
|
logger: loggerProp,
|
|
248
|
+
showSessionDetailsOnLongPress,
|
|
249
|
+
showSessionDetailsOnSwipe,
|
|
250
|
+
appInsightsConfig,
|
|
270
251
|
offlineProfile,
|
|
271
252
|
children
|
|
272
253
|
}) {
|
|
@@ -274,14 +255,19 @@ export function PowerAppsProvider({
|
|
|
274
255
|
// is stable (loggerProp is an object reference; re-running on every render
|
|
275
256
|
// would reconfigure and leak the previous provider).
|
|
276
257
|
const loggerPropRef = useRef(loggerProp);
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
const
|
|
283
|
-
const
|
|
284
|
-
const
|
|
258
|
+
const appInsightsConfigRef = useRef(appInsightsConfig ?? readAppInsightsConfig(appConfig?.expo?.extra?.appInsightsConfig ?? Constants.expoConfig?.extra?.appInsightsConfig));
|
|
259
|
+
const [offlineTelemetryEnabled, setOfflineTelemetryEnabled] = useState();
|
|
260
|
+
const missingClientIdInDevPlayer = Platform.OS !== 'web' && isDevPlayer && !hasConfiguredValue(msalConfig.clientId) && requiresPowerPlatformAuth(powerConfig);
|
|
261
|
+
const missingAppId = Platform.OS !== 'web' && !isDevPlayer && !hasConfiguredValue(powerConfig.appId);
|
|
262
|
+
const missingEnvironmentId = !isDevPlayer && !hasConfiguredValue(powerConfig.environmentId);
|
|
263
|
+
const appId = typeof powerConfig.appId === 'string' ? powerConfig.appId.trim() : '';
|
|
264
|
+
const configuredBundleId = Platform.OS === 'ios' ? Constants.expoConfig?.ios?.bundleIdentifier : Platform.OS === 'android' ? Constants.expoConfig?.android?.package : undefined;
|
|
265
|
+
const bundleId = Platform.OS === 'ios' || Platform.OS === 'android' ? Application.applicationId ?? configuredBundleId : undefined;
|
|
266
|
+
const appInstanceId = Constants.expoConfig?.extra?.telemetry?.appInstanceId;
|
|
267
|
+
const skillCorrelationId = typeof appInstanceId === 'string' ? appInstanceId.trim() : '';
|
|
268
|
+
const sessionDetailsGestureEnabled = showSessionDetailsOnLongPress ?? showSessionDetailsOnSwipe ?? true;
|
|
269
|
+
const requiredAuthScopes = useMemo(() => [powerPlatformScope(powerConfig.region ?? 'prod')], [powerConfig.region]);
|
|
270
|
+
const queryClient = useMemo(() => createHostQueryClient(), []);
|
|
285
271
|
|
|
286
272
|
// Configure the app logger exactly once per mount inside useEffect so that
|
|
287
273
|
// side effects (provider construction, async resolveDeviceId) never run
|
|
@@ -289,6 +275,9 @@ export function PowerAppsProvider({
|
|
|
289
275
|
// silent no-op Logger, so any telemetry emitted before the first commit is
|
|
290
276
|
// silently dropped rather than crashing.
|
|
291
277
|
useEffect(() => {
|
|
278
|
+
// Customer telemetry is a no-op until a valid Application Insights
|
|
279
|
+
// provider is configured below.
|
|
280
|
+
configureCustomerTelemetryLogger(new Logger());
|
|
292
281
|
const lp = loggerPropRef.current;
|
|
293
282
|
if (lp === null) {
|
|
294
283
|
// Explicit opt-out — replace with a silent no-op Logger.
|
|
@@ -304,26 +293,63 @@ export function PowerAppsProvider({
|
|
|
304
293
|
clientType: appName ?? 'PowerAppsNative',
|
|
305
294
|
appVersion: Constants.expoConfig?.version,
|
|
306
295
|
minSeverity: __DEV__ ? 'verbose' : 'info',
|
|
307
|
-
telemetryLocation: resolveTelemetryLocation(powerConfig.geoRegion)
|
|
296
|
+
telemetryLocation: resolveTelemetryLocation(powerConfig.geoRegion),
|
|
297
|
+
commonProperties: {
|
|
298
|
+
...(appId ? {
|
|
299
|
+
appId
|
|
300
|
+
} : {}),
|
|
301
|
+
...(bundleId ? {
|
|
302
|
+
bundleId
|
|
303
|
+
} : {}),
|
|
304
|
+
...(skillCorrelationId ? {
|
|
305
|
+
skillCorrelationId
|
|
306
|
+
} : {})
|
|
307
|
+
}
|
|
308
|
+
};
|
|
309
|
+
const configureDefaultLogger = (deviceId = 'react-native') => {
|
|
310
|
+
const oneDsProvider = new OneDsTelemetryProvider({
|
|
311
|
+
...providerConfig,
|
|
312
|
+
deviceId
|
|
313
|
+
});
|
|
314
|
+
const providers = [oneDsProvider];
|
|
315
|
+
let appInsightsEnabled = false;
|
|
316
|
+
const configuredAppInsights = appInsightsConfigRef.current;
|
|
317
|
+
if (configuredAppInsights?.enabled) {
|
|
318
|
+
try {
|
|
319
|
+
const customerProvider = new ApplicationInsightsTelemetryProvider({
|
|
320
|
+
...configuredAppInsights,
|
|
321
|
+
appVersion: configuredAppInsights.appVersion ?? Constants.expoConfig?.version,
|
|
322
|
+
deviceId,
|
|
323
|
+
sessionId: oneDsProvider.sessionId
|
|
324
|
+
});
|
|
325
|
+
providers.push(customerProvider);
|
|
326
|
+
configureCustomerTelemetryLogger(new Logger({
|
|
327
|
+
providers: [customerProvider]
|
|
328
|
+
}));
|
|
329
|
+
appInsightsEnabled = true;
|
|
330
|
+
} catch (error) {
|
|
331
|
+
console.error('[PowerAppsProvider] Application Insights configuration is invalid.', error);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
const logger = new Logger({
|
|
335
|
+
providers
|
|
336
|
+
});
|
|
337
|
+
configureAppLogger(logger);
|
|
338
|
+
if (appInsightsEnabled) {
|
|
339
|
+
logger.trackActivityEvent('PowerAppsNative.ApplicationStarted', {
|
|
340
|
+
app_id: configuredAppInsights?.appId
|
|
341
|
+
});
|
|
342
|
+
}
|
|
308
343
|
};
|
|
309
344
|
// Resolve the stable device ID first so every event — including the
|
|
310
345
|
// very first — carries the real GUID rather than the 'react-native'
|
|
311
346
|
// fallback. Events emitted while this resolves are silently dropped
|
|
312
347
|
// by the no-op Logger that is active until configureAppLogger is called.
|
|
313
348
|
resolveDeviceId().then(deviceId => {
|
|
314
|
-
|
|
315
|
-
...providerConfig,
|
|
316
|
-
deviceId
|
|
317
|
-
});
|
|
318
|
-
configureAppLogger(new Logger({
|
|
319
|
-
providers: [provider]
|
|
320
|
-
}));
|
|
349
|
+
configureDefaultLogger(deviceId);
|
|
321
350
|
}).catch(_err => {
|
|
322
351
|
// SecureStore unavailable — fall back to a provider without a stable ID.
|
|
323
|
-
|
|
324
|
-
configureAppLogger(new Logger({
|
|
325
|
-
providers: [provider]
|
|
326
|
-
}));
|
|
352
|
+
configureDefaultLogger();
|
|
327
353
|
});
|
|
328
354
|
}
|
|
329
355
|
|
|
@@ -336,6 +362,11 @@ export function PowerAppsProvider({
|
|
|
336
362
|
};
|
|
337
363
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
338
364
|
}, []); // intentionally empty — logger is configured once per mount
|
|
365
|
+
|
|
366
|
+
useEffect(() => {
|
|
367
|
+
if (offlineTelemetryEnabled === undefined) return undefined;
|
|
368
|
+
return configureOfflineSdkTelemetry(offlineTelemetryEnabled);
|
|
369
|
+
}, [offlineTelemetryEnabled]);
|
|
339
370
|
return /*#__PURE__*/_jsx(ErrorBoundary, {
|
|
340
371
|
children: /*#__PURE__*/_jsx(GestureHandlerRootView, {
|
|
341
372
|
style: {
|
|
@@ -353,19 +384,32 @@ export function PowerAppsProvider({
|
|
|
353
384
|
children: /*#__PURE__*/_jsxs(ToastProvider, {
|
|
354
385
|
swipeDirection: "horizontal",
|
|
355
386
|
duration: 3000,
|
|
356
|
-
children: [/*#__PURE__*/_jsx(
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
387
|
+
children: [/*#__PURE__*/_jsx(SessionDetailsGesture, {
|
|
388
|
+
enabled: sessionDetailsGestureEnabled,
|
|
389
|
+
appName: appName ?? Constants.expoConfig?.name ?? 'Power Apps',
|
|
390
|
+
appId: appId || undefined,
|
|
391
|
+
environmentId: powerConfig.environmentId,
|
|
392
|
+
region: powerConfig.region ?? 'prod',
|
|
393
|
+
appVersion: Constants.expoConfig?.version,
|
|
394
|
+
children: /*#__PURE__*/_jsx(QueryClientProvider, {
|
|
395
|
+
client: queryClient,
|
|
396
|
+
children: missingAppId ? /*#__PURE__*/_jsx(MissingAppIdErrorScreen, {}) : missingEnvironmentId ? /*#__PURE__*/_jsx(MissingEnvironmentIdErrorScreen, {}) : missingClientIdInDevPlayer ? /*#__PURE__*/_jsx(MissingClientIdErrorScreen, {}) : /*#__PURE__*/_jsx(AuthProvider, {
|
|
362
397
|
msalConfig: msalConfig,
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
398
|
+
intuneConfig: intuneConfig,
|
|
399
|
+
requiredScopes: requiredAuthScopes,
|
|
400
|
+
children: /*#__PURE__*/_jsx(InnerProviders, {
|
|
401
|
+
msalConfig: msalConfig,
|
|
402
|
+
powerConfig: powerConfig,
|
|
403
|
+
schemaMap: schemaMap,
|
|
404
|
+
renderOAuthWebView: renderOAuthWebView,
|
|
405
|
+
onDisambiguationNeeded: onDisambiguationNeeded,
|
|
406
|
+
onConnectionConsent: onConnectionConsent,
|
|
407
|
+
onResourceConsent: onResourceConsent,
|
|
408
|
+
onConnectionConsentDeclined: onConnectionConsentDeclined,
|
|
409
|
+
offlineProfile: offlineProfile,
|
|
410
|
+
onOfflineEnabledChange: setOfflineTelemetryEnabled,
|
|
411
|
+
children: children
|
|
412
|
+
})
|
|
369
413
|
})
|
|
370
414
|
})
|
|
371
415
|
}), /*#__PURE__*/_jsx(ToastViewport, {
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import React, { useCallback, useMemo, useState } from 'react';
|
|
4
|
+
import { Modal, Platform, Pressable, StyleSheet, Text, View } from 'react-native';
|
|
5
|
+
import * as Clipboard from 'expo-clipboard';
|
|
6
|
+
import { Gesture, GestureDetector } from 'react-native-gesture-handler';
|
|
7
|
+
import { getAppLogger } from "../telemetry/index.js";
|
|
8
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
9
|
+
export function SessionDetailsGesture({
|
|
10
|
+
enabled,
|
|
11
|
+
appName,
|
|
12
|
+
appId,
|
|
13
|
+
environmentId,
|
|
14
|
+
region,
|
|
15
|
+
appVersion,
|
|
16
|
+
children
|
|
17
|
+
}) {
|
|
18
|
+
const [visible, setVisible] = useState(false);
|
|
19
|
+
const [sessionId, setSessionId] = useState();
|
|
20
|
+
const [copied, setCopied] = useState(false);
|
|
21
|
+
const showSessionDetails = useCallback(() => {
|
|
22
|
+
setSessionId(getAppLogger().sessionId);
|
|
23
|
+
setCopied(false);
|
|
24
|
+
setVisible(true);
|
|
25
|
+
}, []);
|
|
26
|
+
const gesture = useMemo(() => Gesture.LongPress().enabled(enabled && Platform.OS !== 'web').numberOfPointers(3).runOnJS(true).onStart(showSessionDetails), [enabled, showSessionDetails]);
|
|
27
|
+
const close = useCallback(() => setVisible(false), []);
|
|
28
|
+
const copySessionId = useCallback(async () => {
|
|
29
|
+
if (!sessionId) return;
|
|
30
|
+
await Clipboard.setStringAsync(sessionId);
|
|
31
|
+
setCopied(true);
|
|
32
|
+
}, [sessionId]);
|
|
33
|
+
return /*#__PURE__*/_jsxs(_Fragment, {
|
|
34
|
+
children: [/*#__PURE__*/_jsx(GestureDetector, {
|
|
35
|
+
gesture: gesture,
|
|
36
|
+
children: /*#__PURE__*/_jsx(View, {
|
|
37
|
+
style: styles.content,
|
|
38
|
+
children: children
|
|
39
|
+
})
|
|
40
|
+
}), /*#__PURE__*/_jsx(Modal, {
|
|
41
|
+
animationType: "fade",
|
|
42
|
+
onRequestClose: close,
|
|
43
|
+
transparent: true,
|
|
44
|
+
visible: visible,
|
|
45
|
+
children: /*#__PURE__*/_jsx(Pressable, {
|
|
46
|
+
accessibilityRole: "button",
|
|
47
|
+
accessibilityLabel: "Close session details",
|
|
48
|
+
onPress: close,
|
|
49
|
+
style: styles.backdrop,
|
|
50
|
+
children: /*#__PURE__*/_jsxs(Pressable, {
|
|
51
|
+
accessible: false,
|
|
52
|
+
onPress: event => event.stopPropagation(),
|
|
53
|
+
style: styles.panel,
|
|
54
|
+
children: [/*#__PURE__*/_jsx(Text, {
|
|
55
|
+
style: styles.title,
|
|
56
|
+
children: "Session details"
|
|
57
|
+
}), /*#__PURE__*/_jsx(SessionDetail, {
|
|
58
|
+
label: "Telemetry session ID",
|
|
59
|
+
value: sessionId ?? 'Not available',
|
|
60
|
+
selectable: true,
|
|
61
|
+
singleLine: true
|
|
62
|
+
}), /*#__PURE__*/_jsx(Pressable, {
|
|
63
|
+
accessibilityRole: "button",
|
|
64
|
+
disabled: !sessionId,
|
|
65
|
+
onPress: () => {
|
|
66
|
+
void copySessionId();
|
|
67
|
+
},
|
|
68
|
+
style: ({
|
|
69
|
+
pressed
|
|
70
|
+
}) => [styles.copyButton, !sessionId && styles.disabledButton, pressed && styles.pressedButton],
|
|
71
|
+
children: /*#__PURE__*/_jsx(Text, {
|
|
72
|
+
style: styles.copyButtonText,
|
|
73
|
+
children: copied ? 'Copied' : 'Copy session ID'
|
|
74
|
+
})
|
|
75
|
+
}), /*#__PURE__*/_jsx(SessionDetail, {
|
|
76
|
+
label: "App",
|
|
77
|
+
value: appName
|
|
78
|
+
}), /*#__PURE__*/_jsx(SessionDetail, {
|
|
79
|
+
label: "App ID",
|
|
80
|
+
value: appId ?? 'Not available',
|
|
81
|
+
selectable: true
|
|
82
|
+
}), /*#__PURE__*/_jsx(SessionDetail, {
|
|
83
|
+
label: "Environment ID",
|
|
84
|
+
value: environmentId ?? 'Not available',
|
|
85
|
+
selectable: true
|
|
86
|
+
}), /*#__PURE__*/_jsx(SessionDetail, {
|
|
87
|
+
label: "Region",
|
|
88
|
+
value: region
|
|
89
|
+
}), /*#__PURE__*/_jsx(SessionDetail, {
|
|
90
|
+
label: "App version",
|
|
91
|
+
value: appVersion ?? 'Not available'
|
|
92
|
+
}), /*#__PURE__*/_jsx(Pressable, {
|
|
93
|
+
accessibilityRole: "button",
|
|
94
|
+
onPress: close,
|
|
95
|
+
style: styles.closeButton,
|
|
96
|
+
children: /*#__PURE__*/_jsx(Text, {
|
|
97
|
+
style: styles.closeButtonText,
|
|
98
|
+
children: "Close"
|
|
99
|
+
})
|
|
100
|
+
})]
|
|
101
|
+
})
|
|
102
|
+
})
|
|
103
|
+
})]
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
function SessionDetail({
|
|
107
|
+
label,
|
|
108
|
+
value,
|
|
109
|
+
selectable = false,
|
|
110
|
+
singleLine = false
|
|
111
|
+
}) {
|
|
112
|
+
return /*#__PURE__*/_jsxs(View, {
|
|
113
|
+
style: styles.row,
|
|
114
|
+
children: [/*#__PURE__*/_jsx(Text, {
|
|
115
|
+
style: styles.label,
|
|
116
|
+
children: label
|
|
117
|
+
}), /*#__PURE__*/_jsx(Text, {
|
|
118
|
+
adjustsFontSizeToFit: singleLine,
|
|
119
|
+
minimumFontScale: 0.85,
|
|
120
|
+
numberOfLines: singleLine ? 1 : undefined,
|
|
121
|
+
selectable: selectable,
|
|
122
|
+
style: styles.value,
|
|
123
|
+
children: value
|
|
124
|
+
})]
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
const styles = StyleSheet.create({
|
|
128
|
+
content: {
|
|
129
|
+
flex: 1
|
|
130
|
+
},
|
|
131
|
+
backdrop: {
|
|
132
|
+
alignItems: 'center',
|
|
133
|
+
backgroundColor: 'rgba(0, 0, 0, 0.48)',
|
|
134
|
+
flex: 1,
|
|
135
|
+
justifyContent: 'center',
|
|
136
|
+
paddingHorizontal: 12,
|
|
137
|
+
paddingVertical: 24
|
|
138
|
+
},
|
|
139
|
+
panel: {
|
|
140
|
+
backgroundColor: '#FFFFFF',
|
|
141
|
+
borderRadius: 8,
|
|
142
|
+
maxWidth: 520,
|
|
143
|
+
paddingHorizontal: 16,
|
|
144
|
+
paddingVertical: 24,
|
|
145
|
+
width: '100%'
|
|
146
|
+
},
|
|
147
|
+
title: {
|
|
148
|
+
color: '#242424',
|
|
149
|
+
fontSize: 20,
|
|
150
|
+
fontWeight: '700',
|
|
151
|
+
marginBottom: 20
|
|
152
|
+
},
|
|
153
|
+
row: {
|
|
154
|
+
marginBottom: 14
|
|
155
|
+
},
|
|
156
|
+
label: {
|
|
157
|
+
color: '#616161',
|
|
158
|
+
fontSize: 12,
|
|
159
|
+
fontWeight: '600',
|
|
160
|
+
marginBottom: 3
|
|
161
|
+
},
|
|
162
|
+
value: {
|
|
163
|
+
color: '#242424',
|
|
164
|
+
fontSize: 15,
|
|
165
|
+
lineHeight: 21
|
|
166
|
+
},
|
|
167
|
+
copyButton: {
|
|
168
|
+
alignSelf: 'flex-start',
|
|
169
|
+
borderColor: '#0F6CBD',
|
|
170
|
+
borderRadius: 4,
|
|
171
|
+
borderWidth: 1,
|
|
172
|
+
marginBottom: 14,
|
|
173
|
+
marginTop: -4,
|
|
174
|
+
paddingHorizontal: 12,
|
|
175
|
+
paddingVertical: 7
|
|
176
|
+
},
|
|
177
|
+
copyButtonText: {
|
|
178
|
+
color: '#0F6CBD',
|
|
179
|
+
fontSize: 13,
|
|
180
|
+
fontWeight: '600'
|
|
181
|
+
},
|
|
182
|
+
disabledButton: {
|
|
183
|
+
opacity: 0.45
|
|
184
|
+
},
|
|
185
|
+
pressedButton: {
|
|
186
|
+
opacity: 0.7
|
|
187
|
+
},
|
|
188
|
+
closeButton: {
|
|
189
|
+
alignItems: 'center',
|
|
190
|
+
alignSelf: 'flex-end',
|
|
191
|
+
backgroundColor: '#0F6CBD',
|
|
192
|
+
borderRadius: 4,
|
|
193
|
+
marginTop: 8,
|
|
194
|
+
minWidth: 88,
|
|
195
|
+
paddingHorizontal: 18,
|
|
196
|
+
paddingVertical: 10
|
|
197
|
+
},
|
|
198
|
+
closeButtonText: {
|
|
199
|
+
color: '#FFFFFF',
|
|
200
|
+
fontSize: 14,
|
|
201
|
+
fontWeight: '600'
|
|
202
|
+
}
|
|
203
|
+
});
|