@dashadmin/dash-utils 1.3.73 → 1.3.74-srcfree.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.
Files changed (66) hide show
  1. package/dist/components/LazyAppLoader.d.ts +17 -0
  2. package/dist/components/MinimalLayout.d.ts +6 -0
  3. package/dist/components/RouterComponent.d.ts +22 -0
  4. package/dist/components/index.d.ts +2 -0
  5. package/dist/contexts/IPCMessageBrokerContext.d.ts +42 -0
  6. package/dist/hooks/useCapacitorAppStateRefresh.d.ts +2 -0
  7. package/dist/hooks/useCapacitorKeyboard.d.ts +19 -0
  8. package/dist/hooks/useDeviceStorageSync.d.ts +4 -0
  9. package/dist/hooks/useDraggable.d.ts +24 -0
  10. package/dist/hooks/useMenuStateInit.d.ts +10 -0
  11. package/dist/hooks/useMobileDetection.d.ts +20 -0
  12. package/dist/hooks/useNotifications.d.ts +51 -0
  13. package/dist/hooks/useQuickSearch.d.ts +6 -0
  14. package/dist/hooks/useWindowSize.d.ts +6 -0
  15. package/dist/index.d.ts +30 -0
  16. package/dist/utils/authProviderUtils.d.ts +37 -0
  17. package/dist/utils/dashBootstrapApp.d.ts +9 -0
  18. package/dist/utils/dashDtorage.d.ts +8 -0
  19. package/dist/utils/dashIPCService.d.ts +93 -0
  20. package/dist/utils/dataProviderUtils.d.ts +44 -0
  21. package/dist/utils/electronStoreSync.d.ts +3 -0
  22. package/dist/utils/envUtils.d.ts +1 -0
  23. package/dist/utils/environmentBodyClasses.d.ts +11 -0
  24. package/dist/utils/isDev.d.ts +5 -0
  25. package/dist/utils/notificationPermission.d.ts +5 -0
  26. package/dist/utils/platformDetection.d.ts +13 -0
  27. package/dist/utils/priceFormatter.d.ts +2 -0
  28. package/dist/utils/resourceLoader.d.ts +8 -0
  29. package/dist/utils/speechService.d.ts +7 -0
  30. package/dist/utils/storedTheme.d.ts +11 -0
  31. package/dist/utils/updateDomCssVariables.d.ts +6 -0
  32. package/dist/utils/validation.d.ts +12 -0
  33. package/package.json +13 -10
  34. package/src/components/LazyAppLoader.tsx +0 -143
  35. package/src/components/MinimalLayout.tsx +0 -22
  36. package/src/components/RouterComponent.tsx +0 -169
  37. package/src/components/index.ts +0 -16
  38. package/src/contexts/IPCMessageBrokerContext.tsx +0 -303
  39. package/src/hooks/useCapacitorAppStateRefresh.ts +0 -34
  40. package/src/hooks/useCapacitorKeyboard.ts +0 -213
  41. package/src/hooks/useDeviceStorageSync.ts +0 -70
  42. package/src/hooks/useDraggable.ts +0 -133
  43. package/src/hooks/useMenuStateInit.ts +0 -85
  44. package/src/hooks/useMobileDetection.ts +0 -165
  45. package/src/hooks/useNotifications.ts +0 -220
  46. package/src/hooks/useQuickSearch.ts +0 -42
  47. package/src/hooks/useWindowSize.tsx +0 -36
  48. package/src/index.ts +0 -202
  49. package/src/utils/authProviderUtils.ts +0 -170
  50. package/src/utils/dashBootstrapApp.ts +0 -104
  51. package/src/utils/dashDtorage.tsx +0 -51
  52. package/src/utils/dashDtorage.tsx.old +0 -78
  53. package/src/utils/dashIPCService.ts +0 -204
  54. package/src/utils/dataProviderUtils.ts +0 -221
  55. package/src/utils/electronStoreSync.ts +0 -34
  56. package/src/utils/envUtils.tsx +0 -27
  57. package/src/utils/environmentBodyClasses.ts +0 -72
  58. package/src/utils/isDev.ts +0 -65
  59. package/src/utils/notificationPermission.ts +0 -57
  60. package/src/utils/platformDetection.ts +0 -98
  61. package/src/utils/priceFormatter.ts +0 -36
  62. package/src/utils/resourceLoader.ts +0 -107
  63. package/src/utils/speechService.ts +0 -112
  64. package/src/utils/storedTheme.ts +0 -60
  65. package/src/utils/updateDomCssVariables.tsx +0 -181
  66. package/src/utils/validation.ts +0 -147
@@ -1,143 +0,0 @@
1
- /**
2
- * Lazy App Loader Utilities
3
- *
4
- * Provides utilities for creating lazy-loaded app components with
5
- * error handling and initialization delays.
6
- */
7
- import React from 'react';
8
-
9
- export interface LazyAppLoaderConfig {
10
- /**
11
- * Dynamic import function that returns the module with the app component
12
- * Example: () => import('./DASHAppLoader')
13
- */
14
- importFn: () => Promise<{ default: React.ComponentType<any> }>;
15
-
16
- /**
17
- * Delay in milliseconds before loading the component (default: 150ms)
18
- * This helps ensure all modules are properly initialized
19
- */
20
- initDelay?: number;
21
-
22
- /**
23
- * Custom fallback component to show if loading fails
24
- * If not provided, a default error message is shown
25
- */
26
- fallbackComponent?: React.ComponentType<any>;
27
-
28
- /**
29
- * Error handler callback
30
- */
31
- onError?: (error: Error) => void;
32
- }
33
-
34
- /**
35
- * Default fallback component shown when app loading fails
36
- */
37
- export const DefaultLoadFailedComponent: React.FC<{ message?: string }> = ({
38
- message = 'Failed to load application'
39
- }) => (
40
- <div style={{
41
- display: 'flex',
42
- justifyContent: 'center',
43
- alignItems: 'center',
44
- height: '100vh',
45
- background: 'linear-gradient(to bottom, var(--bodybg-primary), var(--bodybg-secondary))',
46
- color: '#ff4444',
47
- flexDirection: 'column',
48
- gap: '16px'
49
- }}>
50
- <div style={{ fontSize: '18px' }}>{message}</div>
51
- <button
52
- onClick={() => window.location.reload()}
53
- style={{
54
- padding: '10px 20px',
55
- backgroundColor: '#007bff',
56
- color: 'white',
57
- border: 'none',
58
- borderRadius: '4px',
59
- cursor: 'pointer'
60
- }}
61
- >
62
- Reload Page
63
- </button>
64
- </div>
65
- );
66
-
67
- /**
68
- * Create a lazy-loaded app component with error handling
69
- *
70
- * @param config - Configuration options for the lazy loader
71
- * @returns A React lazy component
72
- *
73
- * @example
74
- * ```tsx
75
- * const AppComponent = createLazyAppComponent({
76
- * importFn: () => import('./DASHAppLoader'),
77
- * initDelay: 150,
78
- * onError: (error) => console.error('Failed to load app:', error)
79
- * });
80
- *
81
- * // Then use with Suspense:
82
- * <React.Suspense fallback={<InitialLoader />}>
83
- * <AppComponent />
84
- * </React.Suspense>
85
- * ```
86
- */
87
- export const createLazyAppComponent = (
88
- config: LazyAppLoaderConfig
89
- ): React.LazyExoticComponent<React.ComponentType<any>> => {
90
- const {
91
- importFn,
92
- initDelay = 150,
93
- fallbackComponent: FallbackComponent,
94
- onError
95
- } = config;
96
-
97
- return React.lazy(() => {
98
- return new Promise<{ default: React.ComponentType<any> }>((resolve) => {
99
- setTimeout(() => {
100
- importFn()
101
- .then((module) => {
102
- resolve({ default: module.default });
103
- })
104
- .catch((error: Error) => {
105
- console.error('Failed to load app component:', error);
106
- onError?.(error);
107
-
108
- // Use custom fallback or default
109
- const ErrorComponent: React.FC = FallbackComponent
110
- ? () => React.createElement(FallbackComponent)
111
- : () => React.createElement(DefaultLoadFailedComponent, {
112
- message: `Failed to load: ${error.message}`
113
- });
114
-
115
- resolve({ default: ErrorComponent });
116
- });
117
- }, initDelay);
118
- });
119
- });
120
- };
121
-
122
- /**
123
- * Simple version of createLazyAppComponent with minimal configuration
124
- *
125
- * @param importFn - Dynamic import function
126
- * @param initDelay - Optional delay in milliseconds (default: 150)
127
- * @returns A React lazy component
128
- *
129
- * @example
130
- * ```tsx
131
- * const AppComponent = createSimpleLazyApp(
132
- * () => import('./DASHAppLoader')
133
- * );
134
- * ```
135
- */
136
- export const createSimpleLazyApp = (
137
- importFn: () => Promise<{ default: React.ComponentType<any> }>,
138
- initDelay: number = 150
139
- ): React.LazyExoticComponent<React.ComponentType<any>> => {
140
- return createLazyAppComponent({ importFn, initDelay });
141
- };
142
-
143
- export default createLazyAppComponent;
@@ -1,22 +0,0 @@
1
- /**
2
- * MinimalLayout Component
3
- *
4
- * A minimal layout wrapper that simply renders its children.
5
- * Useful as a pass-through layout when you want React-Admin
6
- * to use a different layout than the default.
7
- */
8
- import React from 'react';
9
-
10
- export interface MinimalLayoutProps {
11
- children?: React.ReactNode;
12
- }
13
-
14
- /**
15
- * MinimalLayout - A pass-through layout component
16
- * Simply renders children without any wrapper elements
17
- */
18
- export const MinimalLayout: React.FC<MinimalLayoutProps> = ({ children }) => {
19
- return <>{children}</>;
20
- };
21
-
22
- export default MinimalLayout;
@@ -1,169 +0,0 @@
1
- /**
2
- * DashRouterComponent
3
- *
4
- * A smart router component that automatically chooses between
5
- * HashRouter (for Electron/desktop) and BrowserRouter (for web).
6
- *
7
- * Environment detection is automatic when props are not provided.
8
- */
9
- import React, { Suspense } from 'react';
10
- import { BrowserRouter, HashRouter, Routes } from 'react-router-dom';
11
- import { getEnv } from '../utils/envUtils';
12
-
13
- /**
14
- * Props for DashRouterComponent
15
- */
16
- export interface DashRouterComponentProps {
17
- /**
18
- * Direct children - used when publicRoutes is not provided
19
- * @deprecated Use publicRoutes prop instead for cleaner API
20
- */
21
- children?: React.ReactNode;
22
- /** Force a specific router type */
23
- forceType?: 'hash' | 'browser';
24
- /**
25
- * Base path for BrowserRouter
26
- * @default getEnv('BASE_PATH') || '/'
27
- */
28
- basename?: string;
29
- /**
30
- * Platform type from environment (optional - auto-detected from VITE_PLATFORM_TYPE)
31
- * @default getEnv('PLATFORM_TYPE')
32
- */
33
- platformType?: string;
34
- /**
35
- * Platform name from environment (optional - auto-detected from VITE_PLATFORM)
36
- * @default getEnv('PLATFORM')
37
- */
38
- platform?: string;
39
- /** Loading fallback component shown during lazy loading */
40
- loader?: React.ReactNode;
41
- /**
42
- * Public routes to render inside Routes component.
43
- * Can be a function that returns routes (recommended) or pre-created ReactNode.
44
- * Using a function ensures routes are created inside Router context.
45
- */
46
- publicRoutes?: React.ReactNode | (() => React.ReactNode);
47
- /** Optional className for the wrapper div */
48
- className?: string;
49
- }
50
-
51
- /** @deprecated Use DashRouterComponentProps instead */
52
- export type RouterComponentProps = DashRouterComponentProps;
53
-
54
- /**
55
- * Determine if HashRouter should be used based on environment
56
- */
57
- export const shouldUseHashRouter = (platformType?: string, platform?: string): boolean => {
58
- return platformType === 'desktop' || platform === 'electron';
59
- };
60
-
61
- /**
62
- * Inner component that renders routes inside Router context
63
- * This ensures route components with hooks are created INSIDE the Router
64
- */
65
- const RouterContent: React.FC<{
66
- publicRoutes?: React.ReactNode | (() => React.ReactNode);
67
- loader?: React.ReactNode;
68
- className: string;
69
- children?: React.ReactNode;
70
- }> = ({ publicRoutes, loader, className, children }) => {
71
- if (!publicRoutes) {
72
- // Legacy: direct children
73
- return <>{children}</>;
74
- }
75
-
76
- // Resolve routes - call function if it's a function, otherwise use directly
77
- // This is called INSIDE the Router context, so useNavigate etc. will work
78
- let routes: React.ReactNode;
79
- if (typeof publicRoutes === 'function') {
80
- routes = (publicRoutes as () => React.ReactNode)();
81
- } else {
82
- routes = publicRoutes;
83
- }
84
-
85
- return (
86
- <div className={className}>
87
- <Suspense fallback={loader || <div>Loading...</div>}>
88
- <Routes>
89
- {routes}
90
- </Routes>
91
- </Suspense>
92
- </div>
93
- );
94
- };
95
-
96
- /**
97
- * DashRouterComponent - Smart router that chooses the appropriate router type
98
- *
99
- * Automatically detects platform environment when props are not provided:
100
- * - platformType: from VITE_PLATFORM_TYPE env var
101
- * - platform: from VITE_PLATFORM env var
102
- * - basename: from VITE_BASE_PATH env var (defaults to '/')
103
- */
104
- export const DashRouterComponent: React.FC<DashRouterComponentProps> = ({
105
- children,
106
- forceType,
107
- basename,
108
- platformType,
109
- platform,
110
- loader,
111
- publicRoutes,
112
- className = 'dash-public-app',
113
- }) => {
114
- // Get environment values internally if not provided as props
115
- const effectivePlatformType = platformType ?? getEnv('PLATFORM_TYPE');
116
- const effectivePlatform = platform ?? getEnv('PLATFORM');
117
- const effectiveBasename = basename ?? getEnv('BASE_PATH') ?? '/';
118
-
119
- // Render content using RouterContent component (which runs inside Router context)
120
- const content = (
121
- <RouterContent
122
- publicRoutes={publicRoutes}
123
- loader={loader}
124
- className={className}
125
- >
126
- {children}
127
- </RouterContent>
128
- );
129
-
130
- // If forceType is specified, use that
131
- if (forceType === 'hash') {
132
- return <HashRouter basename="">{content}</HashRouter>;
133
- }
134
-
135
- if (forceType === 'browser') {
136
- return <BrowserRouter basename={effectiveBasename}>{content}</BrowserRouter>;
137
- }
138
-
139
- // Auto-detect based on platform
140
- if (shouldUseHashRouter(effectivePlatformType, effectivePlatform)) {
141
- return <HashRouter basename="">{content}</HashRouter>;
142
- }
143
-
144
- return <BrowserRouter basename={effectiveBasename}>{content}</BrowserRouter>;
145
- };
146
-
147
- /**
148
- * Create a DashRouterComponent with pre-configured environment settings
149
- */
150
- export const createRouterComponent = (envVars: {
151
- PLATFORM_TYPE?: string;
152
- PLATFORM?: string;
153
- }): React.FC<{ children: React.ReactNode }> => {
154
- const RouterWrapper: React.FC<{ children: React.ReactNode }> = ({ children }) => (
155
- <DashRouterComponent
156
- platformType={envVars.PLATFORM_TYPE}
157
- platform={envVars.PLATFORM}
158
- >
159
- {children}
160
- </DashRouterComponent>
161
- );
162
-
163
- return RouterWrapper;
164
- };
165
-
166
- /** @deprecated Use DashRouterComponent instead */
167
- export const RouterComponent = DashRouterComponent;
168
-
169
- export default DashRouterComponent;
@@ -1,16 +0,0 @@
1
- /**
2
- * Components Index
3
- *
4
- * Export all utility components from dash-utils
5
- */
6
-
7
- export { MinimalLayout, type MinimalLayoutProps } from './MinimalLayout';
8
- export {
9
- DashRouterComponent,
10
- RouterComponent, // Backward compatibility alias
11
- shouldUseHashRouter,
12
- createRouterComponent,
13
- type DashRouterComponentProps,
14
- type RouterComponentProps // Backward compatibility alias
15
- } from './RouterComponent';
16
-
@@ -1,303 +0,0 @@
1
- import { useState, useRef, useEffect, createContext, useContext } from "react";
2
- import { DashIPCServiceType } from "../utils/dashIPCService";
3
-
4
- /**
5
- * IPCMessageBrokerContext
6
- *
7
- * This context provides access to messages from the Electron main process,
8
- * including log messages and subprocess outputs.
9
- *
10
- * ## Usage
11
- *
12
- * 1. Wrap your component tree with the IPCMessageBrokerProvider:
13
- * ```tsx
14
- * // In your app root or where you need IPC message access
15
- * <IPCMessageBrokerProvider>
16
- * <YourComponent />
17
- * </IPCMessageBrokerProvider>
18
- * ```
19
- *
20
- * 2. Use the hook to access messages in any child component:
21
- * ```tsx
22
- * import { useIPCMessageBroker } from 'dash-utils';
23
- *
24
- * const MyComponent = () => {
25
- * const { logMessages, subprocessOutputs, lastMessage, idleStatus } = useIPCMessageBroker();
26
- *
27
- * return (
28
- * <div>
29
- * <h3>Last Message: {lastMessage}</h3>
30
- *
31
- * <h3>Log Messages:</h3>
32
- * <ul>
33
- * {logMessages.map((log, index) => (
34
- * <li key={index} className={`log-${log.level}`}>
35
- * [{log.timestamp}] {log.level}: {log.message}
36
- * </li>
37
- * ))}
38
- * </ul>
39
- *
40
- * <h3>Subprocess Output:</h3>
41
- * <ul>
42
- * {subprocessOutputs.map((output, index) => (
43
- * <li key={index} className={`output-${output.type}`}>
44
- * [{output.timestamp}] {output.type}: {output.message}
45
- * </li>
46
- * ))}
47
- * </ul>
48
- * </div>
49
- * );
50
- * };
51
- * ```
52
- *
53
- * 3. The context also manages idle status and automatic resuscitation of
54
- * background processes if they become idle for too long.
55
- *
56
- * Note: This context works in both Electron and non-Electron environments.
57
- * In non-Electron environments, it gracefully degrades and still provides the context API.
58
- */
59
-
60
- export interface LogMessage {
61
- level: string;
62
- message: string;
63
- timestamp: string;
64
- }
65
-
66
- export interface SubprocessOutput {
67
- type: string;
68
- message: string;
69
- timestamp: string;
70
- pid?: number;
71
- exitCode?: number;
72
- error?: string;
73
- }
74
-
75
- export interface IPCMessageBrokerContextType {
76
- lastMessage: string | undefined;
77
- idleStatus: boolean;
78
- logMessages: LogMessage[];
79
- subprocessOutputs: SubprocessOutput[];
80
- isElectronAvailable: boolean;
81
- }
82
-
83
- export interface IPCMessageBrokerConfig {
84
- /** Time in milliseconds before idle status is set (default: 180000 = 3 minutes) */
85
- idleTime?: number;
86
- /** Time in milliseconds before resuscitation is triggered (default: 360000 = 6 minutes) */
87
- resuscitationTime?: number;
88
- /** Maximum number of log messages to keep in memory (default: 100) */
89
- maxLogMessages?: number;
90
- /** Maximum number of subprocess outputs to keep in memory (default: 100) */
91
- maxSubprocessOutputs?: number;
92
- /** Maximum initialization attempts (default: 5) */
93
- maxInitAttempts?: number;
94
- /** Delay between initialization attempts in ms (default: 500) */
95
- initRetryDelay?: number;
96
- }
97
-
98
- const DEFAULT_CONFIG: Required<IPCMessageBrokerConfig> = {
99
- idleTime: 180 * 1000,
100
- resuscitationTime: 360 * 1000,
101
- maxLogMessages: 100,
102
- maxSubprocessOutputs: 100,
103
- maxInitAttempts: 5,
104
- initRetryDelay: 500,
105
- };
106
-
107
- export const IPCMessageBrokerContext = createContext<IPCMessageBrokerContextType>({
108
- lastMessage: undefined,
109
- idleStatus: false,
110
- logMessages: [],
111
- subprocessOutputs: [],
112
- isElectronAvailable: false
113
- });
114
-
115
- /** Custom hook for accessing the IPC Message Broker context */
116
- export const useIPCMessageBroker = () => useContext(IPCMessageBrokerContext);
117
- // Global type declaration for DashIPCService
118
- declare global {
119
- interface Window {
120
- DashIPCService?: DashIPCServiceType;
121
- }
122
- }
123
-
124
- interface IPCMessageBrokerProviderProps {
125
- children: React.ReactNode;
126
- config?: IPCMessageBrokerConfig;
127
- }
128
-
129
- export const IPCMessageBrokerProvider = ({
130
- children,
131
- config: userConfig
132
- }: IPCMessageBrokerProviderProps) => {
133
- const config = { ...DEFAULT_CONFIG, ...userConfig };
134
-
135
- const [lastMessage, setLastMessage] = useState<string>();
136
- const [idleStatus, setIdleStatus] = useState(false);
137
- const [idleTimeout, setIdleTimeout] = useState<ReturnType<typeof setTimeout> | null>(null);
138
- const [logMessages, setLogMessages] = useState<LogMessage[]>([]);
139
- const [subprocessOutputs, setSubprocessOutputs] = useState<SubprocessOutput[]>([]);
140
- const [isElectronAvailable, setIsElectronAvailable] = useState<boolean>(false);
141
- const initAttempts = useRef(0);
142
-
143
- const resetIdleStatus = () => {
144
- setIdleStatus(false);
145
- if (idleTimeout) {
146
- clearTimeout(idleTimeout);
147
- }
148
- setIdleTimeout(setTimeout(() => {
149
- setIdleStatus(true);
150
- }, config.idleTime));
151
- };
152
-
153
- // Safely call a method if it exists
154
- const safeMethodCall = <T extends (...args: any[]) => any>(
155
- obj: any,
156
- methodName: string,
157
- fallback: T | null = null
158
- ): T | null => {
159
- if (obj && typeof obj[methodName] === 'function') {
160
- return obj[methodName].bind(obj);
161
- }
162
- console.warn(`Method ${methodName} is not available on DashIPCService`);
163
- return fallback;
164
- };
165
-
166
- // Setup IPC listeners with retry mechanism
167
- const setupIPCListeners = () => {
168
- if (typeof window === 'undefined') return false;
169
-
170
- // Check if DashIPCService is available
171
- if (!window.DashIPCService) {
172
- console.log(`DashIPCService not available yet. Attempt ${initAttempts.current + 1}/${config.maxInitAttempts}`);
173
- initAttempts.current += 1;
174
-
175
- if (initAttempts.current < config.maxInitAttempts) {
176
- setTimeout(setupIPCListeners, config.initRetryDelay);
177
- } else {
178
- console.warn('Failed to initialize DashIPCService after multiple attempts');
179
- }
180
- return false;
181
- }
182
-
183
- console.log('DashIPCService is available, setting up listeners');
184
- setIsElectronAvailable(true);
185
-
186
- const handleMessage = (message: string) => {
187
- setLastMessage(message);
188
- resetIdleStatus();
189
- };
190
-
191
- const handleLogMessage = (logData: LogMessage) => {
192
- console.log('Log message received:', logData);
193
- setLogMessages(prev => [...prev.slice(-(config.maxLogMessages - 1)), logData]);
194
- resetIdleStatus();
195
- };
196
-
197
- const handleSubprocessOutput = (data: SubprocessOutput) => {
198
- console.log('Subprocess output received:', data);
199
- setSubprocessOutputs(prev => [...prev.slice(-(config.maxSubprocessOutputs - 1)), data]);
200
- resetIdleStatus();
201
- };
202
-
203
- // Safely set up event listeners
204
- const onServiceMessage = safeMethodCall(window.DashIPCService, 'onServiceMessage');
205
- const onElectronLog = safeMethodCall(window.DashIPCService, 'onElectronLog');
206
- const onSubprocessOutput = safeMethodCall(window.DashIPCService, 'onSubprocessOutput');
207
- const onStdout = safeMethodCall(window.DashIPCService, 'onStdout');
208
-
209
- // Set up listeners if methods exist
210
- if (onServiceMessage) {
211
- onServiceMessage((data: any) => {
212
- handleMessage(data);
213
- });
214
- }
215
-
216
- if (onElectronLog) {
217
- onElectronLog((data: LogMessage) => {
218
- handleLogMessage(data);
219
- });
220
- }
221
-
222
- if (onSubprocessOutput) {
223
- onSubprocessOutput((data: SubprocessOutput) => {
224
- handleSubprocessOutput(data);
225
- });
226
- }
227
-
228
- // Fallback to stdout if onElectronLog is not available
229
- if (!onElectronLog && onStdout) {
230
- onStdout((message: string) => {
231
- // Try to parse stdout messages as log entries
232
- try {
233
- if (message.includes('{') && message.includes('}')) {
234
- const jsonStart = message.indexOf('{');
235
- const jsonEnd = message.lastIndexOf('}') + 1;
236
- const jsonStr = message.substring(jsonStart, jsonEnd);
237
- const data = JSON.parse(jsonStr);
238
-
239
- if (data.level && data.message) {
240
- handleLogMessage({
241
- level: data.level,
242
- message: data.message,
243
- timestamp: data.timestamp || new Date().toISOString()
244
- });
245
- return;
246
- }
247
- }
248
- } catch {
249
- // Not JSON or not a log structure, use as plain message
250
- }
251
-
252
- // Fallback: treat as a generic log message
253
- handleLogMessage({
254
- level: 'info',
255
- message: message,
256
- timestamp: new Date().toISOString()
257
- });
258
- });
259
- }
260
-
261
- // Start initial idle timer
262
- resetIdleStatus();
263
- return true;
264
- };
265
-
266
- useEffect(() => {
267
- setupIPCListeners();
268
-
269
- return () => {
270
- if (idleTimeout) {
271
- clearTimeout(idleTimeout);
272
- }
273
- };
274
- }, []);
275
-
276
- useEffect(() => {
277
- if (idleStatus && window.DashIPCService && typeof window.DashIPCService.action === 'function') {
278
- const resuscitateTimeout = setTimeout(() => {
279
- window.DashIPCService!.action!('resuscitate', null);
280
- }, config.resuscitationTime - config.idleTime);
281
-
282
- return () => {
283
- clearTimeout(resuscitateTimeout);
284
- };
285
- }
286
- }, [idleStatus, config.resuscitationTime, config.idleTime]);
287
-
288
- const contextValue: IPCMessageBrokerContextType = {
289
- lastMessage,
290
- idleStatus,
291
- logMessages,
292
- subprocessOutputs,
293
- isElectronAvailable
294
- };
295
-
296
- return (
297
- <IPCMessageBrokerContext.Provider value={contextValue}>
298
- {children}
299
- </IPCMessageBrokerContext.Provider>
300
- );
301
- };
302
-
303
- export default IPCMessageBrokerProvider;
@@ -1,34 +0,0 @@
1
- import { useEffect } from 'react';
2
-
3
- /**
4
- * Hook to handle Capacitor app state changes
5
- * Triggers a refresh callback when the app resumes from background
6
- *
7
- * @param onResume - Callback function to execute when app resumes
8
- */
9
- export const useCapacitorAppStateRefresh = (onResume?: () => void) => {
10
- useEffect(() => {
11
- const CapacitorApp = (window as any)?.Capacitor?.Plugins?.App;
12
- console.log('[useCapacitorAppStateRefresh] Checking for Capacitor App plugin:', !!CapacitorApp);
13
-
14
- if (!CapacitorApp) return;
15
-
16
- const handler = (state: { isActive: boolean }) => {
17
- console.log('[useCapacitorAppStateRefresh] App state changed:', state);
18
- if (state.isActive) {
19
- console.log('[useCapacitorAppStateRefresh] App is resuming, triggering callback');
20
- onResume?.();
21
- }
22
- };
23
-
24
- CapacitorApp.addListener('appStateChange', handler);
25
- console.log('[useCapacitorAppStateRefresh] Added appStateChange listener');
26
-
27
- return () => {
28
- CapacitorApp.removeAllListeners?.();
29
- console.log('[useCapacitorAppStateRefresh] Removed all Capacitor App listeners');
30
- };
31
- }, [onResume]);
32
- };
33
-
34
- export default useCapacitorAppStateRefresh;