@legendapp/spark 0.0.1-next.2 → 0.0.1-next.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/LICENSE +21 -0
- package/README.md +10 -4
- package/ai-codex.ts +1 -0
- package/ai.ts +1 -0
- package/app-documents.ts +1 -0
- package/config-plugin.d.cts +2 -0
- package/contracts.ts +2 -0
- package/diagnostics.ts +1 -0
- package/expo-config.d.cts +1 -0
- package/metro.cjs +4 -1
- package/metro.d.cts +12 -0
- package/native.cjs +3 -1
- package/native.d.cts +6 -0
- package/package.json +82 -14
- package/schema.json +276 -58
- package/settings-observable.ts +1 -0
- package/settings-window.ts +1 -0
- package/shortcuts-commands.ts +1 -0
- package/shortcuts-keyboard.ts +3 -0
- package/ui-classnames.ts +1 -0
- package/ui-glass.ts +1 -0
- package/ui-search.ts +1 -0
- package/ui-sidebar.ts +1 -0
- package/ui-split-view.ts +1 -0
- package/ui-symbol.ts +1 -0
- package/vendor/node_modules/@legendapp/spark-ai/package.json +19 -0
- package/vendor/node_modules/@legendapp/spark-ai/src/availability.ts +17 -0
- package/vendor/node_modules/@legendapp/spark-ai/src/index.ts +15 -0
- package/vendor/node_modules/@legendapp/spark-ai/src/invocations.ts +34 -0
- package/vendor/node_modules/@legendapp/spark-ai/src/output.ts +62 -0
- package/vendor/node_modules/@legendapp/spark-ai/src/run.ts +12 -0
- package/vendor/node_modules/@legendapp/spark-ai/src/types.ts +16 -0
- package/vendor/node_modules/@legendapp/spark-audio/macos/RNSparkAudio.h +2 -1
- package/vendor/node_modules/@legendapp/spark-audio/macos/RNSparkAudio.mm +126 -24
- package/vendor/node_modules/@legendapp/spark-audio/package.json +5 -2
- package/vendor/node_modules/@legendapp/spark-audio/src/NativeSparkAudio.ts +5 -1
- package/vendor/node_modules/@legendapp/spark-audio/src/desktop.ts +36 -32
- package/vendor/node_modules/@legendapp/spark-audio/src/events.ts +11 -0
- package/vendor/node_modules/@legendapp/spark-audio/src/hooks.ts +65 -0
- package/vendor/node_modules/@legendapp/spark-audio/src/index.web.ts +92 -33
- package/vendor/node_modules/@legendapp/spark-audio/src/media-session-unavailable.ts +6 -4
- package/vendor/node_modules/@legendapp/spark-audio/src/media-session.ts +52 -19
- package/vendor/node_modules/@legendapp/spark-audio/src/media-session.web.ts +18 -10
- package/vendor/node_modules/@legendapp/spark-audio/src/media-types.ts +40 -13
- package/vendor/node_modules/@legendapp/spark-audio/src/mobile.ts +40 -32
- package/vendor/node_modules/@legendapp/spark-audio/src/player.ts +97 -0
- package/vendor/node_modules/@legendapp/spark-audio/src/status-listeners.ts +21 -15
- package/vendor/node_modules/@legendapp/spark-audio/src/types.ts +9 -4
- package/vendor/node_modules/@legendapp/spark-audio/windows/SparkAudio/SparkAudio.h +67 -20
- package/vendor/node_modules/@legendapp/spark-auth-session/package.json +4 -3
- package/vendor/node_modules/@legendapp/spark-auth-session/src/core.ts +60 -42
- package/vendor/node_modules/@legendapp/spark-auth-session/src/index.ts +28 -12
- package/vendor/node_modules/@legendapp/spark-auth-session/src/mobile.ts +97 -41
- package/vendor/node_modules/@legendapp/spark-auth-session/src/types.ts +20 -9
- package/vendor/node_modules/@legendapp/spark-cli/dist/add-desktop.js +50 -7
- package/vendor/node_modules/@legendapp/spark-cli/dist/build-mode.js +1 -1
- package/vendor/node_modules/@legendapp/spark-cli/dist/build.js +83 -48
- package/vendor/node_modules/@legendapp/spark-cli/dist/cli-arguments.js +60 -0
- package/vendor/node_modules/@legendapp/spark-cli/dist/commands.js +7 -2
- package/vendor/node_modules/@legendapp/spark-cli/dist/create.js +31 -5
- package/vendor/node_modules/@legendapp/spark-cli/dist/credentials.js +69 -23
- package/vendor/node_modules/@legendapp/spark-cli/dist/dev-command.js +12 -3
- package/vendor/node_modules/@legendapp/spark-cli/dist/dev.js +12 -9
- package/vendor/node_modules/@legendapp/spark-cli/dist/examples.js +1 -1
- package/vendor/node_modules/@legendapp/spark-cli/dist/expo-dev-patch.cjs +4 -2
- package/vendor/node_modules/@legendapp/spark-cli/dist/expo-metro.cjs +1 -1
- package/vendor/node_modules/@legendapp/spark-cli/dist/expo-node.js +3 -3
- package/vendor/node_modules/@legendapp/spark-cli/dist/index.js +10 -38
- package/vendor/node_modules/@legendapp/spark-cli/dist/local.js +1 -1
- package/vendor/node_modules/@legendapp/spark-cli/dist/metro.cjs +26 -5
- package/vendor/node_modules/@legendapp/spark-cli/dist/native-metadata.js +26 -0
- package/vendor/node_modules/@legendapp/spark-cli/dist/native-patch-preflight.js +84 -0
- package/vendor/node_modules/@legendapp/spark-cli/dist/native-preparation.js +88 -0
- package/vendor/node_modules/@legendapp/spark-cli/dist/notary-profiles.js +75 -0
- package/vendor/node_modules/@legendapp/spark-cli/dist/package.js +4 -2
- package/vendor/node_modules/@legendapp/spark-cli/dist/platform.js +16 -2
- package/vendor/node_modules/@legendapp/spark-cli/dist/project.js +66 -13
- package/vendor/node_modules/@legendapp/spark-cli/dist/release.js +84 -4
- package/vendor/node_modules/@legendapp/spark-cli/dist/release.json +23 -18
- package/vendor/node_modules/@legendapp/spark-cli/dist/runner-install.js +145 -31
- package/vendor/node_modules/@legendapp/spark-cli/dist/signing.js +4 -3
- package/vendor/node_modules/@legendapp/spark-cli/dist/updates.js +41 -4
- package/vendor/node_modules/@legendapp/spark-cli/dist/windows.js +4 -1
- package/vendor/node_modules/@legendapp/spark-cli/package.json +7 -6
- package/vendor/node_modules/@legendapp/spark-cli/templates/blank-typescript/App.tsx +6 -12
- package/vendor/node_modules/@legendapp/spark-cli/templates/blank-typescript/desktop.config.json +5 -3
- package/vendor/node_modules/@legendapp/spark-cli/templates/blank-typescript/package.json +11 -9
- package/vendor/node_modules/@legendapp/spark-cli/templates/diff-lite/Git.macos.tsx +2 -2
- package/vendor/node_modules/@legendapp/spark-cli/templates/document-editor/Integration.macos.tsx +23 -21
- package/vendor/node_modules/@legendapp/spark-cli/templates/document-editor/Integration.windows.tsx +23 -21
- package/vendor/node_modules/@legendapp/spark-cli/templates/document-editor/io.desktop.ts +11 -8
- package/vendor/node_modules/@legendapp/spark-cli/templates/document-editor/io.macos.ts +3 -3
- package/vendor/node_modules/@legendapp/spark-cli/templates/example-shared/Lifecycle.desktop.tsx +8 -14
- package/vendor/node_modules/@legendapp/spark-cli/templates/example-shared/OpenFiles.desktop.tsx +5 -10
- package/vendor/node_modules/@legendapp/spark-cli/templates/example-shared/io.desktop.ts +11 -8
- package/vendor/node_modules/@legendapp/spark-cli/templates/example-shared/io.macos.ts +3 -3
- package/vendor/node_modules/@legendapp/spark-cli/templates/music-lite/assets.desktop.ts +2 -2
- package/vendor/node_modules/@legendapp/spark-cli/templates/notes-lite/Activation.desktop.tsx +2 -2
- package/vendor/node_modules/@legendapp/spark-cli/templates/notes-lite/Desktop.desktop.ts +37 -15
- package/vendor/node_modules/@legendapp/spark-cli/templates/notes-lite/session.ts +5 -6
- package/vendor/node_modules/@legendapp/spark-cli/templates/notes-lite/window-session.ts +5 -4
- package/vendor/node_modules/@legendapp/spark-cli/templates/universal/desktop.config.json +5 -3
- package/vendor/node_modules/@legendapp/spark-cli/templates/universal/metro.config.js +1 -1
- package/vendor/node_modules/@legendapp/spark-cli/templates/universal/package.json +13 -11
- package/vendor/node_modules/@legendapp/spark-cli/templates/universal/react-native.config.js +1 -1
- package/vendor/node_modules/@legendapp/spark-cli/templates/windows/package.json +13 -11
- package/vendor/node_modules/@legendapp/spark-cli/templates/windows/react-native.config.js +1 -1
- package/vendor/node_modules/@legendapp/spark-clipboard/macos/RNDesktopClipboard.mm +10 -16
- package/vendor/node_modules/@legendapp/spark-clipboard/package.json +2 -2
- package/vendor/node_modules/@legendapp/spark-clipboard/src/NativeDesktopClipboard.ts +1 -1
- package/vendor/node_modules/@legendapp/spark-clipboard/src/desktop.ts +55 -31
- package/vendor/node_modules/@legendapp/spark-clipboard/src/expo.ts +21 -11
- package/vendor/node_modules/@legendapp/spark-clipboard/src/options.ts +8 -0
- package/vendor/node_modules/@legendapp/spark-clipboard/src/types.ts +10 -0
- package/vendor/node_modules/@legendapp/spark-clipboard/windows/SparkClipboard/SparkClipboard.h +38 -15
- package/vendor/node_modules/@legendapp/spark-clipboard/windows/SparkClipboard/SparkClipboard.vcxproj +2 -0
- package/vendor/node_modules/@legendapp/spark-codex/RNCodex.podspec +22 -0
- package/vendor/node_modules/@legendapp/spark-codex/cpp/HybridCodexAppServer.hpp +23 -0
- package/vendor/node_modules/@legendapp/spark-codex/cpp/HybridCodexAppServer.mm +1529 -0
- package/vendor/node_modules/@legendapp/spark-codex/nitro.json +21 -0
- package/vendor/node_modules/@legendapp/spark-codex/nitrogen/generated/.gitattributes +1 -0
- package/vendor/node_modules/@legendapp/spark-codex/nitrogen/generated/ios/RNCodex+autolinking.rb +62 -0
- package/vendor/node_modules/@legendapp/spark-codex/nitrogen/generated/ios/RNCodex-Swift-Cxx-Bridge.cpp +17 -0
- package/vendor/node_modules/@legendapp/spark-codex/nitrogen/generated/ios/RNCodex-Swift-Cxx-Bridge.hpp +27 -0
- package/vendor/node_modules/@legendapp/spark-codex/nitrogen/generated/ios/RNCodex-Swift-Cxx-Umbrella.hpp +38 -0
- package/vendor/node_modules/@legendapp/spark-codex/nitrogen/generated/ios/RNCodexAutolinking.mm +35 -0
- package/vendor/node_modules/@legendapp/spark-codex/nitrogen/generated/ios/RNCodexAutolinking.swift +16 -0
- package/vendor/node_modules/@legendapp/spark-codex/nitrogen/generated/shared/c++/CodexAvailability.hpp +95 -0
- package/vendor/node_modules/@legendapp/spark-codex/nitrogen/generated/shared/c++/CodexRunResult.hpp +99 -0
- package/vendor/node_modules/@legendapp/spark-codex/nitrogen/generated/shared/c++/HybridCodexAppServerSpec.cpp +24 -0
- package/vendor/node_modules/@legendapp/spark-codex/nitrogen/generated/shared/c++/HybridCodexAppServerSpec.hpp +71 -0
- package/vendor/node_modules/@legendapp/spark-codex/package.json +35 -0
- package/vendor/node_modules/@legendapp/spark-codex/react-native.config.js +11 -0
- package/vendor/node_modules/@legendapp/spark-codex/src/Codex.nitro.ts +30 -0
- package/vendor/node_modules/@legendapp/spark-codex/src/index.ts +65 -0
- package/vendor/node_modules/@legendapp/spark-codex/src/native.ts +6 -0
- package/vendor/node_modules/@legendapp/spark-commands/package.json +21 -0
- package/vendor/node_modules/@legendapp/spark-commands/src/bindings.ts +90 -0
- package/vendor/node_modules/@legendapp/spark-commands/src/index.tsx +400 -0
- package/vendor/node_modules/@legendapp/spark-commands/src/router.ts +138 -0
- package/vendor/node_modules/@legendapp/spark-commands/src/storage.ts +20 -0
- package/vendor/node_modules/@legendapp/spark-context-menu/macos/RNContextMenu.mm +7 -8
- package/vendor/node_modules/@legendapp/spark-context-menu/package.json +4 -3
- package/vendor/node_modules/@legendapp/spark-context-menu/src/NativeContextMenu.ts +1 -1
- package/vendor/node_modules/@legendapp/spark-context-menu/src/index.ts +26 -26
- package/vendor/node_modules/@legendapp/spark-context-menu/windows/SparkContextMenu/SparkContextMenu.h +3 -2
- package/vendor/node_modules/@legendapp/spark-desktop-app/RNDesktopApp.podspec +2 -1
- package/vendor/node_modules/@legendapp/spark-desktop-app/cpp/SparkBinaryJSI.hpp +89 -0
- package/vendor/node_modules/@legendapp/spark-desktop-app/cpp/SparkBinaryWindows.hpp +22 -0
- package/vendor/node_modules/@legendapp/spark-desktop-app/macos/RNDesktopApp.mm +13 -7
- package/vendor/node_modules/@legendapp/spark-desktop-app/macos/SparkBinaryJSI.h +48 -0
- package/vendor/node_modules/@legendapp/spark-desktop-app/macos/SparkDesktop.h +4 -0
- package/vendor/node_modules/@legendapp/spark-desktop-app/macos/SparkDesktop.mm +33 -33
- package/vendor/node_modules/@legendapp/spark-desktop-app/macos/SparkDesktopError.h +20 -0
- package/vendor/node_modules/@legendapp/spark-desktop-app/macos/SparkLifecycle.h +26 -0
- package/vendor/node_modules/@legendapp/spark-desktop-app/macos/SparkLifecycle.mm +49 -0
- package/vendor/node_modules/@legendapp/spark-desktop-app/macos/SparkQuitCoordinator.h +9 -0
- package/vendor/node_modules/@legendapp/spark-desktop-app/macos/SparkQuitCoordinator.mm +70 -0
- package/vendor/node_modules/@legendapp/spark-desktop-app/macos/SparkWindow.mm +9 -6
- package/vendor/node_modules/@legendapp/spark-desktop-app/macos/recent-documents/RNRecentDocumentController.mm +55 -0
- package/vendor/node_modules/@legendapp/spark-desktop-app/package.json +5 -3
- package/vendor/node_modules/@legendapp/spark-desktop-app/src/NativeDesktopApp.ts +1 -1
- package/vendor/node_modules/@legendapp/spark-desktop-app/src/api.ts +86 -40
- package/vendor/node_modules/@legendapp/spark-desktop-app/src/contracts/accelerator.ts +40 -0
- package/vendor/node_modules/@legendapp/spark-desktop-app/src/contracts/index.ts +56 -0
- package/vendor/node_modules/@legendapp/spark-desktop-app/src/contracts/menu.ts +114 -0
- package/vendor/node_modules/@legendapp/spark-desktop-app/src/contracts/native-buffer.ts +22 -0
- package/vendor/node_modules/@legendapp/spark-desktop-app/src/contracts/path.ts +24 -0
- package/vendor/node_modules/@legendapp/spark-desktop-app/src/events.ts +75 -0
- package/vendor/node_modules/@legendapp/spark-desktop-app/src/index.ts +2 -0
- package/vendor/node_modules/@legendapp/spark-desktop-app/src/index.windows.ts +2 -0
- package/vendor/node_modules/@legendapp/spark-desktop-app/src/open-requests.ts +43 -0
- package/vendor/node_modules/@legendapp/spark-desktop-app/src/restoration.ts +11 -0
- package/vendor/node_modules/@legendapp/spark-desktop-app/src/transport.ts +10 -0
- package/vendor/node_modules/@legendapp/spark-desktop-config/app.plugin.cjs +10 -5
- package/vendor/node_modules/@legendapp/spark-desktop-config/app.plugin.d.cts +3 -0
- package/vendor/node_modules/@legendapp/spark-desktop-config/autolinking.cjs +35 -0
- package/vendor/node_modules/@legendapp/spark-desktop-config/config.cjs +16 -3
- package/vendor/node_modules/@legendapp/spark-desktop-config/config.d.cts +89 -9
- package/vendor/node_modules/@legendapp/spark-desktop-config/expo.d.cts +3 -0
- package/vendor/node_modules/@legendapp/spark-desktop-config/identity.cjs +3 -2
- package/vendor/node_modules/@legendapp/spark-desktop-config/lifecycle.cjs +20 -0
- package/vendor/node_modules/@legendapp/spark-desktop-config/package.json +6 -5
- package/vendor/node_modules/@legendapp/spark-desktop-config/schema.json +276 -58
- package/vendor/node_modules/@legendapp/spark-desktop-config/updates.cjs +1 -0
- package/vendor/node_modules/@legendapp/spark-desktop-config/validation.cjs +35 -0
- package/vendor/node_modules/@legendapp/spark-desktop-config/windows.plugin.cjs +2 -1
- package/vendor/node_modules/@legendapp/spark-desktop-host/AppDelegate.mm +129 -11
- package/vendor/node_modules/@legendapp/spark-desktop-host/package.json +2 -2
- package/vendor/node_modules/@legendapp/spark-desktop-host/windows/application.inc +277 -121
- package/vendor/node_modules/@legendapp/spark-desktop-links/common/AuthLoopback.h +5 -7
- package/vendor/node_modules/@legendapp/spark-desktop-links/macos/RNDesktopLinks.mm +10 -9
- package/vendor/node_modules/@legendapp/spark-desktop-links/package.json +2 -2
- package/vendor/node_modules/@legendapp/spark-desktop-links/src/NativeDesktopLinks.ts +1 -1
- package/vendor/node_modules/@legendapp/spark-desktop-links/src/api.ts +27 -33
- package/vendor/node_modules/@legendapp/spark-desktop-links/src/expo.ts +3 -4
- package/vendor/node_modules/@legendapp/spark-desktop-links/src/native.ts +9 -0
- package/vendor/node_modules/@legendapp/spark-desktop-links/windows/SparkLinks/SparkLinks.h +22 -22
- package/vendor/node_modules/@legendapp/spark-desktop-shortcuts/RNDesktopShortcuts.podspec +1 -0
- package/vendor/node_modules/@legendapp/spark-desktop-shortcuts/macos/RNDesktopShortcuts.mm +1 -1
- package/vendor/node_modules/@legendapp/spark-desktop-shortcuts/macos/keyboard-manager/RNKeyboardManager.h +9 -0
- package/vendor/node_modules/@legendapp/spark-desktop-shortcuts/macos/keyboard-manager/RNKeyboardManager.mm +307 -0
- package/vendor/node_modules/@legendapp/spark-desktop-shortcuts/package.json +8 -5
- package/vendor/node_modules/@legendapp/spark-desktop-shortcuts/src/NativeDesktopShortcuts.ts +1 -1
- package/vendor/node_modules/@legendapp/spark-desktop-shortcuts/src/api.ts +39 -14
- package/vendor/node_modules/@legendapp/spark-desktop-shortcuts/src/keyboard-manager/NativeKeyboardManager.ts +12 -0
- package/vendor/node_modules/@legendapp/spark-desktop-shortcuts/src/keyboard-manager/codes.ts +108 -0
- package/vendor/node_modules/@legendapp/spark-desktop-shortcuts/src/keyboard-manager/index.ts +99 -0
- package/vendor/node_modules/@legendapp/spark-desktop-windows/RNDesktopWindows.podspec +2 -0
- package/vendor/node_modules/@legendapp/spark-desktop-windows/macos/RNDesktopWindows.mm +229 -103
- package/vendor/node_modules/@legendapp/spark-desktop-windows/macos/SparkWindowGeometry.h +63 -0
- package/vendor/node_modules/@legendapp/spark-desktop-windows/macos/window-manager/LegendWindowRegistry.h +20 -0
- package/vendor/node_modules/@legendapp/spark-desktop-windows/macos/window-manager/LegendWindowRegistry.mm +27 -0
- package/vendor/node_modules/@legendapp/spark-desktop-windows/macos/window-manager/RNWindowManager.h +12 -0
- package/vendor/node_modules/@legendapp/spark-desktop-windows/macos/window-manager/RNWindowManager.mm +3130 -0
- package/vendor/node_modules/@legendapp/spark-desktop-windows/macos/window-manager/RNWindowManagerStartup.mm +31 -0
- package/vendor/node_modules/@legendapp/spark-desktop-windows/macos/window-manager/SidebarStartupFallbacks.mm +14 -0
- package/vendor/node_modules/@legendapp/spark-desktop-windows/package.json +10 -6
- package/vendor/node_modules/@legendapp/spark-desktop-windows/src/NativeDesktopWindowManager.ts +1 -1
- package/vendor/node_modules/@legendapp/spark-desktop-windows/src/api.ts +144 -70
- package/vendor/node_modules/@legendapp/spark-desktop-windows/src/diagnostics.ts +17 -0
- package/vendor/node_modules/@legendapp/spark-desktop-windows/src/index.ts +3 -1
- package/vendor/node_modules/@legendapp/spark-desktop-windows/src/index.windows.ts +3 -1
- package/vendor/node_modules/@legendapp/spark-desktop-windows/src/macos-adapter.ts +53 -0
- package/vendor/node_modules/@legendapp/spark-desktop-windows/src/macos.ts +51 -0
- package/vendor/node_modules/@legendapp/spark-desktop-windows/src/transport.ts +41 -0
- package/vendor/node_modules/@legendapp/spark-desktop-windows/src/types.ts +140 -0
- package/vendor/node_modules/@legendapp/spark-desktop-windows/src/validation.ts +162 -0
- package/vendor/node_modules/@legendapp/spark-desktop-windows/src/window-manager/NativeWindowManager.ts +28 -0
- package/vendor/node_modules/@legendapp/spark-desktop-windows/src/windows/WindowProvider.tsx +20 -0
- package/vendor/node_modules/@legendapp/spark-desktop-windows/src/windows/createWindowsNavigator.tsx +78 -0
- package/vendor/node_modules/@legendapp/spark-desktop-windows/src/windows/index.ts +6 -0
- package/vendor/node_modules/@legendapp/spark-desktop-windows/src/windows/primaryWindowLifecycle.ts +34 -0
- package/vendor/node_modules/@legendapp/spark-desktop-windows/src/windows/types.ts +11 -0
- package/vendor/node_modules/@legendapp/spark-desktop-windows/src/windows/usePrimaryWindowLifecycle.ts +18 -0
- package/vendor/node_modules/@legendapp/spark-desktop-windows/src/windows/useWindowFocusEffect.ts +17 -0
- package/vendor/node_modules/@legendapp/spark-documents/package.json +22 -0
- package/vendor/node_modules/@legendapp/spark-documents/src/controller.ts +97 -0
- package/vendor/node_modules/@legendapp/spark-documents/src/documentTransition.ts +13 -0
- package/vendor/node_modules/@legendapp/spark-documents/src/hooks.ts +139 -0
- package/vendor/node_modules/@legendapp/spark-documents/src/index.tsx +50 -0
- package/vendor/node_modules/@legendapp/spark-documents/src/reload.ts +39 -0
- package/vendor/node_modules/@legendapp/spark-documents/src/requests.ts +15 -0
- package/vendor/node_modules/@legendapp/spark-drag-drop/package.json +4 -3
- package/vendor/node_modules/@legendapp/spark-drag-drop/src/DesktopDragViewNativeComponent.ts +1 -1
- package/vendor/node_modules/@legendapp/spark-drag-drop/src/contracts.ts +73 -18
- package/vendor/node_modules/@legendapp/spark-drag-drop/src/index.tsx +58 -15
- package/vendor/node_modules/@legendapp/spark-drag-drop/windows/SparkDragDrop/SparkDragDrop.h +14 -8
- package/vendor/node_modules/@legendapp/spark-file-dialog/ios/RNFileDialog.mm +34 -121
- package/vendor/node_modules/@legendapp/spark-file-dialog/package.json +12 -5
- package/vendor/node_modules/@legendapp/spark-file-dialog/src/NativeFileDialog.ts +1 -5
- package/vendor/node_modules/@legendapp/spark-file-dialog/src/index.ts +19 -84
- package/vendor/node_modules/@legendapp/spark-file-dialog/src/native.ts +12 -0
- package/vendor/node_modules/@legendapp/spark-file-dialog/src/options.ts +34 -14
- package/vendor/node_modules/@legendapp/spark-file-dialog/src/types.ts +26 -0
- package/vendor/node_modules/@legendapp/spark-file-dialog/windows/SparkFileDialog/SparkFileDialog.h +42 -58
- package/vendor/node_modules/@legendapp/spark-file-system/RNDesktopFileSystem.podspec +1 -0
- package/vendor/node_modules/@legendapp/spark-file-system/macos/RNDesktopFileSystem.mm +32 -21
- package/vendor/node_modules/@legendapp/spark-file-system/macos/SparkFileMutations.h +24 -0
- package/vendor/node_modules/@legendapp/spark-file-system/macos/SparkFileMutations.mm +215 -0
- package/vendor/node_modules/@legendapp/spark-file-system/macos/file-scanner/RNFileScanner.h +9 -0
- package/vendor/node_modules/@legendapp/spark-file-system/macos/file-scanner/RNFileScanner.mm +82 -0
- package/vendor/node_modules/@legendapp/spark-file-system/macos/file-scanner/RNFileScannerCore.h +47 -0
- package/vendor/node_modules/@legendapp/spark-file-system/macos/file-scanner/RNFileScannerCore.mm +306 -0
- package/vendor/node_modules/@legendapp/spark-file-system/package.json +8 -6
- package/vendor/node_modules/@legendapp/spark-file-system/src/NativeDesktopFileSystem.ts +1 -1
- package/vendor/node_modules/@legendapp/spark-file-system/src/file-scanner/NativeFileScanner.ts +11 -0
- package/vendor/node_modules/@legendapp/spark-file-system/src/file-scanner/index.ts +93 -0
- package/vendor/node_modules/@legendapp/spark-file-system/src/handles.ts +48 -14
- package/vendor/node_modules/@legendapp/spark-file-system/src/index.ts +134 -45
- package/vendor/node_modules/@legendapp/spark-file-system/src/path.ts +1 -9
- package/vendor/node_modules/@legendapp/spark-file-system/windows/SparkFileSystem/SparkFileSystem.h +102 -26
- package/vendor/node_modules/@legendapp/spark-file-system/windows/SparkFileSystem/SparkFileSystem.vcxproj +2 -0
- package/vendor/node_modules/@legendapp/spark-global-shortcuts/RNDesktopGlobalShortcuts.podspec +1 -0
- package/vendor/node_modules/@legendapp/spark-global-shortcuts/macos/RNDesktopGlobalShortcuts.mm +7 -4
- package/vendor/node_modules/@legendapp/spark-global-shortcuts/package.json +4 -3
- package/vendor/node_modules/@legendapp/spark-global-shortcuts/src/NativeDesktopGlobalShortcuts.ts +1 -1
- package/vendor/node_modules/@legendapp/spark-global-shortcuts/src/index.ts +39 -10
- package/vendor/node_modules/@legendapp/spark-global-shortcuts/windows/SparkGlobalShortcuts/SparkGlobalShortcuts.h +5 -4
- package/vendor/node_modules/@legendapp/spark-message-dialog/macos/RNDesktopMessageDialog.mm +2 -2
- package/vendor/node_modules/@legendapp/spark-message-dialog/package.json +2 -2
- package/vendor/node_modules/@legendapp/spark-message-dialog/src/NativeDesktopMessageDialog.ts +1 -1
- package/vendor/node_modules/@legendapp/spark-message-dialog/src/index.ts +48 -11
- package/vendor/node_modules/@legendapp/spark-native-menu/ios/RNNativeMenu.mm +141 -609
- package/vendor/node_modules/@legendapp/spark-native-menu/package.json +9 -4
- package/vendor/node_modules/@legendapp/spark-native-menu/src/NativeMenu.ts +2 -7
- package/vendor/node_modules/@legendapp/spark-native-menu/src/api.ts +76 -121
- package/vendor/node_modules/@legendapp/spark-native-menu/src/hooks.ts +97 -0
- package/vendor/node_modules/@legendapp/spark-native-menu/src/windows-menus.ts +43 -37
- package/vendor/node_modules/@legendapp/spark-notifications/macos/RNDesktopNotifications.mm +75 -30
- package/vendor/node_modules/@legendapp/spark-notifications/package.json +2 -2
- package/vendor/node_modules/@legendapp/spark-notifications/src/NativeDesktopNotifications.ts +1 -1
- package/vendor/node_modules/@legendapp/spark-notifications/src/index.ts +130 -42
- package/vendor/node_modules/@legendapp/spark-notifications/windows/SparkNotifications/SparkNotifications.h +46 -8
- package/vendor/node_modules/@legendapp/spark-processes/macos/RNDesktopProcesses.mm +94 -21
- package/vendor/node_modules/@legendapp/spark-processes/package.json +4 -3
- package/vendor/node_modules/@legendapp/spark-processes/src/NativeDesktopProcesses.ts +1 -1
- package/vendor/node_modules/@legendapp/spark-processes/src/index.ts +124 -28
- package/vendor/node_modules/@legendapp/spark-processes/src/types.ts +34 -0
- package/vendor/node_modules/@legendapp/spark-processes/windows/SparkProcesses/SparkProcesses.h +83 -34
- package/vendor/node_modules/@legendapp/spark-processes/windows/SparkProcesses/SparkProcesses.vcxproj +2 -0
- package/vendor/node_modules/@legendapp/spark-secure-storage/macos/RNDesktopSecureStorage.mm +49 -40
- package/vendor/node_modules/@legendapp/spark-secure-storage/package.json +2 -2
- package/vendor/node_modules/@legendapp/spark-secure-storage/src/NativeDesktopSecureStorage.ts +1 -1
- package/vendor/node_modules/@legendapp/spark-secure-storage/src/desktop.ts +16 -14
- package/vendor/node_modules/@legendapp/spark-secure-storage/src/expo.ts +0 -1
- package/vendor/node_modules/@legendapp/spark-secure-storage/src/options.ts +3 -2
- package/vendor/node_modules/@legendapp/spark-secure-storage/src/unavailable.ts +6 -3
- package/vendor/node_modules/@legendapp/spark-settings/package.json +10 -3
- package/vendor/node_modules/@legendapp/spark-settings/src/fileStorage.ts +11 -0
- package/vendor/node_modules/@legendapp/spark-settings/src/index.ts +7 -9
- package/vendor/node_modules/@legendapp/spark-settings/src/storage/index.ts +142 -0
- package/vendor/node_modules/@legendapp/spark-settings/src/store.ts +63 -21
- package/vendor/node_modules/@legendapp/spark-settings-ui/package.json +20 -0
- package/vendor/node_modules/@legendapp/spark-settings-ui/src/index.tsx +436 -0
- package/vendor/node_modules/@legendapp/spark-settings-ui/src/options.ts +10 -0
- package/vendor/node_modules/@legendapp/spark-sqlite/package.json +3 -3
- package/vendor/node_modules/@legendapp/spark-sqlite/src/database.ts +182 -0
- package/vendor/node_modules/@legendapp/spark-sqlite/src/index.ts +19 -6
- package/vendor/node_modules/@legendapp/spark-sqlite/src/types.ts +22 -0
- package/vendor/node_modules/@legendapp/spark-system/macos/RNDesktopSystem.mm +36 -11
- package/vendor/node_modules/@legendapp/spark-system/package.json +2 -2
- package/vendor/node_modules/@legendapp/spark-system/src/NativeDesktopSystem.ts +1 -1
- package/vendor/node_modules/@legendapp/spark-system/src/index.ts +89 -32
- package/vendor/node_modules/@legendapp/spark-system/windows/SparkSystem/SparkSystem.h +8 -4
- package/vendor/node_modules/@legendapp/spark-tray/macos/RNDesktopTray.mm +20 -8
- package/vendor/node_modules/@legendapp/spark-tray/package.json +2 -2
- package/vendor/node_modules/@legendapp/spark-tray/src/NativeDesktopTray.ts +1 -1
- package/vendor/node_modules/@legendapp/spark-tray/src/index.ts +91 -34
- package/vendor/node_modules/@legendapp/spark-tray/windows/SparkTray/SparkTray.h +45 -15
- package/vendor/node_modules/@legendapp/spark-ui/macos/RNSparkButton.mm +2 -1
- package/vendor/node_modules/@legendapp/spark-ui/macos/RNSparkTextInput.mm +10 -2
- package/vendor/node_modules/@legendapp/spark-ui/macos/appkit-split-view/RNSidebarSplitViewComponent.h +15 -0
- package/vendor/node_modules/@legendapp/spark-ui/macos/appkit-split-view/RNSidebarSplitViewComponent.mm +1182 -0
- package/vendor/node_modules/@legendapp/spark-ui/macos/glass-effect-view/RNGlassEffectView.mm +72 -0
- package/vendor/node_modules/@legendapp/spark-ui/macos/native-select/RNNativeSegmentedControl.h +15 -0
- package/vendor/node_modules/@legendapp/spark-ui/macos/native-select/RNNativeSegmentedControl.mm +194 -0
- package/vendor/node_modules/@legendapp/spark-ui/macos/native-select/RNNativeSelect.h +15 -0
- package/vendor/node_modules/@legendapp/spark-ui/macos/native-select/RNNativeSelect.mm +180 -0
- package/vendor/node_modules/@legendapp/spark-ui/macos/sf-symbol/RNSFSymbol.h +15 -0
- package/vendor/node_modules/@legendapp/spark-ui/macos/sf-symbol/RNSFSymbol.mm +155 -0
- package/vendor/node_modules/@legendapp/spark-ui/macos/sidebar/RNSidebar.h +18 -0
- package/vendor/node_modules/@legendapp/spark-ui/macos/sidebar/RNSidebar.mm +645 -0
- package/vendor/node_modules/@legendapp/spark-ui/macos/text-input-search/RNTextInputSearch.h +15 -0
- package/vendor/node_modules/@legendapp/spark-ui/macos/text-input-search/RNTextInputSearch.mm +164 -0
- package/vendor/node_modules/@legendapp/spark-ui/package.json +16 -4
- package/vendor/node_modules/@legendapp/spark-ui/src/SparkSelectNativeComponent.ts +3 -1
- package/vendor/node_modules/@legendapp/spark-ui/src/SparkTextInputNativeComponent.ts +6 -2
- package/vendor/node_modules/@legendapp/spark-ui/src/appkit-split-view/SidebarSplitViewNativeComponent.ts +31 -0
- package/vendor/node_modules/@legendapp/spark-ui/src/appkit-split-view/index.tsx +77 -0
- package/vendor/node_modules/@legendapp/spark-ui/src/availability.ts +10 -0
- package/vendor/node_modules/@legendapp/spark-ui/src/classnames/index.ts +8 -0
- package/vendor/node_modules/@legendapp/spark-ui/src/control.ts +42 -0
- package/vendor/node_modules/@legendapp/spark-ui/src/desktop.tsx +56 -0
- package/vendor/node_modules/@legendapp/spark-ui/src/glass-effect-view/index.tsx +15 -0
- package/vendor/node_modules/@legendapp/spark-ui/src/index.android.tsx +35 -21
- package/vendor/node_modules/@legendapp/spark-ui/src/index.ios.tsx +55 -26
- package/vendor/node_modules/@legendapp/spark-ui/src/index.tsx +1 -27
- package/vendor/node_modules/@legendapp/spark-ui/src/index.web.tsx +45 -14
- package/vendor/node_modules/@legendapp/spark-ui/src/index.windows.tsx +1 -42
- package/vendor/node_modules/@legendapp/spark-ui/src/mobile-input.tsx +11 -0
- package/vendor/node_modules/@legendapp/spark-ui/src/native-select/NativeSegmentedControlNativeComponent.ts +17 -0
- package/vendor/node_modules/@legendapp/spark-ui/src/native-select/NativeSelectNativeComponent.ts +17 -0
- package/vendor/node_modules/@legendapp/spark-ui/src/select.ts +5 -3
- package/vendor/node_modules/@legendapp/spark-ui/src/sf-symbol/SFSymbolNativeComponent.ts +13 -0
- package/vendor/node_modules/@legendapp/spark-ui/src/sf-symbol/index.tsx +27 -0
- package/vendor/node_modules/@legendapp/spark-ui/src/sidebar/SidebarItemNativeComponent.ts +25 -0
- package/vendor/node_modules/@legendapp/spark-ui/src/sidebar/SidebarNativeComponent.ts +24 -0
- package/vendor/node_modules/@legendapp/spark-ui/src/sidebar/index.tsx +104 -0
- package/vendor/node_modules/@legendapp/spark-ui/src/specialized.ts +22 -0
- package/vendor/node_modules/@legendapp/spark-ui/src/text-input-search/TextInputSearchNativeComponent.ts +33 -0
- package/vendor/node_modules/@legendapp/spark-ui/src/text-input-search/index.tsx +34 -0
- package/vendor/node_modules/@legendapp/spark-ui/src/types.ts +30 -19
- package/vendor/node_modules/@legendapp/spark-ui/uniwind.ts +3 -1
- package/vendor/node_modules/@legendapp/spark-ui/uniwind.web.ts +3 -1
- package/vendor/node_modules/@legendapp/spark-ui/windows/SparkUI/SparkUI.h +16 -11
- package/vendor/node_modules/@legendapp/spark-updates/macos/RNDesktopUpdates.mm +21 -8
- package/vendor/node_modules/@legendapp/spark-updates/package.json +2 -2
- package/vendor/node_modules/@legendapp/spark-updates/src/NativeDesktopUpdates.ts +3 -2
- package/vendor/node_modules/@legendapp/spark-updates/src/index.ts +71 -15
- package/vendor/node_modules/@legendapp/spark-webview/package.json +2 -2
- package/vendor/node_modules/@legendapp/spark-webview/src/WebView.tsx +11 -0
- package/vendor/node_modules/@legendapp/spark-webview/src/adapter.ts +55 -0
- package/vendor/node_modules/@legendapp/spark-webview/src/index.ts +2 -2
- package/vendor/node_modules/@legendapp/spark-webview/src/types.ts +32 -0
- package/vendor/node_modules/@legendapp/spark-webview/src/view-props.ts +28 -0
- package/vendor/node_modules/@legendapp/spark-window-options/index.cjs +51 -14
- package/vendor/node_modules/@legendapp/spark-window-options/index.d.ts +21 -8
- package/vendor/node_modules/@legendapp/spark-window-options/package.json +1 -1
- package/windows-macos.ts +1 -0
- package/expo-metro.cjs +0 -1
- package/message-dialog.ts +0 -1
- package/universal.cjs +0 -1
- package/vendor/node_modules/@legendapp/spark-desktop-shortcuts/src/accelerator.ts +0 -22
- package/vendor/node_modules/@legendapp/spark-desktop-windows/src/windows-options.ts +0 -11
- package/vendor/node_modules/@legendapp/spark-file-dialog/src/index.windows.ts +0 -15
- package/vendor/node_modules/@legendapp/spark-global-shortcuts/src/accelerator.ts +0 -22
- package/vendor/node_modules/@legendapp/spark-ui/macos/RNSparkSelect.h +0 -4
- package/vendor/node_modules/@legendapp/spark-ui/macos/RNSparkSelect.mm +0 -53
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
|
-
import { closeSync, existsSync, mkdirSync, mkdtempSync, openSync, readFileSync, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { closeSync, existsSync, ftruncateSync, lstatSync, mkdirSync, mkdtempSync, openSync, readFileSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { spawn } from "node:child_process";
|
|
3
4
|
import { open } from "node:fs/promises";
|
|
4
5
|
import path from "node:path";
|
|
5
6
|
import { setTimeout as sleep } from "node:timers/promises";
|
|
@@ -9,6 +10,142 @@ import { architecture } from "./platform.js";
|
|
|
9
10
|
import { VERSION } from "./project.js";
|
|
10
11
|
import { installedRelease } from "./release.js";
|
|
11
12
|
const defaults = { fetch: globalThis.fetch, run };
|
|
13
|
+
function readLegacyPid(lock) {
|
|
14
|
+
try {
|
|
15
|
+
const content = readFileSync(lock, "utf8").trim();
|
|
16
|
+
if (/^\d+$/.test(content))
|
|
17
|
+
return Number(content);
|
|
18
|
+
}
|
|
19
|
+
catch (error) {
|
|
20
|
+
if (error.code !== "ENOENT")
|
|
21
|
+
throw error;
|
|
22
|
+
}
|
|
23
|
+
return undefined;
|
|
24
|
+
}
|
|
25
|
+
/** The kernel releases this advisory lock if the installer exits, including on a crash. */
|
|
26
|
+
export async function acquireRunnerLock(lock, waitMs = 600_000) {
|
|
27
|
+
const deadline = Date.now() + waitMs;
|
|
28
|
+
let child;
|
|
29
|
+
let exited;
|
|
30
|
+
while (true) {
|
|
31
|
+
if (Date.now() >= deadline)
|
|
32
|
+
throw new Error("Another process is installing Runner. Retry desktop launch when it finishes.");
|
|
33
|
+
const existingPid = readLegacyPid(lock);
|
|
34
|
+
if (existingPid) {
|
|
35
|
+
try {
|
|
36
|
+
process.kill(existingPid, 0);
|
|
37
|
+
if (Date.now() >= deadline)
|
|
38
|
+
throw new Error("Another process is installing Runner. Retry desktop launch when it finishes.");
|
|
39
|
+
await sleep(Math.min(1000, deadline - Date.now()));
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
if (error.code !== "ESRCH")
|
|
44
|
+
throw error;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
const existed = existsSync(lock);
|
|
48
|
+
const observed = existed ? lstatSync(lock) : undefined;
|
|
49
|
+
const remaining = Math.max(1, deadline - Date.now());
|
|
50
|
+
child = spawn("/usr/bin/lockf", ["-k", "-t", String(Math.max(1, Math.ceil(remaining / 1000))), lock, process.execPath, "-e", "process.stdout.write('locked\\n'); process.stdin.resume()"], { detached: true, stdio: ["pipe", "pipe", "pipe"] });
|
|
51
|
+
let stderr = "";
|
|
52
|
+
child.stderr.setEncoding("utf8").on("data", chunk => { stderr += chunk; });
|
|
53
|
+
exited = new Promise(resolve => child.once("close", (code, signal) => resolve({ code, signal })));
|
|
54
|
+
try {
|
|
55
|
+
await new Promise((resolve, reject) => {
|
|
56
|
+
let output = "";
|
|
57
|
+
child.stdout.setEncoding("utf8").on("data", chunk => {
|
|
58
|
+
output += chunk;
|
|
59
|
+
if (output.includes("locked\n"))
|
|
60
|
+
resolve();
|
|
61
|
+
});
|
|
62
|
+
child.once("error", reject);
|
|
63
|
+
void exited.then(({ code }) => reject(new Error(`Could not acquire Runner install lock${stderr ? `: ${stderr.trim()}` : ` (lockf exited ${code})`}`)));
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
try {
|
|
68
|
+
process.kill(-child.pid, "SIGTERM");
|
|
69
|
+
}
|
|
70
|
+
catch { }
|
|
71
|
+
await exited;
|
|
72
|
+
throw error;
|
|
73
|
+
}
|
|
74
|
+
const stopKeeper = async () => { child.stdin.end(); await exited; };
|
|
75
|
+
let fd;
|
|
76
|
+
try {
|
|
77
|
+
const acquired = lstatSync(lock);
|
|
78
|
+
if (observed && (acquired.dev !== observed.dev || acquired.ino !== observed.ino)) {
|
|
79
|
+
await stopKeeper();
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
const content = readFileSync(lock, "utf8").trim();
|
|
83
|
+
const legacyPid = readLegacyPid(lock);
|
|
84
|
+
if (legacyPid) {
|
|
85
|
+
let legacyLive = false;
|
|
86
|
+
try {
|
|
87
|
+
process.kill(legacyPid, 0);
|
|
88
|
+
legacyLive = true;
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
if (error.code !== "ESRCH")
|
|
92
|
+
throw error;
|
|
93
|
+
}
|
|
94
|
+
if (legacyLive) {
|
|
95
|
+
await stopKeeper();
|
|
96
|
+
if (Date.now() >= deadline)
|
|
97
|
+
throw new Error("Another process is installing Runner. Retry desktop launch when it finishes.");
|
|
98
|
+
await sleep(Math.min(1000, deadline - Date.now()));
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
else if (!content && existed) {
|
|
103
|
+
const age = Date.now() - statSync(lock).mtimeMs;
|
|
104
|
+
if (age < 30_000) {
|
|
105
|
+
await stopKeeper();
|
|
106
|
+
if (Date.now() >= deadline)
|
|
107
|
+
throw new Error("Another process is installing Runner. Retry desktop launch when it finishes.");
|
|
108
|
+
await sleep(Math.min(1000, deadline - Date.now()));
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
fd = openSync(lock, "r+");
|
|
113
|
+
ftruncateSync(fd, 0);
|
|
114
|
+
writeFileSync(fd, `v2:${process.pid}`);
|
|
115
|
+
closeSync(fd);
|
|
116
|
+
fd = undefined;
|
|
117
|
+
break;
|
|
118
|
+
}
|
|
119
|
+
catch (error) {
|
|
120
|
+
if (fd !== undefined) {
|
|
121
|
+
try {
|
|
122
|
+
closeSync(fd);
|
|
123
|
+
}
|
|
124
|
+
catch { }
|
|
125
|
+
}
|
|
126
|
+
await stopKeeper();
|
|
127
|
+
throw error;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
let released = false;
|
|
131
|
+
let releasePromise;
|
|
132
|
+
let unexpectedExit;
|
|
133
|
+
void exited.then(result => { if (!released)
|
|
134
|
+
unexpectedExit = result; });
|
|
135
|
+
const release = () => releasePromise ??= (async () => {
|
|
136
|
+
released = true;
|
|
137
|
+
child.stdin.end();
|
|
138
|
+
const result = await exited;
|
|
139
|
+
if (result.code !== 0)
|
|
140
|
+
throw new Error(`Runner install lock process exited unexpectedly (${result.signal ?? result.code}).`);
|
|
141
|
+
})();
|
|
142
|
+
return Object.assign(release, {
|
|
143
|
+
assertAlive() {
|
|
144
|
+
if (unexpectedExit)
|
|
145
|
+
throw new Error(`Runner install lock process exited unexpectedly (${unexpectedExit.signal ?? unexpectedExit.code}).`);
|
|
146
|
+
},
|
|
147
|
+
});
|
|
148
|
+
}
|
|
12
149
|
export async function downloadAsset(asset, file, request = globalThis.fetch) {
|
|
13
150
|
for (let attempt = 0; attempt < 3; attempt++) {
|
|
14
151
|
let handle;
|
|
@@ -50,7 +187,7 @@ export async function downloadAsset(asset, file, request = globalThis.fetch) {
|
|
|
50
187
|
}
|
|
51
188
|
async function verify(app, asset, deps) {
|
|
52
189
|
const runtime = readRuntime(app);
|
|
53
|
-
if (!runtime || runtime.mode !== "go" || runtime.platform !== "macos" || runtime.arch !== "
|
|
190
|
+
if (!runtime || runtime.mode !== "go" || runtime.platform !== "macos" || runtime.arch !== architecture("macos") || runtime.fingerprint !== asset.fingerprint)
|
|
54
191
|
throw new Error("Downloaded Runner has incompatible runtime metadata");
|
|
55
192
|
await deps.run(path.dirname(app), ["codesign", "--verify", "--deep", "--strict", app], { capture: true });
|
|
56
193
|
const signature = await deps.run(path.dirname(app), ["codesign", "-dvvv", app], { capture: true });
|
|
@@ -65,32 +202,7 @@ export async function installRunner(asset, cache = sparkHome(), deps = defaults)
|
|
|
65
202
|
const app = path.join(destination, asset.app);
|
|
66
203
|
mkdirSync(parent, { recursive: true });
|
|
67
204
|
const lock = `${destination}.lock`;
|
|
68
|
-
|
|
69
|
-
for (let attempt = 0; !owned && attempt < 600; attempt++) {
|
|
70
|
-
try {
|
|
71
|
-
const fd = openSync(lock, "wx");
|
|
72
|
-
writeFileSync(fd, String(process.pid));
|
|
73
|
-
closeSync(fd);
|
|
74
|
-
owned = true;
|
|
75
|
-
}
|
|
76
|
-
catch (error) {
|
|
77
|
-
if (error.code !== "EEXIST")
|
|
78
|
-
throw error;
|
|
79
|
-
const pid = Number(readFileSync(lock, "utf8"));
|
|
80
|
-
if (Number.isInteger(pid) && pid > 0) {
|
|
81
|
-
try {
|
|
82
|
-
process.kill(pid, 0);
|
|
83
|
-
}
|
|
84
|
-
catch (probe) {
|
|
85
|
-
if (probe.code === "ESRCH")
|
|
86
|
-
rmSync(lock, { force: true });
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
await sleep(1000);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
if (!owned)
|
|
93
|
-
throw new Error("Another process is installing Runner. Retry desktop launch when it finishes.");
|
|
205
|
+
const releaseLock = await acquireRunnerLock(lock);
|
|
94
206
|
let staging;
|
|
95
207
|
try {
|
|
96
208
|
if (existsSync(app)) {
|
|
@@ -110,8 +222,10 @@ export async function installRunner(asset, cache = sparkHome(), deps = defaults)
|
|
|
110
222
|
// Only publisher-pinned bytes reach the platform extractor.
|
|
111
223
|
await deps.run(staging, ["ditto", "-x", "-k", archive, unpacked], { capture: true });
|
|
112
224
|
await verify(path.join(unpacked, asset.app), asset, deps);
|
|
225
|
+
releaseLock.assertAlive();
|
|
113
226
|
renameSync(unpacked, destination);
|
|
114
227
|
}
|
|
228
|
+
releaseLock.assertAlive();
|
|
115
229
|
registerRuntime(app);
|
|
116
230
|
console.log("Spark Runner installed and verified.");
|
|
117
231
|
return app;
|
|
@@ -119,7 +233,7 @@ export async function installRunner(asset, cache = sparkHome(), deps = defaults)
|
|
|
119
233
|
finally {
|
|
120
234
|
if (staging)
|
|
121
235
|
rmSync(staging, { recursive: true, force: true });
|
|
122
|
-
|
|
236
|
+
await releaseLock();
|
|
123
237
|
}
|
|
124
238
|
}
|
|
125
239
|
export async function acquireRunner(platform) {
|
|
@@ -130,8 +244,8 @@ export async function acquireRunner(platform) {
|
|
|
130
244
|
const asset = release.runners[target];
|
|
131
245
|
if (!asset)
|
|
132
246
|
throw new Error(`This Spark release has no Runner for ${target}. Use a custom development build.`);
|
|
133
|
-
if (process.platform !== "darwin"
|
|
134
|
-
throw new Error("This release's Runner requires
|
|
247
|
+
if (process.platform !== "darwin")
|
|
248
|
+
throw new Error("This release's macOS Runner requires macOS.");
|
|
135
249
|
app = await installRunner(asset);
|
|
136
250
|
}
|
|
137
251
|
return app;
|
|
@@ -134,7 +134,7 @@ export async function validateApp(root, app, credentials, expected, notarized, e
|
|
|
134
134
|
app = realpathSync(app);
|
|
135
135
|
if (expected.runner) {
|
|
136
136
|
const runtime = readJson(path.join(app, "Contents/Resources/spark-runtime.json"));
|
|
137
|
-
if (runtime.mode !== "go" || runtime.platform !== "macos" || runtime.arch !==
|
|
137
|
+
if (runtime.mode !== "go" || runtime.platform !== "macos" || runtime.arch !== expected.arch)
|
|
138
138
|
throw new Error("Distribution app is not a macOS Spark Runner.");
|
|
139
139
|
}
|
|
140
140
|
else if (!existsSync(path.join(app, "Contents/Resources/main.jsbundle")))
|
|
@@ -145,8 +145,9 @@ export async function validateApp(root, app, credentials, expected, notarized, e
|
|
|
145
145
|
throw new Error(`Packaged ${key} does not match the release build.`);
|
|
146
146
|
}
|
|
147
147
|
const arches = (await execute(root, ["lipo", "-archs", path.join(app, "Contents/MacOS", info.CFBundleExecutable)], { capture: true })).trim().split(/\s+/);
|
|
148
|
-
|
|
149
|
-
|
|
148
|
+
const expectedArch = expected.arch === "x64" ? "x86_64" : "arm64";
|
|
149
|
+
if (arches.length !== 1 || arches[0] !== expectedArch)
|
|
150
|
+
throw new Error(`The package must contain a ${expectedArch} app.`);
|
|
150
151
|
await execute(root, ["codesign", "--verify", "--deep", "--strict", "--verbose=2", app], { capture: true });
|
|
151
152
|
const order = signingOrder(app);
|
|
152
153
|
const targets = await entitlementTargets(root, app, order, expected.entitlements, expected.byPath, execute);
|
|
@@ -60,19 +60,56 @@ export function verifyUpdateSignature(archive, signature, publicKey) {
|
|
|
60
60
|
if (!/^[A-Za-z0-9+/]{86}==$/.test(signature) || !verify(null, readFileSync(archive), key, Buffer.from(signature, "base64")))
|
|
61
61
|
throw new Error("Update signature does not match the app's public key or archive");
|
|
62
62
|
}
|
|
63
|
+
const buildNumberPattern = /^[0-9]+(?:\.[0-9]+){0,2}$/;
|
|
64
|
+
function buildNumberParts(version) { return version.split(".").map(part => part.replace(/^0+(?=\d)/, "")); }
|
|
65
|
+
function canonicalBuildNumber(version) { return buildNumberParts(version).concat(["0", "0"]).slice(0, 3).join("."); }
|
|
66
|
+
function compareBuildNumbers(left, right) {
|
|
67
|
+
const a = buildNumberParts(left), b = buildNumberParts(right);
|
|
68
|
+
for (let index = 0; index < 3; index++) {
|
|
69
|
+
const x = a[index] ?? "0", y = b[index] ?? "0";
|
|
70
|
+
if (x.length !== y.length)
|
|
71
|
+
return x.length < y.length ? -1 : 1;
|
|
72
|
+
if (x !== y)
|
|
73
|
+
return x < y ? -1 : 1;
|
|
74
|
+
}
|
|
75
|
+
return 0;
|
|
76
|
+
}
|
|
77
|
+
export function validateUpdateBuildVersion(buildVersion, records, archiveHash) {
|
|
78
|
+
if (!buildNumberPattern.test(buildVersion))
|
|
79
|
+
throw new Error("Updates require a numeric macOS buildNumber, increasing for every release");
|
|
80
|
+
const seen = new Map();
|
|
81
|
+
for (const version of Object.keys(records)) {
|
|
82
|
+
if (!buildNumberPattern.test(version))
|
|
83
|
+
throw new Error(`Invalid build number in Spark update history: ${version}`);
|
|
84
|
+
const canonical = canonicalBuildNumber(version);
|
|
85
|
+
const equivalent = seen.get(canonical);
|
|
86
|
+
if (equivalent && equivalent !== version)
|
|
87
|
+
throw new Error(`Spark update history reuses the numeric build number as both ${equivalent} and ${version}.`);
|
|
88
|
+
seen.set(canonical, version);
|
|
89
|
+
if (compareBuildNumbers(version, buildVersion) === 0 && version !== buildVersion)
|
|
90
|
+
throw new Error(`Build ${buildVersion} aliases the recorded build number ${version}; use a new increasing macos.buildNumber spelling.`);
|
|
91
|
+
}
|
|
92
|
+
const existing = records[buildVersion];
|
|
93
|
+
if (existing) {
|
|
94
|
+
if (existing.sha256 !== archiveHash)
|
|
95
|
+
throw new Error(`Build ${buildVersion} was already packaged with different bytes. Increase macos.buildNumber before publishing another update.`);
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
for (const version of Object.keys(records)) {
|
|
99
|
+
if (compareBuildNumbers(buildVersion, version) <= 0)
|
|
100
|
+
throw new Error(`Build ${buildVersion} must be greater than every published build number. Increase macos.buildNumber before publishing another update.`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
63
103
|
export async function prepareUpdate(root, archive, buildVersion, dependencies = { run, tools: sparkleTools }) {
|
|
64
104
|
const expo = readAppConfig(root).expo;
|
|
65
105
|
const updates = updateConfiguration(expo);
|
|
66
106
|
if (!updates)
|
|
67
107
|
return undefined;
|
|
68
|
-
if (!/^[0-9]+(?:\.[0-9]+){0,2}$/.test(buildVersion))
|
|
69
|
-
throw new Error("Updates require a numeric macOS buildNumber, increasing for every release");
|
|
70
108
|
const directory = path.join(root, "dist/updates");
|
|
71
109
|
const recordsFile = path.join(directory, "releases.json");
|
|
72
110
|
const records = existsSync(recordsFile) ? readJson(recordsFile) : {};
|
|
73
111
|
const hash = createHash("sha256").update(readFileSync(archive)).digest("hex");
|
|
74
|
-
|
|
75
|
-
throw new Error(`Build ${buildVersion} was already packaged with different bytes. Increase macos.buildNumber before publishing another update.`);
|
|
112
|
+
validateUpdateBuildVersion(buildVersion, records, hash);
|
|
76
113
|
const bin = await dependencies.tools(root, dependencies.run);
|
|
77
114
|
const keyArgs = dependencies.keyFile ? ["--ed-key-file", dependencies.keyFile] : ["--account", account(expo)];
|
|
78
115
|
const signature = (await dependencies.run(root, [path.join(bin, "sign_update"), ...keyArgs, "-p", archive], { capture: true })).trim();
|
|
@@ -8,6 +8,7 @@ import path from "node:path";
|
|
|
8
8
|
import { createRequire } from "node:module";
|
|
9
9
|
import { run } from "./commands.js";
|
|
10
10
|
import { prepareConfig, nativePackages, runtimeFor, stateFile, readJson, writeJson, validateBuildModules, goConfigurationIssues, readAppConfig } from "./project.js";
|
|
11
|
+
import { assertNativePatchPreflight } from "./native-patch-preflight.js";
|
|
11
12
|
// Windows .cmd shims are shell programs; run the package's actual JS entry.
|
|
12
13
|
export function nodeCommand(root, name, bin, args = []) {
|
|
13
14
|
const req = createRequire(path.join(root, "package.json"));
|
|
@@ -54,6 +55,7 @@ export async function preserveWindowsBuildOutputs(root, prepare) {
|
|
|
54
55
|
}
|
|
55
56
|
}
|
|
56
57
|
export async function prepareWindows(root, mode) {
|
|
58
|
+
assertNativePatchPreflight(root);
|
|
57
59
|
await checkExpoDesktopNode(root);
|
|
58
60
|
prepareConfig(root);
|
|
59
61
|
prepareWindowsGeometry(root);
|
|
@@ -70,7 +72,7 @@ export async function prepareWindows(root, mode) {
|
|
|
70
72
|
const manifest = readFileSync(path.join(root, "package.json"), "utf8");
|
|
71
73
|
try {
|
|
72
74
|
await preserveWindowsBuildOutputs(root, async () => {
|
|
73
|
-
await run(root, nodeCommand(root, "expo-desktop", "expo-desktop", ["prebuild", "--platform", "windows", "--template", "expo-desktop-template-bare-minimum@54.81.1
|
|
75
|
+
await run(root, nodeCommand(root, "expo-desktop", "expo-desktop", ["prebuild", "--platform", "windows", "--template", "expo-desktop-template-bare-minimum@54.81.1", "--no-install"]), { env: { CI: "1" }, capture: true });
|
|
74
76
|
});
|
|
75
77
|
// The beta template expands all-platform dependencies. Keep the consumer's installed graph.
|
|
76
78
|
}
|
|
@@ -82,6 +84,7 @@ export async function prepareWindows(root, mode) {
|
|
|
82
84
|
export async function buildWindows(root, mode, force) {
|
|
83
85
|
if (mode !== "go" && mode !== "dev")
|
|
84
86
|
throw new Error("Windows currently supports Spark Runner runtimes and development builds. Use spark build --dev; production builds and packaging are not implemented.");
|
|
87
|
+
assertNativePatchPreflight(root);
|
|
85
88
|
if (process.platform !== "win32")
|
|
86
89
|
throw new Error("Windows native builds require Windows x64 or ARM64. Project generation and Metro bundle checks can run on macOS.");
|
|
87
90
|
for (const tool of ["node", "pwsh.exe", "dotnet.exe"])
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@legendapp/spark-cli",
|
|
3
|
-
"version": "0.0.1-next.
|
|
3
|
+
"version": "0.0.1-next.3",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
@@ -11,12 +11,13 @@
|
|
|
11
11
|
"node": ">=24.19.0"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"@legendapp/spark-desktop-config": "0.0.1-next.
|
|
15
|
-
"ws": "8.
|
|
16
|
-
"expo-desktop": "1.0.0
|
|
17
|
-
"npm": "11.
|
|
14
|
+
"@legendapp/spark-desktop-config": "0.0.1-next.3",
|
|
15
|
+
"ws": "8.21.0",
|
|
16
|
+
"expo-desktop": "1.0.0",
|
|
17
|
+
"npm": "11.21.0",
|
|
18
18
|
"typescript": "5.9.3",
|
|
19
|
-
"cross-spawn": "7.0.6"
|
|
19
|
+
"cross-spawn": "7.0.6",
|
|
20
|
+
"@legendapp/spark-window-options": "0.0.1-next.3"
|
|
20
21
|
},
|
|
21
22
|
"private": true
|
|
22
23
|
}
|
|
@@ -1,22 +1,16 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, { useState } from "react";
|
|
2
2
|
import { Button, StyleSheet, Text, View } from "react-native";
|
|
3
3
|
import { openFileDialog } from "@legendapp/spark/dialogs";
|
|
4
|
-
import {
|
|
4
|
+
import { useMenu, type MenuRootItem } from "@legendapp/spark/menus";
|
|
5
5
|
|
|
6
|
-
const menus = [{ id: "hello",
|
|
6
|
+
const menus: MenuRootItem[] = [{ type: "submenu", id: "hello", label: "Hello", items: [{ type: "action", id: "greet", label: "Say Hello" }] }];
|
|
7
7
|
export default function App({ runtime }: { runtime?: { mode: string } }) {
|
|
8
8
|
const [message, setMessage] = useState("Ready");
|
|
9
|
-
|
|
10
|
-
configureMenus("hello-world", menus);
|
|
11
|
-
const subscription = addNativeMenuActionListener(action => {
|
|
12
|
-
if (action.ownerId === "hello-world" && action.itemId === "greet") setMessage("Hello from the native menu");
|
|
13
|
-
});
|
|
14
|
-
return () => { subscription.remove(); clearMenus("hello-world"); };
|
|
15
|
-
}, []);
|
|
9
|
+
useMenu({ id: "hello-world", items: menus, onAction: action => { if (action.itemId === "greet") setMessage("Hello from the native menu"); }, onError: error => setMessage(String(error)) });
|
|
16
10
|
async function chooseFile() {
|
|
17
11
|
try {
|
|
18
|
-
const files = await openFileDialog({ title: "Choose a file",
|
|
19
|
-
setMessage(files
|
|
12
|
+
const files = await openFileDialog({ title: "Choose a file", multiple: false });
|
|
13
|
+
setMessage(files.canceled ? "Dialog cancelled" : files.paths.join(", "));
|
|
20
14
|
} catch (error) { setMessage(String(error)); }
|
|
21
15
|
}
|
|
22
16
|
return <View style={styles.root}>
|
package/vendor/node_modules/@legendapp/spark-cli/templates/blank-typescript/desktop.config.json
CHANGED
|
@@ -3,9 +3,11 @@
|
|
|
3
3
|
"name": "HelloWorld",
|
|
4
4
|
"version": "0.0.1",
|
|
5
5
|
"window": {
|
|
6
|
-
"
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
"size": {
|
|
7
|
+
"width": 1000,
|
|
8
|
+
"height": 700
|
|
9
|
+
},
|
|
10
|
+
"restoreBounds": true
|
|
9
11
|
},
|
|
10
12
|
"macos": {
|
|
11
13
|
"bundleIdentifier": "so.legend.spark.prototype.helloworld"
|
|
@@ -13,13 +13,13 @@
|
|
|
13
13
|
"postinstall": "node node_modules/@legendapp/spark/init-template.cjs"
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@legendapp/spark": "0.0.1-next.
|
|
16
|
+
"@legendapp/spark": "0.0.1-next.3",
|
|
17
17
|
"expo": "54.0.37",
|
|
18
|
-
"expo-desktop": "1.0.0
|
|
19
|
-
"expo-desktop-prebuild-config": "1.1.0
|
|
20
|
-
"expo-desktop-config-plugins": "1.2.0
|
|
21
|
-
"expo-desktop-metro-config": "54.81.0
|
|
22
|
-
"expo-desktop-template-bare-minimum": "54.81.1
|
|
18
|
+
"expo-desktop": "1.0.0",
|
|
19
|
+
"expo-desktop-prebuild-config": "1.1.0",
|
|
20
|
+
"expo-desktop-config-plugins": "1.2.0",
|
|
21
|
+
"expo-desktop-metro-config": "54.81.0",
|
|
22
|
+
"expo-desktop-template-bare-minimum": "54.81.1",
|
|
23
23
|
"react": "19.1.4",
|
|
24
24
|
"react-native": "0.81.6",
|
|
25
25
|
"react-native-macos": "0.81.7",
|
|
@@ -39,10 +39,12 @@
|
|
|
39
39
|
"expo-font": "14.0.12",
|
|
40
40
|
"expo-keep-awake": "15.0.8",
|
|
41
41
|
"expo-modules-core": "3.0.30",
|
|
42
|
-
"expo-desktop-modules-core": "54.0.14
|
|
43
|
-
"expo-desktop-stubs": "54.0.14
|
|
42
|
+
"expo-desktop-modules-core": "54.0.14",
|
|
43
|
+
"expo-desktop-stubs": "54.0.14",
|
|
44
44
|
"react": "19.1.4",
|
|
45
|
-
"react-native": "0.81.6"
|
|
45
|
+
"react-native": "0.81.6",
|
|
46
|
+
"react-native-macos": "0.81.7",
|
|
47
|
+
"react-native-windows": "0.81.35"
|
|
46
48
|
},
|
|
47
49
|
"expo": {
|
|
48
50
|
"install": {
|
|
@@ -5,8 +5,8 @@ import { runCommand } from "@legendapp/spark/processes";
|
|
|
5
5
|
export function Git({ onResult, onError }: { onResult(text: string): void; onError(message: string): void }) {
|
|
6
6
|
const [busy, setBusy] = useState(false);
|
|
7
7
|
return <Button disabled={busy} onPress={() => { setBusy(true); void (async () => {
|
|
8
|
-
const paths = await openFileDialog({
|
|
9
|
-
const result = await runCommand({ executable: "/usr/bin/git", args: ["--no-pager", "diff", "--no-ext-diff", "--no-textconv", "--", "."], cwd: paths[0], timeoutMs: 10_000 });
|
|
8
|
+
const paths = await openFileDialog({ selection: "directories" }); if (paths.canceled) return;
|
|
9
|
+
const result = await runCommand({ executable: "/usr/bin/git", args: ["--no-pager", "diff", "--no-ext-diff", "--no-textconv", "--", "."], cwd: paths.paths[0], timeoutMs: 10_000 });
|
|
10
10
|
if (result.timedOut || result.outputTruncated || result.exitCode !== 0) throw new Error(result.stderr || "Git comparison failed or exceeded its output limit");
|
|
11
11
|
onResult(result.stdout || "No unstaged changes.");
|
|
12
12
|
})().catch(error => onError(String(error))).finally(() => setBusy(false)); }}>{busy ? "Reading Git…" : "Open Git changes"}</Button>;
|
package/vendor/node_modules/@legendapp/spark-cli/templates/document-editor/Integration.macos.tsx
CHANGED
|
@@ -1,17 +1,30 @@
|
|
|
1
1
|
import { useEffect, useState } from "react";
|
|
2
2
|
import { Text } from "react-native";
|
|
3
3
|
import { Button } from "@legendapp/spark/ui";
|
|
4
|
-
import { beforeWindowClose, openWindow,
|
|
4
|
+
import { beforeWindowClose, openWindow, setWindowOptions, addWindowListener } from "@legendapp/spark/windows";
|
|
5
5
|
import { beforeQuit } from "@legendapp/spark/app";
|
|
6
|
-
import {
|
|
6
|
+
import { useMenu, type MenuItem } from "@legendapp/spark/menus";
|
|
7
7
|
import { registerShortcut } from "@legendapp/spark/shortcuts";
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
8
|
+
import { subscribeToOpenRequests } from "@legendapp/spark/app/documents";
|
|
9
|
+
import { readText } from "@legendapp/spark/files";
|
|
10
10
|
import { sessions } from "./sessions";
|
|
11
11
|
import type { DocumentSession } from "./document";
|
|
12
|
+
const items: MenuItem[] = [{ type: "submenu", id: "file", target: { menu: "file" }, label: "File", items: [
|
|
13
|
+
{ type: "action", id: "new", label: "New" }, { type: "action", id: "open", label: "Open…" }, { type: "action", id: "save", label: "Save" }, { type: "action", id: "saveAs", label: "Save As…" },
|
|
14
|
+
] }];
|
|
12
15
|
let nextWindow = 0;
|
|
13
16
|
export function Integration({ session, windowId, documentId, onReady }: { session: DocumentSession; windowId: string; documentId: string; onReady: (ready: boolean) => void }) {
|
|
14
17
|
const [error, setError] = useState<string | null>(null);
|
|
18
|
+
const menu = useMenu({ id: `editor-${windowId}`, items, onAction: event => {
|
|
19
|
+
const actions: Record<string, () => unknown> = { new: () => session.newDocument(), open: () => session.open(), save: () => session.save(), saveAs: () => session.save(true) };
|
|
20
|
+
actions[event.itemId]?.();
|
|
21
|
+
}, onError: error => setError(String(error)) });
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
if (menu.status !== "ready") return;
|
|
24
|
+
let disposed = false, focus: Awaited<ReturnType<typeof addWindowListener>> | undefined;
|
|
25
|
+
void addWindowListener(windowId, "focusChanged", event => { if (event.focused) void menu.menu.update({ items }).catch(error => setError(String(error))); }).then(value => { if (disposed) void value.remove(); else focus = value; }).catch(error => setError(String(error)));
|
|
26
|
+
return () => { disposed = true; void focus?.remove(); };
|
|
27
|
+
}, [menu, windowId]);
|
|
15
28
|
useEffect(() => {
|
|
16
29
|
let removed = false;
|
|
17
30
|
const cleanups: (() => void | Promise<void>)[] = [];
|
|
@@ -19,17 +32,8 @@ export function Integration({ session, windowId, documentId, onReady }: { sessio
|
|
|
19
32
|
const subscription = await registration;
|
|
20
33
|
if (removed) await subscription.remove(); else cleanups.push(() => subscription.remove());
|
|
21
34
|
};
|
|
22
|
-
const owner = `editor-${windowId}`;
|
|
23
35
|
const actions: Record<string, () => unknown> = { new: () => session.newDocument(), open: () => session.open(), save: () => session.save(), saveAs: () => session.save(true) };
|
|
24
|
-
const
|
|
25
|
-
{ id: "new", title: "New" }, { id: "open", title: "Open…" }, { id: "save", title: "Save" }, { id: "saveAs", title: "Save As…" },
|
|
26
|
-
] }]);
|
|
27
|
-
menus(); cleanups.push(() => clearMenus(owner));
|
|
28
|
-
const menu = addNativeMenuActionListener(event => { if (event.ownerId === owner) actions[event.itemId]?.(); });
|
|
29
|
-
cleanups.push(() => menu.remove());
|
|
30
|
-
const focus = onWindowEvent(event => { if (event.type === "focus" && event.windowId === windowId) menus(); });
|
|
31
|
-
cleanups.push(() => focus.remove());
|
|
32
|
-
const title = () => { const state = session.getSnapshot(); void setWindowTitle(windowId, `${state.file.name}${session.dirty ? " •" : ""}`).catch(e => setError(String(e))); };
|
|
36
|
+
const title = () => { const state = session.getSnapshot(); void setWindowOptions(windowId, { title: `${state.file.name}${session.dirty ? " •" : ""}` }).catch(e => setError(String(e))); };
|
|
33
37
|
title(); cleanups.push(session.subscribe(title));
|
|
34
38
|
void (async () => {
|
|
35
39
|
await retain(beforeWindowClose(windowId, session.canClose));
|
|
@@ -38,12 +42,10 @@ export function Integration({ session, windowId, documentId, onReady }: { sessio
|
|
|
38
42
|
}
|
|
39
43
|
if (windowId === "main") {
|
|
40
44
|
await retain(beforeQuit(async () => { for (const document of sessions.values()) if (!await document.canClose()) return false; return true; }));
|
|
41
|
-
await retain(
|
|
42
|
-
if (event.type !== "
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
const location = decodeURIComponent(match[1]!);
|
|
46
|
-
void readTextFile(location).then(text => session.load({ location, name: location.split("/").pop()! }, text)).catch(e => setError(String(e)));
|
|
45
|
+
await retain(subscribeToOpenRequests(event => {
|
|
46
|
+
if (event.type !== "file") return;
|
|
47
|
+
const location = event.path;
|
|
48
|
+
void readText(location).then(text => session.load({ location, name: location.split("/").pop()! }, text)).catch(e => setError(String(e)));
|
|
47
49
|
}));
|
|
48
50
|
}
|
|
49
51
|
if (!removed) onReady(true);
|
|
@@ -51,7 +53,7 @@ export function Integration({ session, windowId, documentId, onReady }: { sessio
|
|
|
51
53
|
return () => { removed = true; for (const cleanup of cleanups.reverse()) void Promise.resolve().then(cleanup).catch(console.error); };
|
|
52
54
|
}, [session, windowId, onReady]);
|
|
53
55
|
return <>
|
|
54
|
-
<Button onPress={() => {
|
|
56
|
+
<Button onPress={() => { const id = `document-${++nextWindow}`; void openWindow({ id, title: session.getSnapshot().file.name, component: "main", size: { width: 800, height: 600 }, props: { windowId: id, windowProps: { documentId } } }).catch(e => setError(String(e))); }}>Open another view</Button>
|
|
55
57
|
{error ? <Text accessibilityRole="alert">{error}</Text> : null}
|
|
56
58
|
</>;
|
|
57
59
|
}
|
package/vendor/node_modules/@legendapp/spark-cli/templates/document-editor/Integration.windows.tsx
CHANGED
|
@@ -1,17 +1,30 @@
|
|
|
1
1
|
import { useEffect, useState } from "react";
|
|
2
2
|
import { Text } from "react-native";
|
|
3
3
|
import { Button } from "@legendapp/spark/ui";
|
|
4
|
-
import { beforeWindowClose, openWindow,
|
|
4
|
+
import { beforeWindowClose, openWindow, setWindowOptions, addWindowListener } from "@legendapp/spark/windows";
|
|
5
5
|
import { beforeQuit } from "@legendapp/spark/app";
|
|
6
|
-
import {
|
|
6
|
+
import { useMenu, type MenuItem } from "@legendapp/spark/menus";
|
|
7
7
|
import { registerShortcut } from "@legendapp/spark/shortcuts";
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
8
|
+
import { subscribeToOpenRequests } from "@legendapp/spark/app/documents";
|
|
9
|
+
import { readText } from "@legendapp/spark/files";
|
|
10
10
|
import { sessions } from "./sessions";
|
|
11
11
|
import type { DocumentSession } from "./document";
|
|
12
|
+
const items: MenuItem[] = [{ type: "submenu", id: "file", target: { menu: "file" }, label: "File", items: [
|
|
13
|
+
{ type: "action", id: "new", label: "New" }, { type: "action", id: "open", label: "Open…" }, { type: "action", id: "save", label: "Save" }, { type: "action", id: "saveAs", label: "Save As…" },
|
|
14
|
+
] }];
|
|
12
15
|
let nextWindow = 0;
|
|
13
16
|
export function Integration({ session, windowId, documentId, onReady }: { session: DocumentSession; windowId: string; documentId: string; onReady: (ready: boolean) => void }) {
|
|
14
17
|
const [error, setError] = useState<string | null>(null);
|
|
18
|
+
const menu = useMenu({ id: `editor-${windowId}`, items, onAction: event => {
|
|
19
|
+
const actions: Record<string, () => unknown> = { new: () => session.newDocument(), open: () => session.open(), save: () => session.save(), saveAs: () => session.save(true) };
|
|
20
|
+
actions[event.itemId]?.();
|
|
21
|
+
}, onError: error => setError(String(error)) });
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
if (menu.status !== "ready") return;
|
|
24
|
+
let disposed = false, focus: Awaited<ReturnType<typeof addWindowListener>> | undefined;
|
|
25
|
+
void addWindowListener(windowId, "focusChanged", event => { if (event.focused) void menu.menu.update({ items }).catch(error => setError(String(error))); }).then(value => { if (disposed) void value.remove(); else focus = value; }).catch(error => setError(String(error)));
|
|
26
|
+
return () => { disposed = true; void focus?.remove(); };
|
|
27
|
+
}, [menu, windowId]);
|
|
15
28
|
useEffect(() => {
|
|
16
29
|
let removed = false;
|
|
17
30
|
const cleanups: (() => void | Promise<void>)[] = [];
|
|
@@ -19,17 +32,8 @@ export function Integration({ session, windowId, documentId, onReady }: { sessio
|
|
|
19
32
|
const subscription = await registration;
|
|
20
33
|
if (removed) await subscription.remove(); else cleanups.push(() => subscription.remove());
|
|
21
34
|
};
|
|
22
|
-
const owner = `editor-${windowId}`;
|
|
23
35
|
const actions: Record<string, () => unknown> = { new: () => session.newDocument(), open: () => session.open(), save: () => session.save(), saveAs: () => session.save(true) };
|
|
24
|
-
const
|
|
25
|
-
{ id: "new", title: "New" }, { id: "open", title: "Open…" }, { id: "save", title: "Save" }, { id: "saveAs", title: "Save As…" },
|
|
26
|
-
] }]);
|
|
27
|
-
menus(); cleanups.push(() => clearMenus(owner));
|
|
28
|
-
const menu = addNativeMenuActionListener(event => { if (event.ownerId === owner) actions[event.itemId]?.(); });
|
|
29
|
-
cleanups.push(() => menu.remove());
|
|
30
|
-
const focus = onWindowEvent(event => { if (event.type === "focus" && event.windowId === windowId) menus(); });
|
|
31
|
-
cleanups.push(() => focus.remove());
|
|
32
|
-
const title = () => { const state = session.getSnapshot(); void setWindowTitle(windowId, `${state.file.name}${session.dirty ? " •" : ""}`).catch(e => setError(String(e))); };
|
|
36
|
+
const title = () => { const state = session.getSnapshot(); void setWindowOptions(windowId, { title: `${state.file.name}${session.dirty ? " •" : ""}` }).catch(e => setError(String(e))); };
|
|
33
37
|
title(); cleanups.push(session.subscribe(title));
|
|
34
38
|
void (async () => {
|
|
35
39
|
await retain(beforeWindowClose(windowId, session.canClose));
|
|
@@ -38,12 +42,10 @@ export function Integration({ session, windowId, documentId, onReady }: { sessio
|
|
|
38
42
|
}
|
|
39
43
|
if (windowId === "main") {
|
|
40
44
|
await retain(beforeQuit(async () => { for (const document of sessions.values()) if (!await document.canClose()) return false; return true; }));
|
|
41
|
-
await retain(
|
|
42
|
-
if (event.type !== "
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
const location = decodeURIComponent(match[1]!).replace(/^\/([A-Za-z]:)/, "$1").replace(/\//g, "\\");
|
|
46
|
-
void readTextFile(location).then(text => session.load({ location, name: location.split("/").pop()! }, text)).catch(e => setError(String(e)));
|
|
45
|
+
await retain(subscribeToOpenRequests(event => {
|
|
46
|
+
if (event.type !== "file") return;
|
|
47
|
+
const location = event.path;
|
|
48
|
+
void readText(location).then(text => session.load({ location, name: location.split("/").pop()! }, text)).catch(e => setError(String(e)));
|
|
47
49
|
}));
|
|
48
50
|
}
|
|
49
51
|
if (!removed) onReady(true);
|
|
@@ -51,7 +53,7 @@ export function Integration({ session, windowId, documentId, onReady }: { sessio
|
|
|
51
53
|
return () => { removed = true; for (const cleanup of cleanups.reverse()) void Promise.resolve().then(cleanup).catch(console.error); };
|
|
52
54
|
}, [session, windowId, onReady]);
|
|
53
55
|
return <>
|
|
54
|
-
<Button onPress={() => {
|
|
56
|
+
<Button onPress={() => { const id = `document-${++nextWindow}`; void openWindow({ id, title: session.getSnapshot().file.name, component: "main", size: { width: 800, height: 600 }, props: { windowId: id, windowProps: { documentId } } }).catch(e => setError(String(e))); }}>Open another view</Button>
|
|
55
57
|
{error ? <Text accessibilityRole="alert">{error}</Text> : null}
|
|
56
58
|
</>;
|
|
57
59
|
}
|