catalyst-core 0.2.0-beta.3 → 0.3.0-beta.2
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/babel.native.config.cjs +8 -0
- package/bin/catalyst.js +49 -105
- package/changelog.md +8 -0
- package/dist/caching.js +1 -1
- package/dist/globals.d.ts +7 -0
- package/dist/index.jsx +8 -0
- package/dist/logger.js +74 -3
- package/dist/native/androidProject/app/build.gradle.kts +45 -4
- package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/NativeBridge.kt +86 -0
- package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/utils/BridgeUtils.kt +8 -0
- package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/utils/FrameworkServerUtils.kt +173 -13
- package/dist/native/androidProject/settings.gradle.kts +10 -0
- package/dist/native/androidSetup.js +300 -8
- package/dist/native/bridge/WebBridge.js +481 -59
- package/dist/native/bridge/constants/NativeInterfaces.js +304 -45
- package/dist/native/bridge/errors.js +250 -26
- package/dist/native/bridge/hooks/index.js +132 -1
- package/dist/native/bridge/hooks/useAI.js +94 -0
- package/dist/native/bridge/hooks/useCamera.js +347 -9
- package/dist/native/bridge/hooks/useDataProtection.js +200 -2
- package/dist/native/bridge/hooks/useDeviceInfo.js +71 -2
- package/dist/native/bridge/hooks/useFilePicker.js +429 -2
- package/dist/native/bridge/hooks/useGoogleSignIn.js +81 -1
- package/dist/native/bridge/hooks/useHapticFeedback.js +196 -1
- package/dist/native/bridge/hooks/useIntent.js +95 -1
- package/dist/native/bridge/hooks/useNativeTransition.js +202 -27
- package/dist/native/bridge/hooks/useNetworkStatus.js +84 -3
- package/dist/native/bridge/hooks/useNotification.js +318 -2
- package/dist/native/bridge/hooks/useSafeArea.js +84 -2
- package/dist/native/bridge/hooks/useVideoStream.js +434 -6
- package/dist/native/bridge/hooks/utils.js +27 -1
- package/dist/native/bridge/hooks.js +16 -1
- package/dist/native/bridge/perf/collectors/ApiCollector.js +66 -3
- package/dist/native/bridge/perf/collectors/CacheCollector.js +186 -11
- package/dist/native/bridge/perf/collectors/HookCollector.js +141 -19
- package/dist/native/bridge/perf/collectors/InsightsCollector.js +481 -23
- package/dist/native/bridge/perf/collectors/InteractionCollector.js +245 -10
- package/dist/native/bridge/perf/collectors/KeyboardCollector.js +107 -8
- package/dist/native/bridge/perf/collectors/NavigationCollector.js +273 -32
- package/dist/native/bridge/perf/collectors/NetworkTimingCollector.js +178 -2
- package/dist/native/bridge/perf/collectors/RenderCollector.js +258 -14
- package/dist/native/bridge/perf/collectors/ScrollCollector.js +95 -9
- package/dist/native/bridge/perf/collectors/ThreadCollector.js +90 -6
- package/dist/native/bridge/perf/core/constants.js +103 -20
- package/dist/native/bridge/perf/core/measure.js +179 -30
- package/dist/native/bridge/perf/core/session.js +89 -23
- package/dist/native/bridge/perf/core/store.js +554 -1
- package/dist/native/bridge/perf/core/summary.js +174 -1
- package/dist/native/bridge/perf/core/traceExport.js +240 -1
- package/dist/native/bridge/perf/core/waterfalls.js +146 -1
- package/dist/native/bridge/perf/index.js +359 -38
- package/dist/native/bridge/safeArea.js +53 -5
- package/dist/native/bridge/standardizedHooks.js +595 -82
- package/dist/native/bridge/useBaseHook.js +274 -38
- package/dist/native/bridge/utils/CameraUtils.js +201 -56
- package/dist/native/bridge/utils/FileObjectConverter.js +129 -18
- package/dist/native/bridge/utils/NativeBridge.js +425 -141
- package/dist/native/buildAndroid/assets.js +510 -13
- package/dist/native/buildAndroid/build.js +296 -19
- package/dist/native/buildAndroid/config.js +87 -1
- package/dist/native/buildAndroid/index.js +406 -1
- package/dist/native/buildAppAndroid.js +34 -2
- package/dist/native/buildAppIos.js +62 -2
- package/dist/native/buildIos/assets.js +609 -8
- package/dist/native/buildIos/build.js +639 -20
- package/dist/native/buildIos/config.js +294 -12
- package/dist/native/buildIos/index.js +343 -6
- package/dist/native/buildIos/plugins.js +343 -16
- package/dist/native/internal-plugins/device-info-plugin/android/DeviceInfoPlugin.kt +43 -0
- package/dist/native/internal-plugins/device-info-plugin/ios/DeviceInfoPlugin.swift +28 -0
- package/dist/native/internal-plugins/device-info-plugin/manifest.json +19 -0
- package/dist/native/internalPluginUtils.js +232 -7
- package/dist/native/package.json +3 -0
- package/dist/native/plugin-bridge/PluginBridge.js +227 -1
- package/dist/native/pluginComposerAndroid.js +407 -23
- package/dist/native/pluginComposerIos.js +435 -11
- package/dist/native/renameAndroidProject.js +1094 -88
- package/dist/native/setupEmulatorIos.js +289 -22
- package/dist/native/setupServer.js +160 -19
- package/dist/native/terminalProgress.js +199 -11
- package/dist/native/utils.js +193 -15
- package/dist/offline/catalyst-sw.js +145 -1
- package/dist/offline/registerServiceWorker.js +33 -1
- package/dist/otel.js +375 -46
- package/dist/router/ClientRouter.js +14 -2
- package/dist/router/ServerRouter.js +9 -1
- package/dist/router.js +1 -1
- package/dist/scripts/build.js +112 -3
- package/dist/scripts/checkVersion.js +3 -1
- package/dist/scripts/cleanCache.js +30 -1
- package/dist/scripts/generateOfflineManifest.js +116 -1
- package/dist/scripts/loadEnvironmentVariables.js +32 -6
- package/dist/scripts/plugins.js +309 -1
- package/dist/scripts/preServerInit.js +13 -0
- package/dist/scripts/scriptUtils.js +54 -3
- package/dist/scripts/serve.js +51 -4
- package/dist/scripts/start.js +47 -10
- package/dist/scripts/validator.js +149 -1
- package/dist/sentry.cjs +127 -0
- package/dist/sentry.js +125 -5
- package/dist/server/expressServer.js +296 -5
- package/dist/server/manifestCache.js +36 -0
- package/dist/server/renderer/ChunkExtractor.js +144 -0
- package/dist/server/renderer/document/Body.jsx +59 -0
- package/dist/server/renderer/document/FastRefresh.jsx +20 -0
- package/dist/server/renderer/document/Head.jsx +60 -0
- package/dist/server/renderer/document/index.jsx +2 -0
- package/dist/server/renderer/extract.js +149 -31
- package/dist/server/renderer/handler.jsx +450 -0
- package/dist/server/renderer/index.js +8 -1
- package/dist/server/renderer/render.js +47 -0
- package/dist/server/utils/botDetectionMiddleware.js +29 -0
- package/dist/server/utils/cjsRequire.js +10 -0
- package/dist/server/utils/userAgentUtil.js +87 -9
- package/dist/server/utils/validator.js +164 -1
- package/dist/vite/FastRefresh.jsx +20 -0
- package/dist/vite/inject-cache-key-plugin.js +276 -0
- package/dist/vite/loadCustomViteConfig.js +22 -0
- package/dist/vite/manifest-categorization-plugin.js +455 -0
- package/dist/vite/node-loader.mjs +458 -0
- package/dist/vite/scssParams.js +21 -0
- package/dist/vite/vite.config.client.js +130 -0
- package/dist/vite/vite.config.js +498 -0
- package/dist/vite/vite.config.server.js +84 -0
- package/dist/web-router/components/MetaTag.jsx +34 -0
- package/dist/web-router/components/RouterDataProvider.jsx +332 -0
- package/dist/web-router/components/Split.jsx +200 -0
- package/dist/web-router/components/SplitInview.jsx +106 -0
- package/dist/web-router/components/SsrRequestContext.jsx +14 -0
- package/dist/web-router/context.jsx +12 -0
- package/dist/web-router/hooks.jsx +72 -0
- package/dist/web-router/types/components/MetaTag.d.ts +2 -0
- package/dist/web-router/types/components/RouterDataProvider.d.ts +95 -0
- package/dist/web-router/types/context.d.ts +14 -0
- package/dist/web-router/types/hooks.d.ts +1 -0
- package/dist/web-router/types/index.d.ts +3 -0
- package/dist/web-router/types/utils/metaDataUtils.d.ts +24 -0
- package/dist/web-router/utils/metaDataUtils.jsx +119 -0
- package/mcp_v2/conversion-tasks.json +35 -17
- package/mcp_v2/knowledge-base.json +176 -17
- package/mcp_v2/lib/helpers.js +10 -0
- package/mcp_v2/mcp.js +40 -8
- package/mcp_v2/package.json +1 -0
- package/mcp_v2/tools/build.js +161 -37
- package/mcp_v2/tools/conversion.js +106 -5
- package/mcp_v2/tools/tasks.js +18 -14
- package/package.json +35 -68
- package/babel.config.js +0 -32
- package/dist/index.js +0 -1
- package/dist/scripts/devBuild.js +0 -3
- package/dist/scripts/devServe.js +0 -3
- package/dist/scripts/loadScriptsBeforeServerStarts.js +0 -4
- package/dist/scripts/registerAliases.js +0 -6
- package/dist/server/renderer/document/Body.js +0 -11
- package/dist/server/renderer/document/Head.js +0 -9
- package/dist/server/renderer/document/index.js +0 -1
- package/dist/server/renderer/handler.js +0 -47
- package/dist/server/startServer.js +0 -57
- package/dist/webpack/babel-plugins/remove-client.plugin.js +0 -5
- package/dist/webpack/babel-plugins/remove-ssr.plugin.js +0 -5
- package/dist/webpack/babel.config.client.js +0 -1
- package/dist/webpack/babel.config.ssr.js +0 -1
- package/dist/webpack/base.babel.js +0 -7
- package/dist/webpack/development.client.babel.js +0 -10
- package/dist/webpack/production.client.babel.js +0 -4
- package/dist/webpack/production.ssr.babel.js +0 -8
- package/dist/webpack/scssParams.js +0 -9
|
@@ -1 +1,196 @@
|
|
|
1
|
-
"use strict";
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.useHapticFeedback = exports.requestHapticFeedback = void 0;
|
|
7
|
+
var _react = require("react");
|
|
8
|
+
var _NativeBridge = _interopRequireDefault(require("../utils/NativeBridge.js"));
|
|
9
|
+
var _NativeInterfaces = require("../constants/NativeInterfaces.js");
|
|
10
|
+
var _useBaseHook = require("../useBaseHook.js");
|
|
11
|
+
var _errors = require("../errors.js");
|
|
12
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
13
|
+
/* eslint-disable react-compiler/react-compiler, react-hooks/exhaustive-deps */
|
|
14
|
+
|
|
15
|
+
const requestHapticFeedback = (feedbackType = "light") => {
|
|
16
|
+
if (typeof window === "undefined") {
|
|
17
|
+
return Promise.resolve(null);
|
|
18
|
+
}
|
|
19
|
+
if (!window.WebBridge) {
|
|
20
|
+
throw new Error("WebBridge is not initialized. Call WebBridge.init() first.");
|
|
21
|
+
}
|
|
22
|
+
return new Promise((resolve, reject) => {
|
|
23
|
+
try {
|
|
24
|
+
if (!_NativeBridge.default.isAvailable()) {
|
|
25
|
+
reject(new Error("Native bridge not available"));
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
const handleHapticResponse = data => {
|
|
29
|
+
window.WebBridge.unregister(_NativeInterfaces.NATIVE_CALLBACKS.HAPTIC_FEEDBACK);
|
|
30
|
+
if (data === _NativeInterfaces.RESPONSE_STATUS.SUCCESS) {
|
|
31
|
+
resolve(data);
|
|
32
|
+
} else {
|
|
33
|
+
reject(new Error(`Haptic feedback failed: ${data}`));
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
window.WebBridge.register(_NativeInterfaces.NATIVE_CALLBACKS.HAPTIC_FEEDBACK, handleHapticResponse);
|
|
37
|
+
_NativeBridge.default.haptic.feedback(feedbackType);
|
|
38
|
+
console.log("📳 Haptic feedback requested:", feedbackType);
|
|
39
|
+
} catch (error) {
|
|
40
|
+
reject(error);
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
};
|
|
44
|
+
exports.requestHapticFeedback = requestHapticFeedback;
|
|
45
|
+
const detectHapticCapabilities = isNative => {
|
|
46
|
+
const userAgent = typeof navigator !== "undefined" ? navigator.userAgent.toLowerCase() : "";
|
|
47
|
+
if (isNative) {
|
|
48
|
+
const platform = userAgent.includes("android") ? "android" : userAgent.includes("iphone") || userAgent.includes("ipad") ? "ios" : "native";
|
|
49
|
+
const availableTypes = platform === "ios" ? ["light", "medium", "heavy", "success", "warning", "error", "selection", "impact"] : ["light", "medium", "heavy"];
|
|
50
|
+
return {
|
|
51
|
+
isSupported: true,
|
|
52
|
+
availableTypes,
|
|
53
|
+
platform
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
const isSupported = typeof navigator !== "undefined" && "vibrate" in navigator;
|
|
57
|
+
return {
|
|
58
|
+
isSupported,
|
|
59
|
+
availableTypes: isSupported ? ["light", "medium", "heavy"] : [],
|
|
60
|
+
platform: "web"
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
const useHapticFeedback = ({
|
|
64
|
+
webFallback
|
|
65
|
+
} = {}) => {
|
|
66
|
+
const base = (0, _useBaseHook.useBaseHook)("useHapticFeedback", {
|
|
67
|
+
hasWebFallback: true,
|
|
68
|
+
webFallback
|
|
69
|
+
});
|
|
70
|
+
const [capabilities, setCapabilities] = (0, _react.useState)(() => detectHapticCapabilities(base.isNative));
|
|
71
|
+
if (base.webFallbackDisabled) {
|
|
72
|
+
return {
|
|
73
|
+
data: null,
|
|
74
|
+
loading: false,
|
|
75
|
+
progress: null,
|
|
76
|
+
error: null,
|
|
77
|
+
isWeb: true,
|
|
78
|
+
isNative: false,
|
|
79
|
+
webFallbackActive: false,
|
|
80
|
+
webFallbackDisabled: true,
|
|
81
|
+
setWebFallback: base.setWebFallback,
|
|
82
|
+
execute: () => {},
|
|
83
|
+
clear: () => {},
|
|
84
|
+
clearError: () => {},
|
|
85
|
+
triggerHaptic: () => {},
|
|
86
|
+
trigger: () => {},
|
|
87
|
+
light: () => {},
|
|
88
|
+
medium: () => {},
|
|
89
|
+
heavy: () => {},
|
|
90
|
+
success: () => {},
|
|
91
|
+
warning: () => {},
|
|
92
|
+
errorHaptic: () => {},
|
|
93
|
+
selection: () => {},
|
|
94
|
+
impact: () => {},
|
|
95
|
+
capabilities: {
|
|
96
|
+
isSupported: false,
|
|
97
|
+
availableTypes: [],
|
|
98
|
+
platform: "web"
|
|
99
|
+
},
|
|
100
|
+
isSupported: false,
|
|
101
|
+
isAvailable: false,
|
|
102
|
+
availableTypes: [],
|
|
103
|
+
HAPTIC_TYPES: {}
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
const HAPTIC_TYPES = {
|
|
107
|
+
LIGHT: "light",
|
|
108
|
+
MEDIUM: "medium",
|
|
109
|
+
HEAVY: "heavy",
|
|
110
|
+
SUCCESS: "success",
|
|
111
|
+
WARNING: "warning",
|
|
112
|
+
ERROR: "error",
|
|
113
|
+
SELECTION: "selection",
|
|
114
|
+
IMPACT: "impact"
|
|
115
|
+
};
|
|
116
|
+
(0, _react.useEffect)(() => {
|
|
117
|
+
setCapabilities(detectHapticCapabilities(base.isNative));
|
|
118
|
+
}, [base.isNative]);
|
|
119
|
+
const handleWebHaptic = type => {
|
|
120
|
+
if (!navigator.vibrate) return false;
|
|
121
|
+
const vibrationPatterns = {
|
|
122
|
+
[HAPTIC_TYPES.LIGHT]: [50],
|
|
123
|
+
[HAPTIC_TYPES.MEDIUM]: [100],
|
|
124
|
+
[HAPTIC_TYPES.HEAVY]: [200],
|
|
125
|
+
[HAPTIC_TYPES.SUCCESS]: [100, 50, 100],
|
|
126
|
+
[HAPTIC_TYPES.WARNING]: [200, 100, 200],
|
|
127
|
+
[HAPTIC_TYPES.ERROR]: [300, 100, 300, 100, 300],
|
|
128
|
+
[HAPTIC_TYPES.SELECTION]: [25],
|
|
129
|
+
[HAPTIC_TYPES.IMPACT]: [150]
|
|
130
|
+
};
|
|
131
|
+
navigator.vibrate(vibrationPatterns[type] || [100]);
|
|
132
|
+
return true;
|
|
133
|
+
};
|
|
134
|
+
const handleHapticTrigger = async (type, options = {}) => {
|
|
135
|
+
try {
|
|
136
|
+
base.setLoading(true);
|
|
137
|
+
base.updateProgress({
|
|
138
|
+
state: "active",
|
|
139
|
+
phase: "triggering",
|
|
140
|
+
message: `Triggering ${type} haptic feedback...`
|
|
141
|
+
});
|
|
142
|
+
const success = base.isNative ? await requestHapticFeedback(type) : handleWebHaptic(type, options);
|
|
143
|
+
base.setDataAndComplete({
|
|
144
|
+
lastType: type,
|
|
145
|
+
lastOptions: options,
|
|
146
|
+
timestamp: new Date().toISOString(),
|
|
147
|
+
success,
|
|
148
|
+
capabilities,
|
|
149
|
+
lastOperation: "trigger",
|
|
150
|
+
operationSuccess: success
|
|
151
|
+
});
|
|
152
|
+
return success;
|
|
153
|
+
} catch (error) {
|
|
154
|
+
console.error("📳 Haptic feedback failed:", error);
|
|
155
|
+
base.handleNativeError(error);
|
|
156
|
+
return false;
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
const executeHaptic = (type = "light", options = {}) => {
|
|
160
|
+
if (!capabilities.isSupported) {
|
|
161
|
+
base.handleNativeError((0, _errors.createStandardError)(_errors.ERROR_CODES.FEATURE_UNSUPPORTED, "Haptic feedback not supported", null, "Device does not support haptic feedback"));
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
return handleHapticTrigger(type, options);
|
|
165
|
+
};
|
|
166
|
+
return {
|
|
167
|
+
data: base.data,
|
|
168
|
+
loading: base.loading,
|
|
169
|
+
progress: base.progress,
|
|
170
|
+
error: base.error,
|
|
171
|
+
isWeb: base.isWeb,
|
|
172
|
+
isNative: base.isNative,
|
|
173
|
+
webFallbackActive: base.webFallbackActive,
|
|
174
|
+
webFallbackDisabled: false,
|
|
175
|
+
setWebFallback: base.setWebFallback,
|
|
176
|
+
clear: base.clear,
|
|
177
|
+
clearError: base.clearError,
|
|
178
|
+
execute: executeHaptic,
|
|
179
|
+
triggerHaptic: executeHaptic,
|
|
180
|
+
trigger: executeHaptic,
|
|
181
|
+
light: () => executeHaptic(HAPTIC_TYPES.LIGHT),
|
|
182
|
+
medium: () => executeHaptic(HAPTIC_TYPES.MEDIUM),
|
|
183
|
+
heavy: () => executeHaptic(HAPTIC_TYPES.HEAVY),
|
|
184
|
+
success: () => executeHaptic(HAPTIC_TYPES.SUCCESS),
|
|
185
|
+
warning: () => executeHaptic(HAPTIC_TYPES.WARNING),
|
|
186
|
+
errorHaptic: () => executeHaptic(HAPTIC_TYPES.ERROR),
|
|
187
|
+
selection: () => executeHaptic(HAPTIC_TYPES.SELECTION),
|
|
188
|
+
impact: () => executeHaptic(HAPTIC_TYPES.IMPACT),
|
|
189
|
+
capabilities,
|
|
190
|
+
isSupported: capabilities.isSupported,
|
|
191
|
+
isAvailable: capabilities.isSupported,
|
|
192
|
+
availableTypes: capabilities.availableTypes,
|
|
193
|
+
HAPTIC_TYPES
|
|
194
|
+
};
|
|
195
|
+
};
|
|
196
|
+
exports.useHapticFeedback = useHapticFeedback;
|
|
@@ -1 +1,95 @@
|
|
|
1
|
-
"use strict";
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.useIntent = void 0;
|
|
7
|
+
var _react = require("react");
|
|
8
|
+
var _NativeBridge = _interopRequireDefault(require("../utils/NativeBridge.js"));
|
|
9
|
+
var _NativeInterfaces = require("../constants/NativeInterfaces.js");
|
|
10
|
+
var _useBaseHook = require("../useBaseHook.js");
|
|
11
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
12
|
+
/* eslint-disable react-compiler/react-compiler, react-hooks/exhaustive-deps */
|
|
13
|
+
|
|
14
|
+
const useIntent = () => {
|
|
15
|
+
const base = (0, _useBaseHook.useBaseHook)("useIntent");
|
|
16
|
+
if (typeof window === "undefined") {
|
|
17
|
+
return {
|
|
18
|
+
data: null,
|
|
19
|
+
loading: false,
|
|
20
|
+
progress: null,
|
|
21
|
+
error: null,
|
|
22
|
+
isWeb: true,
|
|
23
|
+
isNative: false,
|
|
24
|
+
execute: () => {},
|
|
25
|
+
clear: () => {},
|
|
26
|
+
clearError: () => {},
|
|
27
|
+
isLoading: false,
|
|
28
|
+
processingState: null,
|
|
29
|
+
openFile: () => {},
|
|
30
|
+
success: null,
|
|
31
|
+
reset: () => {}
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
if (!window.WebBridge) {
|
|
35
|
+
throw new Error("WebBridge is not initialized. Call WebBridge.init() first.");
|
|
36
|
+
}
|
|
37
|
+
(0, _react.useEffect)(() => {
|
|
38
|
+
window.WebBridge.register(_NativeInterfaces.NATIVE_CALLBACKS.ON_INTENT_SUCCESS, data => {
|
|
39
|
+
console.log("📄 Intent completed successfully:", data);
|
|
40
|
+
base.setDataAndComplete({
|
|
41
|
+
result: data,
|
|
42
|
+
success: true
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
window.WebBridge.register(_NativeInterfaces.NATIVE_CALLBACKS.ON_INTENT_ERROR, data => {
|
|
46
|
+
console.error("📄 Intent error:", data);
|
|
47
|
+
base.handleNativeError(data);
|
|
48
|
+
});
|
|
49
|
+
window.WebBridge.register(_NativeInterfaces.NATIVE_CALLBACKS.ON_INTENT_CANCELLED, data => {
|
|
50
|
+
console.log("📄 Intent cancelled:", data);
|
|
51
|
+
base.setLoading(false);
|
|
52
|
+
base.resetProgress();
|
|
53
|
+
});
|
|
54
|
+
return () => {
|
|
55
|
+
window.WebBridge.unregister(_NativeInterfaces.NATIVE_CALLBACKS.ON_INTENT_SUCCESS);
|
|
56
|
+
window.WebBridge.unregister(_NativeInterfaces.NATIVE_CALLBACKS.ON_INTENT_ERROR);
|
|
57
|
+
window.WebBridge.unregister(_NativeInterfaces.NATIVE_CALLBACKS.ON_INTENT_CANCELLED);
|
|
58
|
+
};
|
|
59
|
+
}, [base.setDataAndComplete, base.handleNativeError, base.setLoading, base.resetProgress]);
|
|
60
|
+
const openFile = (fileUrl, mimeType = null) => {
|
|
61
|
+
if (!fileUrl) {
|
|
62
|
+
base.handleNativeError("File URL is required");
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
console.log("📄 File open with intent requested:", {
|
|
66
|
+
fileUrl,
|
|
67
|
+
mimeType
|
|
68
|
+
});
|
|
69
|
+
base.executeOperation(() => {
|
|
70
|
+
base.updateProgress({
|
|
71
|
+
state: "opening_file",
|
|
72
|
+
phase: "processing",
|
|
73
|
+
message: "Opening file with external app..."
|
|
74
|
+
});
|
|
75
|
+
_NativeBridge.default.file.openWithIntent(fileUrl, mimeType);
|
|
76
|
+
}, "intent file open");
|
|
77
|
+
};
|
|
78
|
+
return {
|
|
79
|
+
data: base.data,
|
|
80
|
+
loading: base.loading,
|
|
81
|
+
progress: base.progress,
|
|
82
|
+
error: base.error,
|
|
83
|
+
isWeb: base.isWeb,
|
|
84
|
+
isNative: base.isNative,
|
|
85
|
+
execute: openFile,
|
|
86
|
+
clear: base.clear,
|
|
87
|
+
clearError: base.clearError,
|
|
88
|
+
isLoading: base.loading,
|
|
89
|
+
processingState: base.progress?.phase || null,
|
|
90
|
+
openFile,
|
|
91
|
+
success: base.data?.success || null,
|
|
92
|
+
reset: base.clear
|
|
93
|
+
};
|
|
94
|
+
};
|
|
95
|
+
exports.useIntent = useIntent;
|
|
@@ -1,4 +1,21 @@
|
|
|
1
|
-
"use strict";
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.useNativeTransition = void 0;
|
|
7
|
+
var _react = require("react");
|
|
8
|
+
var _reactRouterDom = require("react-router-dom");
|
|
9
|
+
var _NativeBridge = _interopRequireDefault(require("../utils/NativeBridge.js"));
|
|
10
|
+
var _NativeInterfaces = require("../constants/NativeInterfaces.js");
|
|
11
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
12
|
+
/* eslint-disable react-compiler/react-compiler, react-hooks/exhaustive-deps */
|
|
13
|
+
|
|
14
|
+
const DEFAULT_DURATION = 300;
|
|
15
|
+
const DEFAULT_TIMEOUT_MULTIPLIER = 3;
|
|
16
|
+
const MIN_TIMEOUT = 800;
|
|
17
|
+
|
|
18
|
+
/**
|
|
2
19
|
* Wraps useNavigate with native slide/fade transitions using a snapshot overlay pattern.
|
|
3
20
|
*
|
|
4
21
|
* Native path:
|
|
@@ -15,29 +32,187 @@
|
|
|
15
32
|
* direction: 'left' | 'right' | 'up' | 'down' (default: 'left')
|
|
16
33
|
* duration: ms (default: 300)
|
|
17
34
|
* timeout: ms safety timer (default: max(duration*3, 800))
|
|
18
|
-
*/
|
|
19
|
-
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
35
|
+
*/
|
|
36
|
+
const useNativeTransition = (defaults = {}) => {
|
|
37
|
+
const router = (0, _reactRouterDom.useNavigate)();
|
|
38
|
+
const isNative = typeof window !== "undefined" && _NativeBridge.default.isAvailable();
|
|
39
|
+
const [transitioning, setTransitioning] = (0, _react.useState)(false);
|
|
40
|
+
const overlayRef = (0, _react.useRef)(null);
|
|
41
|
+
const webTimeoutRef = (0, _react.useRef)(null);
|
|
42
|
+
const pendingCommitRef = (0, _react.useRef)(null);
|
|
43
|
+
|
|
44
|
+
// Register native callbacks once
|
|
45
|
+
(0, _react.useEffect)(() => {
|
|
46
|
+
if (typeof window === "undefined" || !window.WebBridge) return;
|
|
47
|
+
window.WebBridge.register(_NativeInterfaces.NATIVE_CALLBACKS.ON_TRANSITION_COMMITTED, () => {
|
|
48
|
+
setTransitioning(false);
|
|
49
|
+
});
|
|
50
|
+
window.WebBridge.register(_NativeInterfaces.NATIVE_CALLBACKS.ON_TRANSITION_CANCELLED, () => {
|
|
51
|
+
setTransitioning(false);
|
|
52
|
+
});
|
|
53
|
+
window.WebBridge.register(_NativeInterfaces.NATIVE_CALLBACKS.ON_TRANSITION_TIMEOUT, () => {
|
|
54
|
+
console.warn("🔀 useNativeTransition: native safety timeout fired — overlay force-faded");
|
|
55
|
+
setTransitioning(false);
|
|
56
|
+
});
|
|
57
|
+
return () => {
|
|
58
|
+
window.WebBridge.unregister(_NativeInterfaces.NATIVE_CALLBACKS.ON_TRANSITION_COMMITTED);
|
|
59
|
+
window.WebBridge.unregister(_NativeInterfaces.NATIVE_CALLBACKS.ON_TRANSITION_CANCELLED);
|
|
60
|
+
window.WebBridge.unregister(_NativeInterfaces.NATIVE_CALLBACKS.ON_TRANSITION_TIMEOUT);
|
|
61
|
+
};
|
|
62
|
+
}, []);
|
|
63
|
+
|
|
64
|
+
// Web fallback: create/remove a CSS overlay on document.body
|
|
65
|
+
const _showWebOverlay = (0, _react.useCallback)(duration => {
|
|
66
|
+
if (typeof document === "undefined") return;
|
|
67
|
+
const overlay = document.createElement("div");
|
|
68
|
+
overlay.style.cssText = ["position:fixed", "inset:0", "z-index:9999", "background:var(--transition-overlay-color,#fff)", `transition:opacity ${duration}ms ease`, "opacity:0", "pointer-events:none"].join(";");
|
|
69
|
+
document.body.appendChild(overlay);
|
|
70
|
+
overlayRef.current = overlay;
|
|
71
|
+
|
|
72
|
+
// Trigger enter animation (fade in)
|
|
73
|
+
requestAnimationFrame(() => {
|
|
74
|
+
requestAnimationFrame(() => {
|
|
75
|
+
overlay.style.opacity = "1";
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
}, []);
|
|
79
|
+
const _hideWebOverlay = (0, _react.useCallback)(duration => {
|
|
80
|
+
const overlay = overlayRef.current;
|
|
81
|
+
if (!overlay) return;
|
|
82
|
+
overlay.style.opacity = "0";
|
|
83
|
+
const cleanup = () => {
|
|
84
|
+
overlay.remove();
|
|
85
|
+
overlayRef.current = null;
|
|
86
|
+
setTransitioning(false);
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
// Use transitionend when possible, fallback to setTimeout
|
|
90
|
+
overlay.addEventListener("transitionend", cleanup, {
|
|
91
|
+
once: true
|
|
92
|
+
});
|
|
93
|
+
webTimeoutRef.current = setTimeout(cleanup, duration + 50);
|
|
94
|
+
}, []);
|
|
95
|
+
|
|
96
|
+
// Cancel any in-flight web transition (e.g. safety timeout path)
|
|
97
|
+
const _cancelWebOverlay = (0, _react.useCallback)(() => {
|
|
98
|
+
clearTimeout(webTimeoutRef.current);
|
|
99
|
+
if (overlayRef.current) {
|
|
100
|
+
overlayRef.current.remove();
|
|
101
|
+
overlayRef.current = null;
|
|
102
|
+
}
|
|
103
|
+
setTransitioning(false);
|
|
104
|
+
}, []);
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* navigate(to, options)
|
|
108
|
+
*
|
|
109
|
+
* Options (in addition to standard react-router NavigateOptions):
|
|
110
|
+
* type: 'slide' | 'fade'
|
|
111
|
+
* direction: 'left' | 'right' | 'up' | 'down'
|
|
112
|
+
* duration: ms
|
|
113
|
+
* timeout: ms (native safety timer; web safety timer uses duration*3)
|
|
114
|
+
* replace: boolean (passed to router)
|
|
115
|
+
* state: any (passed to router)
|
|
116
|
+
*/
|
|
117
|
+
const navigate = (0, _react.useCallback)((to, options = {}) => {
|
|
118
|
+
const {
|
|
119
|
+
type = defaults.type ?? "slide",
|
|
120
|
+
direction = defaults.direction ?? "left",
|
|
121
|
+
duration = defaults.duration ?? DEFAULT_DURATION,
|
|
122
|
+
timeout = defaults.timeout ?? Math.max(duration * DEFAULT_TIMEOUT_MULTIPLIER, MIN_TIMEOUT),
|
|
123
|
+
replace = false,
|
|
124
|
+
state,
|
|
125
|
+
...rest
|
|
126
|
+
} = options;
|
|
127
|
+
const routerOpts = {
|
|
128
|
+
replace,
|
|
129
|
+
state,
|
|
130
|
+
...rest
|
|
131
|
+
};
|
|
132
|
+
setTransitioning(true);
|
|
133
|
+
if (isNative) {
|
|
134
|
+
try {
|
|
135
|
+
_NativeBridge.default.transition.start({
|
|
136
|
+
type,
|
|
137
|
+
direction,
|
|
138
|
+
duration,
|
|
139
|
+
timeout
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
// Route swap happens immediately — native overlay hides the skeleton
|
|
143
|
+
router(to, routerOpts);
|
|
144
|
+
|
|
145
|
+
// Give the new page one frame to mount before committing
|
|
146
|
+
requestAnimationFrame(() => {
|
|
147
|
+
requestAnimationFrame(() => {
|
|
148
|
+
try {
|
|
149
|
+
_NativeBridge.default.transition.commit();
|
|
150
|
+
} catch (err) {
|
|
151
|
+
console.error("🔀 useNativeTransition: commitTransition failed:", err);
|
|
152
|
+
_NativeBridge.default.transition.cancel();
|
|
153
|
+
setTransitioning(false);
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
} catch (err) {
|
|
158
|
+
console.error("🔀 useNativeTransition: startTransition failed, falling back to plain navigate:", err);
|
|
159
|
+
setTransitioning(false);
|
|
160
|
+
router(to, routerOpts);
|
|
161
|
+
}
|
|
162
|
+
} else {
|
|
163
|
+
// Web fallback — CSS overlay
|
|
164
|
+
_showWebOverlay(duration);
|
|
165
|
+
const webSafetyTimeout = Math.max(duration * DEFAULT_TIMEOUT_MULTIPLIER, MIN_TIMEOUT);
|
|
166
|
+
pendingCommitRef.current = {
|
|
167
|
+
duration,
|
|
168
|
+
webSafetyTimeout
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
// Route swap after overlay is visible
|
|
172
|
+
requestAnimationFrame(() => {
|
|
173
|
+
requestAnimationFrame(() => {
|
|
174
|
+
router(to, routerOpts);
|
|
175
|
+
|
|
176
|
+
// Commit: fade overlay back out
|
|
177
|
+
requestAnimationFrame(() => {
|
|
178
|
+
requestAnimationFrame(() => {
|
|
179
|
+
_hideWebOverlay(duration);
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
});
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
// Web safety timeout
|
|
186
|
+
webTimeoutRef.current = setTimeout(() => {
|
|
187
|
+
console.warn("🔀 useNativeTransition: web safety timeout — removing overlay");
|
|
188
|
+
_cancelWebOverlay();
|
|
189
|
+
}, webSafetyTimeout);
|
|
190
|
+
}
|
|
191
|
+
}, [isNative, defaults, router, _showWebOverlay, _hideWebOverlay, _cancelWebOverlay]);
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Imperatively cancel an in-flight transition (e.g. error boundary).
|
|
195
|
+
* On native: fires cancelTransition bridge command.
|
|
196
|
+
* On web: removes overlay immediately.
|
|
197
|
+
*/
|
|
198
|
+
const cancelTransition = (0, _react.useCallback)(() => {
|
|
199
|
+
if (isNative) {
|
|
200
|
+
try {
|
|
201
|
+
_NativeBridge.default.transition.cancel();
|
|
202
|
+
} catch (_) {
|
|
203
|
+
/* swallow — cancel is best-effort */
|
|
204
|
+
}
|
|
205
|
+
} else {
|
|
206
|
+
_cancelWebOverlay();
|
|
207
|
+
}
|
|
208
|
+
setTransitioning(false);
|
|
209
|
+
}, [isNative, _cancelWebOverlay]);
|
|
210
|
+
return {
|
|
211
|
+
navigate,
|
|
212
|
+
cancelTransition,
|
|
213
|
+
transitioning,
|
|
214
|
+
isNative,
|
|
215
|
+
isWeb: !isNative
|
|
216
|
+
};
|
|
217
|
+
};
|
|
218
|
+
exports.useNativeTransition = useNativeTransition;
|
|
@@ -1,3 +1,84 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.useNetworkStatus = void 0;
|
|
7
|
+
var _react = require("react");
|
|
8
|
+
var _NativeBridge = _interopRequireDefault(require("../utils/NativeBridge.js"));
|
|
9
|
+
var _NativeInterfaces = require("../constants/NativeInterfaces.js");
|
|
10
|
+
var _utils = require("./utils.js");
|
|
11
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
12
|
+
/* eslint-disable react-compiler/react-compiler, react-hooks/exhaustive-deps */
|
|
13
|
+
|
|
14
|
+
const useNetworkStatus = ({
|
|
15
|
+
webFallback
|
|
16
|
+
} = {}) => {
|
|
17
|
+
// navigator.onLine is unreliable in some dev/Electron environments — default true if undefined
|
|
18
|
+
const initialOnline = typeof navigator !== "undefined" && typeof navigator.onLine === "boolean" ? navigator.onLine : true;
|
|
19
|
+
const [status, setStatus] = (0, _react.useState)({
|
|
20
|
+
online: initialOnline,
|
|
21
|
+
type: null
|
|
22
|
+
});
|
|
23
|
+
const [error, setError] = (0, _react.useState)(null);
|
|
24
|
+
const isNative = _NativeBridge.default.isAvailable();
|
|
25
|
+
const [webFallbackState, setWebFallback] = (0, _react.useState)(true);
|
|
26
|
+
const webFallbackResolved = webFallback !== undefined ? webFallback !== false : webFallbackState;
|
|
27
|
+
const webFallbackActive = !isNative && webFallbackResolved;
|
|
28
|
+
const webFallbackDisabled = !isNative && !webFallbackResolved;
|
|
29
|
+
(0, _react.useEffect)(() => {
|
|
30
|
+
if (typeof window === "undefined") return;
|
|
31
|
+
if (!isNative) {
|
|
32
|
+
if (webFallbackDisabled) return;
|
|
33
|
+
|
|
34
|
+
// Web fallback: browser online/offline events
|
|
35
|
+
const handleOnline = () => setStatus({
|
|
36
|
+
online: true,
|
|
37
|
+
type: null
|
|
38
|
+
});
|
|
39
|
+
const handleOffline = () => setStatus({
|
|
40
|
+
online: false,
|
|
41
|
+
type: null
|
|
42
|
+
});
|
|
43
|
+
window.addEventListener("online", handleOnline);
|
|
44
|
+
window.addEventListener("offline", handleOffline);
|
|
45
|
+
return () => {
|
|
46
|
+
window.removeEventListener("online", handleOnline);
|
|
47
|
+
window.removeEventListener("offline", handleOffline);
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
if (!window.WebBridge) return;
|
|
51
|
+
const handleStatus = payload => {
|
|
52
|
+
try {
|
|
53
|
+
const parsed = (0, _utils.parseNativePayload)(payload) || {};
|
|
54
|
+
setStatus({
|
|
55
|
+
online: Boolean(parsed.online),
|
|
56
|
+
type: parsed.type || null
|
|
57
|
+
});
|
|
58
|
+
setError(null);
|
|
59
|
+
} catch (e) {
|
|
60
|
+
console.error("🌐 Error parsing network status:", e);
|
|
61
|
+
setError(e.message);
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
window.WebBridge.register(_NativeInterfaces.NATIVE_CALLBACKS.NETWORK_STATUS_CHANGED, handleStatus);
|
|
65
|
+
try {
|
|
66
|
+
_NativeBridge.default.network.getStatus();
|
|
67
|
+
} catch (e) {
|
|
68
|
+
setError(e.message || "Network status unavailable");
|
|
69
|
+
}
|
|
70
|
+
return () => {
|
|
71
|
+
window.WebBridge.unregister(_NativeInterfaces.NATIVE_CALLBACKS.NETWORK_STATUS_CHANGED);
|
|
72
|
+
};
|
|
73
|
+
}, [isNative, webFallbackDisabled]);
|
|
74
|
+
return {
|
|
75
|
+
...status,
|
|
76
|
+
error,
|
|
77
|
+
isNative,
|
|
78
|
+
isWeb: !isNative,
|
|
79
|
+
webFallbackActive,
|
|
80
|
+
webFallbackDisabled,
|
|
81
|
+
setWebFallback
|
|
82
|
+
};
|
|
83
|
+
};
|
|
84
|
+
exports.useNetworkStatus = useNetworkStatus;
|