akanjs 3.0.0-beta.9 → 3.0.1
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/CHANGELOG.md +3659 -0
- package/README.ko.md +216 -159
- package/README.md +210 -151
- package/base/base.ts +6 -11
- package/base/baseEnv.ts +71 -14
- package/base/databaseModes.ts +75 -0
- package/base/index.ts +1 -0
- package/base/primitiveRegistry.ts +38 -47
- package/base/symbols.ts +1 -1
- package/base/types.ts +1 -1
- package/base/utils.ts +3 -6
- package/client/cn.ts +3 -13
- package/client/cookie.ts +61 -34
- package/client/createFont.ts +0 -2
- package/client/csrTypes.ts +47 -63
- package/client/decorators.ts +1 -1
- package/client/device.ts +101 -125
- package/client/frameConfig.ts +17 -28
- package/client/index.ts +1 -1
- package/client/makePageProto.tsx +3 -4
- package/client/native/accessibility.ts +1 -0
- package/client/native/app-state.ts +1 -0
- package/client/native/app.ts +1 -0
- package/client/native/appearance.ts +1 -0
- package/client/native/auth-session.ts +1 -0
- package/client/native/autostart.ts +1 -0
- package/client/native/badge.ts +1 -0
- package/client/native/biometric.ts +1 -0
- package/client/native/browser.ts +1 -0
- package/client/native/camera.ts +1 -0
- package/client/native/clipboard.ts +1 -0
- package/client/native/contacts.ts +1 -0
- package/client/native/device.ts +1 -0
- package/client/native/dialog.ts +1 -0
- package/client/native/dock.ts +1 -0
- package/client/native/file-picker.ts +1 -0
- package/client/native/filesystem.ts +1 -0
- package/client/native/geolocation.ts +1 -0
- package/client/native/global-shortcut.ts +1 -0
- package/client/native/haptics.ts +1 -0
- package/client/native/http.ts +1 -0
- package/client/native/iap.ts +1 -0
- package/client/native/keep-awake.ts +1 -0
- package/client/native/keyboard.ts +1 -0
- package/client/native/local-notifications.ts +1 -0
- package/client/native/menu.ts +1 -0
- package/client/native/network.ts +1 -0
- package/client/native/opener.ts +1 -0
- package/client/native/preferences.ts +1 -0
- package/client/native/push.ts +1 -0
- package/client/native/screen-orientation.ts +1 -0
- package/client/native/screen.ts +1 -0
- package/client/native/secure-storage.ts +1 -0
- package/client/native/share.ts +1 -0
- package/client/native/single-instance.ts +1 -0
- package/client/native/splash-screen.ts +1 -0
- package/client/native/sqlite.ts +1 -0
- package/client/native/toast.ts +1 -0
- package/client/native/tray.ts +1 -0
- package/client/native/updates.ts +1 -0
- package/client/native/volume.ts +1 -0
- package/client/native/window-state.ts +1 -0
- package/client/native/window.ts +1 -0
- package/client/native.ts +79 -0
- package/client/resolveServerUrl.ts +11 -0
- package/client/route/RootLayoutDefinition.ts +0 -6
- package/client/route/RouteDefinition.ts +46 -31
- package/client/route/resolveRouteModule.ts +1 -5
- package/client/router.ts +54 -40
- package/client/rscNavigation.ts +9 -5
- package/client/sharedContext.ts +2 -19
- package/client/storage.ts +66 -46
- package/client/translator.ts +31 -6
- package/client/types.ts +0 -3
- package/common/CodeAgentClient.ts +91 -0
- package/common/CodeTranscript.ts +325 -0
- package/common/Logger.ts +35 -36
- package/common/RouteLayering.ts +52 -0
- package/common/TrustedProxy.ts +6 -34
- package/common/applyMixins.ts +13 -2
- package/common/authToken.ts +0 -11
- package/common/capitalize.ts +3 -4
- package/common/clamp.ts +0 -1
- package/common/clientAddress.ts +1 -15
- package/common/codeAgentProfile.ts +181 -0
- package/common/codeAgentWire.ts +305 -0
- package/common/eventStream.ts +88 -0
- package/common/fileUpload.ts +1 -12
- package/common/formatNumber.ts +3 -12
- package/common/hmrPhase.ts +2 -0
- package/common/index.ts +105 -21
- package/common/interpolateTranslation.ts +1 -6
- package/common/isEmail.ts +0 -1
- package/common/isRecord.ts +2 -0
- package/common/isThenable.ts +1 -8
- package/common/isValidDate.ts +3 -5
- package/common/logContext.ts +1 -1
- package/common/markdownBlocks.ts +134 -0
- package/common/markdownSpans.ts +47 -0
- package/common/markdownTable.ts +50 -0
- package/common/mcpExposure.ts +4 -27
- package/common/objectPath.ts +67 -0
- package/common/objectify.ts +52 -0
- package/common/phone.ts +14 -0
- package/common/randomPick.ts +13 -0
- package/common/requestOrigin.ts +0 -17
- package/common/restClient.ts +8 -13
- package/common/round.ts +4 -0
- package/common/routeConvention.ts +22 -23
- package/common/sleep.ts +1 -8
- package/common/subRoute.ts +4 -7
- package/common/toError.ts +1 -0
- package/common/tunnelWire.ts +263 -0
- package/common/types.ts +5 -10
- package/common/version.ts +8 -0
- package/common/websocketContract.ts +80 -0
- package/constant/cascadePaths.ts +6 -9
- package/constant/constantRegistry.ts +21 -57
- package/constant/crystalize.ts +2 -12
- package/constant/dateSlot.ts +0 -15
- package/constant/fieldInfo.ts +30 -109
- package/constant/fieldQueryMeta.ts +2 -10
- package/constant/getDefault.ts +16 -8
- package/constant/hydrationPlan.ts +1 -9
- package/constant/index.ts +0 -1
- package/constant/labelOf.ts +1 -6
- package/constant/mask.ts +36 -38
- package/constant/purify.ts +6 -14
- package/constant/serialize.ts +82 -5
- package/constant/textFieldPaths.ts +2 -3
- package/constant/types.ts +2 -6
- package/constant/via.ts +20 -60
- package/dictionary/DictionaryLookup.ts +1 -7
- package/dictionary/agent.dictionary.ts +43 -11
- package/dictionary/base.dictionary.ts +6 -0
- package/dictionary/dictInfo.ts +145 -626
- package/dictionary/dictShape.ts +54 -0
- package/dictionary/dictionary.ts +1 -2
- package/dictionary/dictionaryRegistry.ts +7 -28
- package/dictionary/locale.ts +24 -116
- package/dictionary/trans.ts +18 -56
- package/document/dataLoader.ts +77 -78
- package/document/database.ts +52 -56
- package/document/documentQuery.ts +32 -32
- package/document/documentSchema.ts +21 -26
- package/document/filterMeta.ts +11 -31
- package/document/index.ts +0 -1
- package/document/into.ts +8 -18
- package/document/loaderInfo.ts +28 -7
- package/document/noDocumentError.ts +2 -7
- package/document/queryEvaluator.ts +21 -43
- package/document/types.ts +0 -1
- package/fetch/client/fetchClient.ts +62 -110
- package/fetch/client/fetchHandle.ts +4 -12
- package/fetch/client/httpClient.ts +32 -69
- package/fetch/client/remoteError.ts +2 -8
- package/fetch/client/sliceInitHandle.ts +3 -6
- package/fetch/client/sliceQueryArgs.ts +11 -0
- package/fetch/client/wsClient.ts +77 -61
- package/fetch/fetchType/appliedReturn.type.ts +5 -24
- package/fetch/fetchType/buildFetch.type.ts +28 -1
- package/fetch/fetchType/index.ts +0 -1
- package/fetch/requestStorage.ts +7 -28
- package/fetch/types.ts +0 -1
- package/index.ts +251 -136
- package/native/desktop.ts +5 -0
- package/package.json +48 -95
- package/server/SSR_MEMORY_DIAGNOSIS.md +2 -2
- package/server/akanApp.ts +171 -298
- package/server/akanAppHeaders.ts +6 -4
- package/server/akanOption.ts +25 -27
- package/server/akanServer.ts +143 -228
- package/server/animatedImage.ts +2 -11
- package/server/artifact/builderRpc.ts +42 -66
- package/server/artifact/devBuildRecovery.ts +12 -0
- package/server/artifact/index.ts +1 -1
- package/server/artifact/ipcTypes.ts +83 -33
- package/server/artifact/routeClientCache.ts +144 -64
- package/server/artifact/routeSeedIndexStore.ts +2 -35
- package/server/artifact/routesManifestStore.ts +13 -38
- package/server/binaryPubsub.ts +0 -9
- package/server/cachePolicy.ts +22 -46
- package/server/console.ts +12 -16
- package/server/consoleSession.ts +55 -12
- package/server/contentEncoding.ts +52 -26
- package/server/crawler.ts +6 -0
- package/server/decorators.ts +4 -70
- package/server/devtools/constantSerializer.ts +2 -14
- package/server/devtools/depsSerializer.ts +14 -46
- package/server/devtools/devtoolsJson.ts +6 -18
- package/server/devtools/devtoolsRouter.ts +2 -12
- package/server/devtools/signalSerializer.ts +4 -44
- package/server/devtools/types.ts +0 -12
- package/server/di/diLifecycle.ts +140 -224
- package/server/di/predefinedAdaptor.ts +11 -5
- package/server/di/resolveHierarchy.ts +114 -5
- package/server/di/utils.ts +13 -29
- package/server/head.tsx +49 -0
- package/server/hmr/clientScript.ts +174 -89
- package/server/hmr/csrDevManifest.ts +42 -0
- package/server/hmr/csrDevRuntime.ts +694 -0
- package/server/hmr/csrDevShell.ts +191 -0
- package/server/hmr/csrDevSourceMap.ts +142 -0
- package/server/hmr/devArtifactPruner.ts +77 -0
- package/server/hmr/devHmrController.ts +300 -173
- package/server/hmr/runtimeMetadataFile.ts +17 -0
- package/server/hmr/ssrDevShim.ts +112 -0
- package/server/hmr/ssrUpdateQueue.ts +111 -0
- package/server/hmr/wsHub.ts +55 -12
- package/server/imageOptimizer.ts +5 -26
- package/server/index.ts +2 -1
- package/server/lifecycle/orphanGroup.ts +21 -0
- package/server/lifecycle/portInUse.ts +1 -4
- package/server/lifecycle/runtimeDir.ts +0 -4
- package/server/lifecycle/shutdownManager.ts +4 -29
- package/server/logging/childOutputReader.ts +0 -12
- package/server/logging/hubFileSink.ts +10 -6
- package/server/logging/logControlSocket.ts +13 -7
- package/server/logging/logForwarder.ts +19 -22
- package/server/logging/logHub.ts +0 -0
- package/server/logging/logQuery.ts +4 -7
- package/server/logging/logStdoutWriter.ts +1 -11
- package/server/logging/logStreamRoute.ts +4 -21
- package/server/logging/logTailClient.ts +1 -8
- package/server/logging/rotatingLogWriter.ts +4 -6
- package/server/mcp/McpAuth.ts +5 -79
- package/server/mcp/McpDispatcher.ts +13 -90
- package/server/mcp/McpEventStream.ts +2 -12
- package/server/mcp/McpExecutionContext.ts +1 -42
- package/server/mcp/McpRateLimiter.ts +61 -30
- package/server/mcp/McpRouter.ts +49 -208
- package/server/mcp/PagePromptComposer.ts +7 -29
- package/server/memoryLimit.ts +1 -13
- package/server/nativeFile.ts +107 -0
- package/server/oauth/OAuthAuthorize.ts +3 -7
- package/server/oauth/OAuthClientIdMetadata.ts +2 -27
- package/server/oauth/OAuthErrors.ts +0 -13
- package/server/oauth/OAuthMetadata.ts +1 -7
- package/server/oauth/OAuthPkce.ts +0 -2
- package/server/oauth/OAuthRedirect.ts +0 -9
- package/server/oauth/OAuthRegistration.ts +0 -2
- package/server/oauth/OAuthRevocation.ts +1 -11
- package/server/oauth/OAuthToken.ts +3 -14
- package/server/oauth/oauthTypes.ts +1 -2
- package/server/ops/ageEncryption.ts +317 -0
- package/server/ops/appInfo.ts +94 -0
- package/server/ops/opsCommand.ts +116 -0
- package/server/ops/opsRoute.ts +152 -0
- package/server/ops/opsToken.ts +93 -0
- package/server/ops/snapshotJobs.ts +133 -0
- package/server/ops/snapshotRestore.ts +118 -0
- package/server/ops/snapshotTypes.ts +52 -0
- package/server/ops/sqliteFiles.ts +20 -0
- package/server/ops/sqliteSnapshot.ts +149 -0
- package/server/processMetricsCollector.ts +12 -14
- package/server/proxy/hostBasePathWebProxy.ts +20 -13
- package/server/proxy/index.ts +2 -3
- package/server/proxy/localeWebProxy.ts +3 -17
- package/server/proxy/types.ts +14 -0
- package/server/proxy/webProxyRunner.ts +13 -1
- package/server/resolver/CascadeRunner.ts +7 -23
- package/server/resolver/database.resolver.ts +57 -123
- package/server/resolver/service.resolver.ts +9 -161
- package/server/resolver/signal.resolver.ts +82 -110
- package/server/robots.ts +1 -23
- package/server/routeElementComposer.tsx +23 -52
- package/server/routeState.ts +15 -34
- package/server/routeTreeBuilder.ts +40 -125
- package/server/routing/apiRouter.ts +71 -53
- package/server/routing/appWsData.ts +4 -28
- package/server/routing/hostAllowlist.ts +24 -0
- package/server/routing/soloAppRoutes.ts +5 -5
- package/server/rscClient.tsx +32 -39
- package/server/rscClientFetch.ts +7 -3
- package/server/rscClientPatch.ts +4 -25
- package/server/rscHttp.ts +1 -1
- package/server/rscNavigationState.ts +10 -25
- package/server/rscPagePrompts.ts +4 -24
- package/server/rscSegmentOutlet.tsx +1 -5
- package/server/rscWorker.tsx +173 -303
- package/server/rscWorkerCache.ts +74 -8
- package/server/rscWorkerHost.ts +276 -240
- package/server/selfExec.ts +33 -0
- package/server/semaphore.ts +1 -1
- package/server/sitemap.ts +1 -3
- package/server/ssrFromRscRenderer.tsx +52 -139
- package/server/ssrTypes.ts +12 -29
- package/server/staticPath.ts +0 -16
- package/server/systemPageDocument.tsx +71 -2
- package/server/systemPages.tsx +4 -2
- package/server/tunnel/TunnelAgent.ts +237 -0
- package/server/tunnel/TunnelDataSocket.ts +146 -0
- package/server/tunnel/TunnelHttpStream.ts +86 -0
- package/server/tunnel/TunnelTcpStream.ts +96 -0
- package/server/tunnel/TunnelWebsocketStream.ts +110 -0
- package/server/tunnel/index.ts +6 -0
- package/server/tunnel/tunnelStream.ts +32 -0
- package/server/types.tsx +11 -10
- package/server/vendor/react-dom.ts +1 -0
- package/server/vendor/react-refresh-runtime.ts +13 -1
- package/server/vendor/react.ts +2 -0
- package/server/webRouter.ts +189 -331
- package/service/agent.service.ts +16 -80
- package/service/injectInfo.ts +106 -75
- package/service/ipcTypes.ts +8 -1
- package/service/liveSyncHub.ts +4 -34
- package/service/predefinedAdaptor/anthropicLlm.ts +51 -88
- package/service/predefinedAdaptor/cache.adaptor.ts +257 -75
- package/service/predefinedAdaptor/database.adaptor.ts +366 -108
- package/service/predefinedAdaptor/documentTransfer.ts +89 -0
- package/service/predefinedAdaptor/index.ts +2 -1
- package/service/predefinedAdaptor/insightQuery.ts +89 -79
- package/service/predefinedAdaptor/llm.adaptor.ts +53 -60
- package/service/predefinedAdaptor/llmOverflow.ts +63 -0
- package/service/predefinedAdaptor/openaiDialect.ts +36 -65
- package/service/predefinedAdaptor/openaiLlm.ts +24 -27
- package/service/predefinedAdaptor/queue.adaptor.ts +41 -22
- package/service/predefinedAdaptor/schedule.adaptor.ts +69 -9
- package/service/predefinedAdaptor/searchIndex.ts +76 -325
- package/service/predefinedAdaptor/solidCache.adaptor.ts +135 -12
- package/service/predefinedAdaptor/solidPubsub.adaptor.ts +28 -16
- package/service/predefinedAdaptor/solidQueue.adaptor.ts +61 -10
- package/service/predefinedAdaptor/solidSqlite.ts +10 -16
- package/service/predefinedAdaptor/sql/PendingStoreEnsures.ts +1 -0
- package/service/predefinedAdaptor/sql/PostgresInsightSession.ts +113 -0
- package/service/predefinedAdaptor/sql/QueryCompiler.ts +52 -32
- package/service/predefinedAdaptor/sql/SqlDocumentStore.ts +290 -138
- package/service/predefinedAdaptor/sql/SqliteInsightSession.ts +85 -0
- package/service/predefinedAdaptor/sql/UpdateCompiler.ts +1 -7
- package/service/predefinedAdaptor/sql/dialect/postgres.ts +138 -53
- package/service/predefinedAdaptor/sql/dialect/sqlite.ts +18 -15
- package/service/predefinedAdaptor/sql/driver/bunSqlite.ts +31 -4
- package/service/predefinedAdaptor/sql/driver/libsql.ts +20 -12
- package/service/predefinedAdaptor/sql/driver/postgres.ts +13 -7
- package/service/predefinedAdaptor/sql/search/fts5.ts +249 -0
- package/service/predefinedAdaptor/sql/search/mirror.ts +76 -0
- package/service/predefinedAdaptor/sql/search/postgres.ts +453 -0
- package/service/predefinedAdaptor/sql/search/types.ts +50 -0
- package/service/predefinedAdaptor/sql/types.ts +76 -17
- package/service/predefinedAdaptor/sql/values.ts +40 -2
- package/service/predefinedAdaptor/sqlitePath.ts +12 -0
- package/service/predefinedAdaptor/sseData.ts +23 -0
- package/service/predefinedAdaptor/storage.adaptor.ts +19 -7
- package/service/predefinedAdaptor/websocket.adaptor.ts +154 -184
- package/service/serve.ts +1 -2
- package/service/serviceModule.ts +52 -70
- package/service/toolNames.ts +5 -22
- package/service/types.ts +3 -9
- package/signal/CrossSiteGuard.ts +46 -42
- package/signal/SignalFailure.ts +2 -15
- package/signal/agent/AgentCatalogue.ts +9 -55
- package/signal/agent.signal.ts +9 -6
- package/signal/agentMeter.ts +45 -0
- package/signal/agentTurnStream.ts +48 -46
- package/signal/endpoint.ts +23 -8
- package/signal/endpointCache.ts +59 -0
- package/signal/endpointInfo.ts +26 -27
- package/signal/exception.ts +3 -34
- package/signal/guard.ts +4 -21
- package/signal/guards.ts +2 -10
- package/signal/index.ts +1 -0
- package/signal/internal.ts +12 -12
- package/signal/internalArg.ts +10 -13
- package/signal/internalInfo.ts +1 -1
- package/signal/mcp/McpDocument.ts +21 -90
- package/signal/mcp/McpProgress.ts +6 -19
- package/signal/mcp/McpUriTemplate.ts +1 -27
- package/signal/mcp/Msg.ts +13 -122
- package/signal/mcp/mcpProtocol.ts +3 -26
- package/signal/mcp/pagePrompt.ts +3 -9
- package/signal/middleware.ts +2 -87
- package/signal/openapi/openapi.ts +0 -4
- package/signal/schema/JsonSchemaBuilder.ts +32 -46
- package/signal/serializer/fetch.serializer.ts +41 -45
- package/signal/serverSignal.ts +6 -8
- package/signal/signalContext.ts +70 -168
- package/signal/signalRegistry.ts +11 -17
- package/signal/slice.ts +40 -36
- package/signal/sliceInfo.ts +5 -30
- package/signal/trace.ts +11 -84
- package/signal/types.ts +22 -76
- package/store/SliceRequest.ts +1 -11
- package/store/action.ts +153 -395
- package/store/actionTag.ts +1 -10
- package/store/agent/AgentBridge.ts +3 -25
- package/store/agent/AgentContext.ts +2 -9
- package/store/agent/AgentCursor.ts +160 -0
- package/store/agent/AgentPrompts.ts +0 -15
- package/store/agent/AgentVisual.ts +152 -0
- package/store/agent/ScreenFlash.ts +67 -0
- package/store/agent/ScreenReader.ts +3 -52
- package/store/agent/ScreenSettle.ts +1 -13
- package/store/agent/ScreenTarget.ts +16 -34
- package/store/agent/StoreCatalogue.ts +12 -24
- package/store/agent/StoreSurfaceSource.ts +38 -66
- package/store/agent/index.ts +4 -4
- package/store/agentic/AgentValue.ts +9 -26
- package/store/agentic/StExposeBuilder.ts +3 -12
- package/store/agentic/StExposeDraft.ts +0 -6
- package/store/agentic/StStateBuilder.ts +3 -11
- package/store/agentic/StStateDraft.ts +0 -5
- package/store/agentic/StToolBuilder.ts +48 -41
- package/store/agentic/StToolDraft.ts +0 -7
- package/store/agentic/attachAgentic.ts +2 -10
- package/store/agentic/formFields.ts +8 -42
- package/store/agentic/index.ts +0 -1
- package/store/agentic/useAgentReference.ts +2 -20
- package/store/agentic/useFieldTool.ts +176 -58
- package/store/agentic/useFormTools.ts +4 -21
- package/store/agentic/useRelationFieldTool.ts +2 -15
- package/store/baseSt.ts +0 -1
- package/store/databaseStateNames.ts +0 -9
- package/store/draftStore.ts +4 -54
- package/store/formSetterNames.ts +2 -19
- package/store/liveInsert.ts +36 -43
- package/store/sliceKeys.ts +37 -0
- package/store/sliceRole.ts +1 -10
- package/store/state.ts +4 -50
- package/store/stateBuilder.ts +1 -23
- package/store/storeInstance.ts +77 -151
- package/store/storeRegistry.ts +1 -8
- package/store/types.ts +1 -1
- package/test/conformance.ts +299 -0
- package/test/index.ts +2 -2
- package/test/sampleOf.ts +52 -28
- package/test/signalTestRuntime.ts +14 -12
- package/test/testServer.ts +66 -31
- package/types/base/base.d.ts +2 -3
- package/types/base/baseEnv.d.ts +8 -10
- package/types/base/databaseModes.d.ts +28 -0
- package/types/base/index.d.ts +1 -0
- package/types/base/primitiveRegistry.d.ts +23 -10
- package/types/base/symbols.d.ts +1 -1
- package/types/client/cn.d.ts +3 -13
- package/types/client/cookie.d.ts +8 -15
- package/types/client/csrTypes.d.ts +32 -60
- package/types/client/decorators.d.ts +1 -1
- package/types/client/device.d.ts +9 -11
- package/types/client/index.d.ts +1 -1
- package/types/client/native/accessibility.d.ts +1 -0
- package/types/client/native/app-state.d.ts +1 -0
- package/types/client/native/app.d.ts +1 -0
- package/types/client/native/appearance.d.ts +1 -0
- package/types/client/native/auth-session.d.ts +1 -0
- package/types/client/native/autostart.d.ts +1 -0
- package/types/client/native/badge.d.ts +1 -0
- package/types/client/native/biometric.d.ts +1 -0
- package/types/client/native/browser.d.ts +1 -0
- package/types/client/native/camera.d.ts +1 -0
- package/types/client/native/clipboard.d.ts +1 -0
- package/types/client/native/contacts.d.ts +1 -0
- package/types/client/native/device.d.ts +1 -0
- package/types/client/native/dialog.d.ts +1 -0
- package/types/client/native/dock.d.ts +1 -0
- package/types/client/native/file-picker.d.ts +1 -0
- package/types/client/native/filesystem.d.ts +1 -0
- package/types/client/native/geolocation.d.ts +1 -0
- package/types/client/native/global-shortcut.d.ts +1 -0
- package/types/client/native/haptics.d.ts +1 -0
- package/types/client/native/http.d.ts +1 -0
- package/types/client/native/iap.d.ts +1 -0
- package/types/client/native/keep-awake.d.ts +1 -0
- package/types/client/native/keyboard.d.ts +1 -0
- package/types/client/native/local-notifications.d.ts +1 -0
- package/types/client/native/menu.d.ts +1 -0
- package/types/client/native/network.d.ts +1 -0
- package/types/client/native/opener.d.ts +1 -0
- package/types/client/native/preferences.d.ts +1 -0
- package/types/client/native/push.d.ts +1 -0
- package/types/client/native/screen-orientation.d.ts +1 -0
- package/types/client/native/screen.d.ts +1 -0
- package/types/client/native/secure-storage.d.ts +1 -0
- package/types/client/native/share.d.ts +1 -0
- package/types/client/native/single-instance.d.ts +1 -0
- package/types/client/native/splash-screen.d.ts +1 -0
- package/types/client/native/sqlite.d.ts +1 -0
- package/types/client/native/toast.d.ts +1 -0
- package/types/client/native/tray.d.ts +1 -0
- package/types/client/native/updates.d.ts +1 -0
- package/types/client/native/volume.d.ts +1 -0
- package/types/client/native/window-state.d.ts +1 -0
- package/types/client/native/window.d.ts +1 -0
- package/types/client/native.d.ts +41 -0
- package/types/client/resolveServerUrl.d.ts +1 -0
- package/types/client/route/RootLayoutDefinition.d.ts +0 -1
- package/types/client/route/RouteDefinition.d.ts +18 -16
- package/types/client/route/resolveRouteModule.d.ts +1 -5
- package/types/client/router.d.ts +11 -4
- package/types/client/rscNavigation.d.ts +8 -5
- package/types/client/sharedContext.d.ts +2 -19
- package/types/client/storage.d.ts +9 -2
- package/types/client/translator.d.ts +1 -0
- package/types/client/types.d.ts +0 -3
- package/types/common/CodeAgentClient.d.ts +20 -0
- package/types/common/CodeTranscript.d.ts +72 -0
- package/types/common/Logger.d.ts +4 -20
- package/types/common/RouteLayering.d.ts +28 -0
- package/types/common/TrustedProxy.d.ts +2 -28
- package/types/common/applyMixins.d.ts +3 -0
- package/types/common/authToken.d.ts +0 -11
- package/types/common/capitalize.d.ts +1 -1
- package/types/common/clamp.d.ts +0 -1
- package/types/common/clientAddress.d.ts +1 -15
- package/types/common/codeAgentProfile.d.ts +115 -0
- package/types/common/codeAgentWire.d.ts +279 -0
- package/types/common/eventStream.d.ts +18 -0
- package/types/common/fileUpload.d.ts +6 -11
- package/types/common/hmrPhase.d.ts +2 -0
- package/types/common/index.d.ts +22 -21
- package/types/common/interpolateTranslation.d.ts +1 -6
- package/types/common/isEmail.d.ts +0 -1
- package/types/common/isRecord.d.ts +1 -0
- package/types/common/isThenable.d.ts +0 -8
- package/types/common/logContext.d.ts +1 -1
- package/types/common/markdownBlocks.d.ts +32 -0
- package/types/common/markdownSpans.d.ts +30 -0
- package/types/common/markdownTable.d.ts +14 -0
- package/types/common/mcpExposure.d.ts +3 -23
- package/types/common/objectPath.d.ts +10 -0
- package/types/common/objectify.d.ts +7 -0
- package/types/common/phone.d.ts +2 -0
- package/types/common/randomPick.d.ts +1 -0
- package/types/common/requestOrigin.d.ts +0 -17
- package/types/common/restClient.d.ts +0 -7
- package/types/common/round.d.ts +1 -0
- package/types/common/routeConvention.d.ts +2 -7
- package/types/common/sleep.d.ts +0 -1
- package/types/common/subRoute.d.ts +4 -6
- package/types/common/toError.d.ts +1 -0
- package/types/common/tunnelWire.d.ts +161 -0
- package/types/common/types.d.ts +6 -10
- package/types/common/version.d.ts +6 -0
- package/types/common/websocketContract.d.ts +41 -0
- package/types/constant/cascadePaths.d.ts +2 -5
- package/types/constant/constantRegistry.d.ts +4 -4
- package/types/constant/dateSlot.d.ts +0 -5
- package/types/constant/fieldInfo.d.ts +2 -21
- package/types/constant/fieldQueryMeta.d.ts +2 -10
- package/types/constant/getDefault.d.ts +5 -7
- package/types/constant/hydrationPlan.d.ts +0 -8
- package/types/constant/index.d.ts +0 -1
- package/types/constant/labelOf.d.ts +1 -6
- package/types/constant/mask.d.ts +11 -36
- package/types/constant/serialize.d.ts +10 -2
- package/types/constant/types.d.ts +2 -6
- package/types/constant/via.d.ts +0 -1
- package/types/dictionary/DictionaryLookup.d.ts +1 -7
- package/types/dictionary/agent.dictionary.d.ts +2 -1
- package/types/dictionary/base.dictionary.d.ts +1 -1
- package/types/dictionary/dictInfo.d.ts +25 -92
- package/types/dictionary/dictShape.d.ts +26 -0
- package/types/dictionary/dictionary.d.ts +9 -9
- package/types/dictionary/dictionaryRegistry.d.ts +1 -15
- package/types/dictionary/locale.d.ts +9 -28
- package/types/dictionary/trans.d.ts +5 -14
- package/types/document/dataLoader.d.ts +2 -2
- package/types/document/database.d.ts +21 -14
- package/types/document/documentQuery.d.ts +6 -1
- package/types/document/documentSchema.d.ts +3 -7
- package/types/document/filterMeta.d.ts +3 -8
- package/types/document/index.d.ts +0 -1
- package/types/document/into.d.ts +3 -2
- package/types/document/loaderInfo.d.ts +9 -4
- package/types/document/noDocumentError.d.ts +2 -7
- package/types/document/queryEvaluator.d.ts +7 -24
- package/types/document/types.d.ts +0 -1
- package/types/fetch/client/fetchClient.d.ts +2 -12
- package/types/fetch/client/fetchHandle.d.ts +3 -11
- package/types/fetch/client/httpClient.d.ts +3 -1
- package/types/fetch/client/remoteError.d.ts +2 -8
- package/types/fetch/client/sliceInitHandle.d.ts +2 -5
- package/types/fetch/client/sliceQueryArgs.d.ts +3 -0
- package/types/fetch/client/wsClient.d.ts +10 -15
- package/types/fetch/fetchType/appliedReturn.type.d.ts +5 -23
- package/types/fetch/fetchType/buildFetch.type.d.ts +15 -1
- package/types/fetch/fetchType/index.d.ts +0 -1
- package/types/fetch/requestStorage.d.ts +3 -16
- package/types/fetch/types.d.ts +0 -1
- package/types/index.d.ts +245 -135
- package/types/native/desktop.d.ts +3 -0
- package/types/server/akanApp.d.ts +5 -28
- package/types/server/akanAppHeaders.d.ts +2 -1
- package/types/server/akanOption.d.ts +12 -24
- package/types/server/akanServer.d.ts +16 -56
- package/types/server/animatedImage.d.ts +0 -6
- package/types/server/artifact/builderRpc.d.ts +10 -31
- package/types/server/artifact/devBuildRecovery.d.ts +4 -0
- package/types/server/artifact/index.d.ts +1 -1
- package/types/server/artifact/ipcTypes.d.ts +80 -31
- package/types/server/artifact/routeClientCache.d.ts +12 -13
- package/types/server/artifact/routeSeedIndexStore.d.ts +0 -16
- package/types/server/artifact/routesManifestStore.d.ts +1 -1
- package/types/server/binaryPubsub.d.ts +0 -8
- package/types/server/cachePolicy.d.ts +4 -22
- package/types/server/console.d.ts +3 -6
- package/types/server/consoleSession.d.ts +2 -2
- package/types/server/contentEncoding.d.ts +6 -14
- package/types/server/crawler.d.ts +1 -0
- package/types/server/decorators.d.ts +0 -12
- package/types/server/devtools/constantSerializer.d.ts +1 -6
- package/types/server/devtools/depsSerializer.d.ts +1 -7
- package/types/server/devtools/devtoolsJson.d.ts +1 -7
- package/types/server/devtools/devtoolsRouter.d.ts +2 -11
- package/types/server/devtools/signalSerializer.d.ts +1 -9
- package/types/server/devtools/types.d.ts +0 -11
- package/types/server/di/diLifecycle.d.ts +0 -36
- package/types/server/di/predefinedAdaptor.d.ts +3 -2
- package/types/server/di/resolveHierarchy.d.ts +22 -5
- package/types/server/di/utils.d.ts +4 -17
- package/types/server/head.d.ts +6 -0
- package/types/server/hmr/csrDevManifest.d.ts +33 -0
- package/types/server/hmr/csrDevRuntime.d.ts +105 -0
- package/types/server/hmr/csrDevShell.d.ts +22 -0
- package/types/server/hmr/csrDevSourceMap.d.ts +17 -0
- package/types/server/hmr/devArtifactPruner.d.ts +9 -0
- package/types/server/hmr/devHmrController.d.ts +11 -8
- package/types/server/hmr/runtimeMetadataFile.d.ts +1 -0
- package/types/server/hmr/ssrDevShim.d.ts +7 -0
- package/types/server/hmr/ssrUpdateQueue.d.ts +23 -0
- package/types/server/hmr/wsHub.d.ts +33 -8
- package/types/server/index.d.ts +2 -1
- package/types/server/lifecycle/orphanGroup.d.ts +7 -0
- package/types/server/lifecycle/portInUse.d.ts +1 -4
- package/types/server/lifecycle/runtimeDir.d.ts +0 -4
- package/types/server/lifecycle/shutdownManager.d.ts +0 -9
- package/types/server/logging/childOutputReader.d.ts +0 -12
- package/types/server/logging/hubFileSink.d.ts +1 -5
- package/types/server/logging/logControlSocket.d.ts +2 -7
- package/types/server/logging/logForwarder.d.ts +3 -15
- package/types/server/logging/logHub.d.ts +1 -15
- package/types/server/logging/logQuery.d.ts +3 -6
- package/types/server/logging/logStdoutWriter.d.ts +0 -6
- package/types/server/logging/logStreamRoute.d.ts +0 -9
- package/types/server/logging/logTailClient.d.ts +0 -5
- package/types/server/mcp/McpAuth.d.ts +3 -71
- package/types/server/mcp/McpDispatcher.d.ts +0 -23
- package/types/server/mcp/McpEventStream.d.ts +1 -12
- package/types/server/mcp/McpExecutionContext.d.ts +0 -33
- package/types/server/mcp/McpRateLimiter.d.ts +10 -13
- package/types/server/mcp/McpRouter.d.ts +1 -47
- package/types/server/mcp/PagePromptComposer.d.ts +1 -13
- package/types/server/memoryLimit.d.ts +1 -13
- package/types/server/nativeFile.d.ts +10 -0
- package/types/server/oauth/OAuthAuthorize.d.ts +1 -6
- package/types/server/oauth/OAuthClientIdMetadata.d.ts +2 -26
- package/types/server/oauth/OAuthErrors.d.ts +0 -13
- package/types/server/oauth/OAuthMetadata.d.ts +1 -7
- package/types/server/oauth/OAuthPkce.d.ts +0 -1
- package/types/server/oauth/OAuthRedirect.d.ts +0 -9
- package/types/server/oauth/OAuthRegistration.d.ts +0 -1
- package/types/server/oauth/OAuthRevocation.d.ts +1 -11
- package/types/server/oauth/OAuthToken.d.ts +1 -13
- package/types/server/oauth/oauthTypes.d.ts +1 -2
- package/types/server/ops/ageEncryption.d.ts +19 -0
- package/types/server/ops/appInfo.d.ts +37 -0
- package/types/server/ops/opsCommand.d.ts +5 -0
- package/types/server/ops/opsRoute.d.ts +24 -0
- package/types/server/ops/opsToken.d.ts +26 -0
- package/types/server/ops/snapshotJobs.d.ts +24 -0
- package/types/server/ops/snapshotRestore.d.ts +24 -0
- package/types/server/ops/snapshotTypes.d.ts +45 -0
- package/types/server/ops/sqliteFiles.d.ts +5 -0
- package/types/server/ops/sqliteSnapshot.d.ts +32 -0
- package/types/server/processMetricsCollector.d.ts +3 -1
- package/types/server/proxy/hostBasePathWebProxy.d.ts +7 -1
- package/types/server/proxy/index.d.ts +2 -3
- package/types/server/proxy/localeWebProxy.d.ts +1 -1
- package/types/server/proxy/types.d.ts +5 -0
- package/types/server/proxy/webProxyRunner.d.ts +1 -0
- package/types/server/resolver/CascadeRunner.d.ts +0 -4
- package/types/server/resolver/database.resolver.d.ts +1 -1
- package/types/server/resolver/service.resolver.d.ts +2 -2
- package/types/server/resolver/signal.resolver.d.ts +0 -15
- package/types/server/routeElementComposer.d.ts +2 -8
- package/types/server/routeState.d.ts +1 -1
- package/types/server/routing/apiRouter.d.ts +14 -21
- package/types/server/routing/appWsData.d.ts +0 -26
- package/types/server/routing/hostAllowlist.d.ts +8 -0
- package/types/server/routing/soloAppRoutes.d.ts +2 -6
- package/types/server/rscClient.d.ts +0 -12
- package/types/server/rscClientFetch.d.ts +6 -6
- package/types/server/rscClientPatch.d.ts +1 -1
- package/types/server/rscHttp.d.ts +1 -0
- package/types/server/rscNavigationState.d.ts +3 -2
- package/types/server/rscPagePrompts.d.ts +0 -9
- package/types/server/rscWorkerCache.d.ts +41 -3
- package/types/server/rscWorkerHost.d.ts +17 -60
- package/types/server/selfExec.d.ts +8 -0
- package/types/server/ssrFromRscRenderer.d.ts +3 -13
- package/types/server/ssrTypes.d.ts +10 -29
- package/types/server/staticPath.d.ts +0 -16
- package/types/server/systemPageDocument.d.ts +10 -0
- package/types/server/systemPages.d.ts +2 -3
- package/types/server/tunnel/TunnelAgent.d.ts +29 -0
- package/types/server/tunnel/TunnelDataSocket.d.ts +22 -0
- package/types/server/tunnel/TunnelHttpStream.d.ts +10 -0
- package/types/server/tunnel/TunnelTcpStream.d.ts +11 -0
- package/types/server/tunnel/TunnelWebsocketStream.d.ts +10 -0
- package/types/server/tunnel/index.d.ts +6 -0
- package/types/server/tunnel/tunnelStream.d.ts +19 -0
- package/types/server/tunnel.d.ts +1 -0
- package/types/server/types.d.ts +11 -10
- package/types/server/vendor/react-dom.d.ts +1 -1
- package/types/server/vendor/react-refresh-runtime.d.ts +1 -1
- package/types/server/vendor/react.d.ts +1 -1
- package/types/server/webRouter.d.ts +10 -21
- package/types/service/agent.service.d.ts +10 -77
- package/types/service/injectInfo.d.ts +26 -15
- package/types/service/ipcTypes.d.ts +22 -0
- package/types/service/liveSyncHub.d.ts +4 -22
- package/types/service/predefinedAdaptor/anthropicLlm.d.ts +17 -45
- package/types/service/predefinedAdaptor/cache.adaptor.d.ts +42 -12
- package/types/service/predefinedAdaptor/database.adaptor.d.ts +20 -16
- package/types/service/predefinedAdaptor/documentTransfer.d.ts +15 -0
- package/types/service/predefinedAdaptor/index.d.ts +2 -1
- package/types/service/predefinedAdaptor/insightQuery.d.ts +7 -30
- package/types/service/predefinedAdaptor/llm.adaptor.d.ts +44 -60
- package/types/service/predefinedAdaptor/llmOverflow.d.ts +16 -0
- package/types/service/predefinedAdaptor/openaiDialect.d.ts +18 -35
- package/types/service/predefinedAdaptor/openaiLlm.d.ts +9 -14
- package/types/service/predefinedAdaptor/queue.adaptor.d.ts +12 -7
- package/types/service/predefinedAdaptor/schedule.adaptor.d.ts +7 -2
- package/types/service/predefinedAdaptor/searchIndex.d.ts +17 -47
- package/types/service/predefinedAdaptor/solidCache.adaptor.d.ts +15 -6
- package/types/service/predefinedAdaptor/solidPubsub.adaptor.d.ts +6 -4
- package/types/service/predefinedAdaptor/solidSqlite.d.ts +2 -1
- package/types/service/predefinedAdaptor/sql/PostgresInsightSession.d.ts +20 -0
- package/types/service/predefinedAdaptor/sql/QueryCompiler.d.ts +9 -11
- package/types/service/predefinedAdaptor/sql/SqlDocumentStore.d.ts +11 -25
- package/types/service/predefinedAdaptor/sql/SqliteInsightSession.d.ts +15 -0
- package/types/service/predefinedAdaptor/sql/UpdateCompiler.d.ts +0 -4
- package/types/service/predefinedAdaptor/sql/dialect/postgres.d.ts +18 -10
- package/types/service/predefinedAdaptor/sql/dialect/sqlite.d.ts +5 -2
- package/types/service/predefinedAdaptor/sql/driver/bunSqlite.d.ts +9 -3
- package/types/service/predefinedAdaptor/sql/driver/libsql.d.ts +8 -5
- package/types/service/predefinedAdaptor/sql/driver/postgres.d.ts +4 -4
- package/types/service/predefinedAdaptor/sql/search/fts5.d.ts +28 -0
- package/types/service/predefinedAdaptor/sql/search/mirror.d.ts +20 -0
- package/types/service/predefinedAdaptor/sql/search/postgres.d.ts +53 -0
- package/types/service/predefinedAdaptor/sql/search/types.d.ts +45 -0
- package/types/service/predefinedAdaptor/sql/types.d.ts +69 -15
- package/types/service/predefinedAdaptor/sql/values.d.ts +8 -0
- package/types/service/predefinedAdaptor/sqlitePath.d.ts +1 -0
- package/types/service/predefinedAdaptor/sseData.d.ts +1 -0
- package/types/service/predefinedAdaptor/storage.adaptor.d.ts +3 -2
- package/types/service/predefinedAdaptor/websocket.adaptor.d.ts +26 -26
- package/types/service/serviceModule.d.ts +7 -7
- package/types/service/toolNames.d.ts +4 -21
- package/types/service/types.d.ts +3 -3
- package/types/signal/CrossSiteGuard.d.ts +11 -30
- package/types/signal/SignalFailure.d.ts +1 -15
- package/types/signal/agent/AgentCatalogue.d.ts +8 -54
- package/types/signal/agent.signal.d.ts +4 -1
- package/types/signal/agentMeter.d.ts +24 -0
- package/types/signal/agentTurnStream.d.ts +10 -11
- package/types/signal/endpoint.d.ts +1 -2
- package/types/signal/endpointCache.d.ts +5 -0
- package/types/signal/endpointInfo.d.ts +4 -9
- package/types/signal/exception.d.ts +1 -34
- package/types/signal/guard.d.ts +4 -15
- package/types/signal/guards.d.ts +2 -10
- package/types/signal/index.d.ts +1 -0
- package/types/signal/internal.d.ts +1 -5
- package/types/signal/internalArg.d.ts +7 -13
- package/types/signal/mcp/McpDocument.d.ts +5 -45
- package/types/signal/mcp/McpProgress.d.ts +6 -19
- package/types/signal/mcp/McpUriTemplate.d.ts +1 -19
- package/types/signal/mcp/Msg.d.ts +13 -70
- package/types/signal/mcp/mcpProtocol.d.ts +1 -26
- package/types/signal/mcp/pagePrompt.d.ts +3 -9
- package/types/signal/middleware.d.ts +0 -27
- package/types/signal/schema/JsonSchemaBuilder.d.ts +15 -43
- package/types/signal/serializer/fetch.serializer.d.ts +1 -6
- package/types/signal/serverSignal.d.ts +0 -1
- package/types/signal/signalContext.d.ts +14 -66
- package/types/signal/signalRegistry.d.ts +0 -1
- package/types/signal/slice.d.ts +6 -11
- package/types/signal/sliceInfo.d.ts +5 -30
- package/types/signal/trace.d.ts +2 -30
- package/types/signal/types.d.ts +22 -76
- package/types/store/SliceRequest.d.ts +1 -11
- package/types/store/action.d.ts +2 -6
- package/types/store/actionTag.d.ts +1 -10
- package/types/store/agent/AgentBridge.d.ts +3 -22
- package/types/store/agent/AgentContext.d.ts +1 -7
- package/types/store/agent/AgentCursor.d.ts +24 -0
- package/types/store/agent/AgentPrompts.d.ts +0 -5
- package/types/store/agent/AgentVisual.d.ts +25 -0
- package/types/store/agent/ScreenFlash.d.ts +23 -0
- package/types/store/agent/ScreenReader.d.ts +3 -26
- package/types/store/agent/ScreenSettle.d.ts +1 -12
- package/types/store/agent/ScreenTarget.d.ts +3 -23
- package/types/store/agent/StoreCatalogue.d.ts +12 -16
- package/types/store/agent/StoreSurfaceSource.d.ts +11 -23
- package/types/store/agent/index.d.ts +4 -3
- package/types/store/agentic/AgentValue.d.ts +3 -23
- package/types/store/agentic/StExposeBuilder.d.ts +2 -11
- package/types/store/agentic/StExposeDraft.d.ts +0 -6
- package/types/store/agentic/StStateBuilder.d.ts +1 -7
- package/types/store/agentic/StStateDraft.d.ts +0 -5
- package/types/store/agentic/StToolBuilder.d.ts +14 -37
- package/types/store/agentic/StToolDraft.d.ts +0 -7
- package/types/store/agentic/attachAgentic.d.ts +2 -10
- package/types/store/agentic/formFields.d.ts +5 -41
- package/types/store/agentic/index.d.ts +0 -1
- package/types/store/agentic/useAgentReference.d.ts +2 -20
- package/types/store/agentic/useFieldTool.d.ts +19 -16
- package/types/store/agentic/useFormTools.d.ts +1 -18
- package/types/store/agentic/useRelationFieldTool.d.ts +1 -14
- package/types/store/baseSt.d.ts +2 -15
- package/types/store/databaseStateNames.d.ts +0 -9
- package/types/store/draftStore.d.ts +4 -30
- package/types/store/formSetterNames.d.ts +0 -19
- package/types/store/liveInsert.d.ts +0 -23
- package/types/store/sliceKeys.d.ts +31 -0
- package/types/store/sliceRole.d.ts +1 -10
- package/types/store/state.d.ts +2 -9
- package/types/store/stateBuilder.d.ts +0 -14
- package/types/store/storeInstance.d.ts +9 -22
- package/types/store/storeRegistry.d.ts +0 -2
- package/types/test/conformance.d.ts +73 -0
- package/types/test/index.d.ts +2 -2
- package/types/test/sampleOf.d.ts +17 -2
- package/types/test/signalTestRuntime.d.ts +1 -1
- package/types/test/testServer.d.ts +4 -3
- package/types/ui/Agent/Approval.d.ts +1 -1
- package/types/ui/Agent/Attach.d.ts +3 -3
- package/types/ui/Agent/Bubble.d.ts +4 -15
- package/types/ui/Agent/Chat.d.ts +29 -78
- package/types/ui/Agent/ChatCommands.d.ts +4 -14
- package/types/ui/Agent/Composer.d.ts +15 -9
- package/types/ui/Agent/Dock.d.ts +39 -11
- package/types/ui/Agent/Guide.d.ts +1 -5
- package/types/ui/Agent/History.d.ts +1 -18
- package/types/ui/Agent/Launcher.d.ts +3 -3
- package/types/ui/Agent/Markdown.d.ts +4 -8
- package/types/ui/Agent/MentionNode.d.ts +18 -0
- package/types/ui/Agent/Menu.d.ts +3 -5
- package/types/ui/Agent/Question.d.ts +2 -7
- package/types/ui/Agent/Queued.d.ts +2 -7
- package/types/ui/Agent/Refer.d.ts +1 -5
- package/types/ui/Agent/RichInput.d.ts +14 -0
- package/types/ui/Agent/Skip.d.ts +4 -16
- package/types/ui/Agent/Steps.d.ts +17 -0
- package/types/ui/Agent/ToolCard.d.ts +9 -0
- package/types/ui/Agent/Zone.d.ts +13 -30
- package/types/ui/Agent/agentSessionOf.d.ts +20 -16
- package/types/ui/Agent/attachment.d.ts +4 -38
- package/types/ui/Agent/fetchRunner.d.ts +1 -8
- package/types/ui/Agent/index.d.ts +5 -9
- package/types/ui/Agent/mentionDraft.d.ts +9 -0
- package/types/ui/Agent/tokenCount.d.ts +1 -5
- package/types/ui/Agent/useChatAttachments.d.ts +0 -5
- package/types/ui/Agent/useChatQueue.d.ts +1 -14
- package/types/ui/Agent/useChatReferences.d.ts +3 -14
- package/types/ui/Agent/useChatVoice.d.ts +0 -12
- package/types/ui/Agent/useDraftRecall.d.ts +0 -8
- package/types/ui/Agent/useKeyboardInset.d.ts +0 -7
- package/types/ui/Agent/useReferenceMenu.d.ts +3 -11
- package/types/ui/Agent/useSlashMenu.d.ts +0 -2
- package/types/ui/Agent/voice.d.ts +8 -42
- package/types/ui/Badge.d.ts +0 -1
- package/types/ui/BottomSheet.d.ts +2 -5
- package/types/ui/Button.d.ts +6 -23
- package/types/ui/ClientSide.d.ts +1 -3
- package/types/ui/Constant/Doc.d.ts +6 -6
- package/types/ui/Constant/Graph.d.ts +1 -1
- package/types/ui/Constant/index.d.ts +1 -1
- package/types/ui/Constant/schemaGraph.d.ts +0 -4
- package/types/ui/Copy.d.ts +3 -4
- package/types/ui/CsrImage.d.ts +2 -1
- package/types/ui/Data/CardList.d.ts +1 -1
- package/types/ui/Data/Dashboard.d.ts +2 -5
- package/types/ui/Data/Insight.d.ts +1 -1
- package/types/ui/Data/Item.d.ts +10 -10
- package/types/ui/Data/ListContainer.d.ts +2 -11
- package/types/ui/Data/Pagination.d.ts +1 -3
- package/types/ui/Data/QueryMaker.d.ts +3 -10
- package/types/ui/Data/RefPicker.d.ts +1 -8
- package/types/ui/Data/TableList.d.ts +1 -1
- package/types/ui/DatePicker.d.ts +0 -11
- package/types/ui/Dialog/LegacyModal.d.ts +1 -4
- package/types/ui/Dialog/Provider.d.ts +38 -5
- package/types/ui/Dialog/index.d.ts +5 -5
- package/types/ui/DragAction.d.ts +4 -4
- package/types/ui/DraggableList.d.ts +3 -3
- package/types/ui/Dropdown.d.ts +2 -10
- package/types/ui/Empty.d.ts +4 -11
- package/types/ui/Field/Choice.d.ts +3 -3
- package/types/ui/Field/Collection.d.ts +4 -19
- package/types/ui/Field/DateField.d.ts +2 -2
- package/types/ui/Field/Label.d.ts +1 -1
- package/types/ui/Field/NumberField.d.ts +2 -2
- package/types/ui/Field/Relation.d.ts +14 -41
- package/types/ui/Field/Text.d.ts +14 -71
- package/types/ui/Field/index.d.ts +21 -30
- package/types/ui/Field/lightRefCache.d.ts +0 -8
- package/types/ui/Field/useRelationOptions.d.ts +1 -12
- package/types/ui/Image.d.ts +9 -13
- package/types/ui/InfiniteScroll.d.ts +3 -7
- package/types/ui/Input.d.ts +8 -15
- package/types/ui/KeyboardAvoiding.d.ts +1 -1
- package/types/ui/Layout/BottomInset.d.ts +1 -1
- package/types/ui/Layout/BottomTab.d.ts +1 -1
- package/types/ui/Layout/Header.d.ts +1 -1
- package/types/ui/Layout/Navbar.d.ts +1 -1
- package/types/ui/Layout/Role.d.ts +23 -0
- package/types/ui/Layout/Sider.d.ts +22 -1
- package/types/ui/Layout/TopInset.d.ts +6 -1
- package/types/ui/Layout/index.d.ts +13 -13
- package/types/ui/LegacyModal.d.ts +2 -13
- package/types/ui/Link/Action.d.ts +11 -0
- package/types/ui/Link/Anchor.d.ts +20 -0
- package/types/ui/Link/index.d.ts +5 -8
- package/types/ui/Load/Edit.d.ts +1 -1
- package/types/ui/Load/Edit_Client.d.ts +1 -1
- package/types/ui/Load/Page.d.ts +3 -5
- package/types/ui/Load/PageCSR.d.ts +1 -1
- package/types/ui/Load/Pagination.d.ts +1 -1
- package/types/ui/Load/Stream.d.ts +1 -13
- package/types/ui/Load/Units.d.ts +1 -1
- package/types/ui/Load/View.d.ts +2 -7
- package/types/ui/Loading/ProgressBar.d.ts +1 -5
- package/types/ui/Loading/Skeleton.d.ts +3 -1
- package/types/ui/Loading/Spin.d.ts +9 -15
- package/types/ui/Loading/index.d.ts +3 -8
- package/types/ui/Loading/index_.d.ts +3 -10
- package/types/ui/Menu.d.ts +1 -6
- package/types/ui/Modal.d.ts +1 -18
- package/types/ui/Model/AdminPanel.d.ts +2 -5
- package/types/ui/Model/DraftBar.d.ts +3 -8
- package/types/ui/Model/Edit.d.ts +1 -1
- package/types/ui/Model/EditModal.d.ts +8 -23
- package/types/ui/Model/EditWrapper.d.ts +1 -1
- package/types/ui/Model/LoadStore.d.ts +18 -0
- package/types/ui/Model/New.d.ts +1 -1
- package/types/ui/Model/NewWrapper.d.ts +1 -1
- package/types/ui/Model/NewWrapper_Client.d.ts +1 -1
- package/types/ui/Model/Remove.d.ts +1 -3
- package/types/ui/Model/RemoveWrapper.d.ts +1 -1
- package/types/ui/Model/SureToRemove.d.ts +1 -4
- package/types/ui/Model/View.d.ts +1 -1
- package/types/ui/Model/ViewEditModal.d.ts +1 -3
- package/types/ui/Model/ViewModal.d.ts +1 -1
- package/types/ui/Model/ViewWrapper.d.ts +1 -1
- package/types/ui/Model/draftScope.d.ts +0 -7
- package/types/ui/Model/index.d.ts +2 -2
- package/types/ui/Model/index_.d.ts +2 -2
- package/types/ui/More.d.ts +1 -1
- package/types/ui/ObjectId.d.ts +1 -1
- package/types/ui/Pagination.d.ts +5 -13
- package/types/ui/Popconfirm.d.ts +4 -18
- package/types/ui/Radio.d.ts +0 -4
- package/types/ui/RecentTime.d.ts +6 -10
- package/types/ui/Reference/Panel.d.ts +46 -8
- package/types/ui/Reference/Segmented.d.ts +1 -4
- package/types/ui/Reference/docUi.d.ts +24 -0
- package/types/ui/Reference/index.d.ts +3 -7
- package/types/ui/Refresh.d.ts +2 -2
- package/types/ui/ScreenNavigator.d.ts +4 -4
- package/types/ui/Select.d.ts +3 -20
- package/types/ui/ServerPortal.d.ts +1 -1
- package/types/ui/Signal/Arg.d.ts +13 -13
- package/types/ui/Signal/Doc.d.ts +6 -6
- package/types/ui/Signal/Endpoint.d.ts +43 -0
- package/types/ui/Signal/Listener.d.ts +2 -2
- package/types/ui/Signal/Object.d.ts +4 -4
- package/types/ui/Signal/Response.d.ts +3 -3
- package/types/ui/Signal/RestApi.d.ts +5 -5
- package/types/ui/Signal/WebSocket.d.ts +25 -2
- package/types/ui/Signal/endpointEntries.d.ts +2 -4
- package/types/ui/Signal/index.d.ts +1 -3
- package/types/ui/Signal/style.d.ts +1 -2
- package/types/ui/Switch.d.ts +2 -6
- package/types/ui/System/CSR.d.ts +5 -5
- package/types/ui/System/Client.d.ts +12 -14
- package/types/ui/System/Common.d.ts +12 -23
- package/types/ui/System/Reconnect.d.ts +1 -1
- package/types/ui/System/Root.d.ts +2 -5
- package/types/ui/System/SSR.d.ts +4 -4
- package/types/ui/System/SelectLanguage.d.ts +1 -1
- package/types/ui/System/ThemeToggle.d.ts +2 -1
- package/types/ui/System/index.d.ts +8 -7
- package/types/ui/Tab/Provider.d.ts +25 -5
- package/types/ui/Tab/index.d.ts +4 -4
- package/types/ui/Table.d.ts +8 -24
- package/types/ui/Toast.d.ts +11 -18
- package/types/ui/ToggleSelect.d.ts +0 -5
- package/types/ui/Tooltip.d.ts +1 -2
- package/types/ui/UiOverride/UiOverride.d.ts +111 -0
- package/types/ui/UiOverride/index.d.ts +2 -5
- package/types/ui/UiOverride/override.d.ts +2 -18
- package/types/ui/Unauthorized.d.ts +1 -7
- package/types/ui/agentAttrs.d.ts +4 -11
- package/types/ui/index.d.ts +4 -4
- package/types/ui/overlayLayer.d.ts +4 -24
- package/types/ui/overlayPosition.d.ts +0 -12
- package/types/ui/recipe/badgeRecipe.d.ts +2 -2
- package/types/ui/recipe/buttonRecipe.d.ts +2 -2
- package/types/ui/recipe/factory.d.ts +1 -21
- package/types/ui/recipe/index.d.ts +0 -14
- package/types/ui/recipe/inputRecipe.d.ts +3 -3
- package/types/ui/sliceNamesOf.d.ts +78 -0
- package/types/ui/triggerSlot.d.ts +3 -13
- package/types/vendor/@akanjs/native/packages/cli/src/api.d.ts +267 -0
- package/types/vendor/@akanjs/native/packages/cli/src/commands/build.d.ts +28 -0
- package/types/vendor/@akanjs/native/packages/cli/src/commands/compat.d.ts +2 -0
- package/types/vendor/@akanjs/native/packages/cli/src/commands/dev.d.ts +2 -0
- package/types/vendor/@akanjs/native/packages/cli/src/commands/doctor.d.ts +37 -0
- package/types/vendor/@akanjs/native/packages/cli/src/commands/plugin.d.ts +2 -0
- package/types/vendor/@akanjs/native/packages/cli/src/commands/signing.d.ts +2 -0
- package/types/vendor/@akanjs/native/packages/cli/src/commands/test.d.ts +2 -0
- package/types/vendor/@akanjs/native/packages/cli/src/commands/toolchain.d.ts +2 -0
- package/types/vendor/@akanjs/native/packages/cli/src/commands/update.d.ts +2 -0
- package/types/vendor/@akanjs/native/packages/cli/src/config.d.ts +333 -0
- package/types/vendor/@akanjs/native/packages/cli/src/index.d.ts +2 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/acl.d.ts +21 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/addons.d.ts +19 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/apilevel.d.ts +40 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/apk.d.ts +36 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/args.d.ts +9 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/boot.d.ts +32 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/chrome.d.ts +6 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/codegen.d.ts +94 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/compat.d.ts +49 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/configkeys.d.ts +2 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/csp.d.ts +51 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/desktop-server.d.ts +8 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/env.d.ts +44 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/exec.d.ts +31 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/googleservices.d.ts +2 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/hmr.d.ts +120 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/html.d.ts +20 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/icons.d.ts +44 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/image.d.ts +21 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/iossigning.d.ts +81 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/launch.d.ts +51 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/log.d.ts +42 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/macossigning.d.ts +95 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/manifestmerge.d.ts +18 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/maven.d.ts +97 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/names.d.ts +45 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/native-plugins.d.ts +67 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/nativeconfig.d.ts +11 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/permissions.d.ts +10 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/plist.d.ts +11 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/png.d.ts +11 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/prepare.d.ts +164 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/privacy.d.ts +13 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/project.d.ts +218 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/publish.d.ts +32 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/root.d.ts +1 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/routes.d.ts +1 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/serve.d.ts +17 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/signing.d.ts +14 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/spec.d.ts +96 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/toolchains.d.ts +159 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/updates.d.ts +103 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/vectors.d.ts +13 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/windowssigning.d.ts +30 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/xml.d.ts +13 -0
- package/types/vendor/@akanjs/native/packages/cli/src/platforms/android.d.ts +57 -0
- package/types/vendor/@akanjs/native/packages/cli/src/platforms/desktop-update.d.ts +13 -0
- package/types/vendor/@akanjs/native/packages/cli/src/platforms/desktop.d.ts +46 -0
- package/types/vendor/@akanjs/native/packages/cli/src/platforms/index.d.ts +14 -0
- package/types/vendor/@akanjs/native/packages/cli/src/platforms/ios.d.ts +44 -0
- package/types/vendor/@akanjs/native/packages/cli/src/platforms/linux-appimage.d.ts +11 -0
- package/types/vendor/@akanjs/native/packages/cli/src/platforms/linux.d.ts +6 -0
- package/types/vendor/@akanjs/native/packages/cli/src/platforms/macos.d.ts +12 -0
- package/types/vendor/@akanjs/native/packages/cli/src/platforms/targets.d.ts +4 -0
- package/types/vendor/@akanjs/native/packages/cli/src/platforms/web-run.d.ts +15 -0
- package/types/vendor/@akanjs/native/packages/cli/src/platforms/web.d.ts +2 -0
- package/types/vendor/@akanjs/native/packages/cli/src/platforms/windows-installer.d.ts +55 -0
- package/types/vendor/@akanjs/native/packages/cli/src/platforms/windows.d.ts +8 -0
- package/types/vendor/@akanjs/native/packages/cli/src/platforms.d.ts +1 -0
- package/types/vendor/@akanjs/native/packages/cli/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/packages/core/src/acl.d.ts +97 -0
- package/types/vendor/@akanjs/native/packages/core/src/boot.d.ts +66 -0
- package/types/vendor/@akanjs/native/packages/core/src/contract.d.ts +35 -0
- package/types/vendor/@akanjs/native/packages/core/src/errors.d.ts +27 -0
- package/types/vendor/@akanjs/native/packages/core/src/files.d.ts +23 -0
- package/types/vendor/@akanjs/native/packages/core/src/index.d.ts +14 -0
- package/types/vendor/@akanjs/native/packages/core/src/kernel.d.ts +112 -0
- package/types/vendor/@akanjs/native/packages/core/src/live.d.ts +12 -0
- package/types/vendor/@akanjs/native/packages/core/src/mime.d.ts +2 -0
- package/types/vendor/@akanjs/native/packages/core/src/plugin.d.ts +71 -0
- package/types/vendor/@akanjs/native/packages/core/src/protocol.d.ts +109 -0
- package/types/vendor/@akanjs/native/packages/core/src/runtime.d.ts +66 -0
- package/types/vendor/@akanjs/native/packages/core/src/state.d.ts +28 -0
- package/types/vendor/@akanjs/native/packages/core/src/testing.d.ts +41 -0
- package/types/vendor/@akanjs/native/packages/core/src/version.d.ts +2 -0
- package/types/vendor/@akanjs/native/packages/core/src/veto.d.ts +17 -0
- package/types/vendor/@akanjs/native/packages/core/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/packages/desktop/src/deeplinks.d.ts +24 -0
- package/types/vendor/@akanjs/native/packages/desktop/src/delta.d.ts +2 -0
- package/types/vendor/@akanjs/native/packages/desktop/src/dispatcher.d.ts +102 -0
- package/types/vendor/@akanjs/native/packages/desktop/src/ffi.d.ts +144 -0
- package/types/vendor/@akanjs/native/packages/desktop/src/grants.d.ts +11 -0
- package/types/vendor/@akanjs/native/packages/desktop/src/host.d.ts +11 -0
- package/types/vendor/@akanjs/native/packages/desktop/src/lifecycle.d.ts +40 -0
- package/types/vendor/@akanjs/native/packages/desktop/src/main.d.ts +15 -0
- package/types/vendor/@akanjs/native/packages/desktop/src/page-veto.d.ts +17 -0
- package/types/vendor/@akanjs/native/packages/desktop/src/paths.d.ts +36 -0
- package/types/vendor/@akanjs/native/packages/desktop/src/plugin.d.ts +220 -0
- package/types/vendor/@akanjs/native/packages/desktop/src/relaunch.d.ts +40 -0
- package/types/vendor/@akanjs/native/packages/desktop/src/server.d.ts +97 -0
- package/types/vendor/@akanjs/native/packages/react/src/index.d.ts +8 -0
- package/types/vendor/@akanjs/native/packages/react/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/accessibility/src/announce.d.ts +8 -0
- package/types/vendor/@akanjs/native/plugins/accessibility/src/index.d.ts +47 -0
- package/types/vendor/@akanjs/native/plugins/accessibility/src/web.d.ts +4 -0
- package/types/vendor/@akanjs/native/plugins/accessibility/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/app/src/desktop.d.ts +3 -0
- package/types/vendor/@akanjs/native/plugins/app/src/index.d.ts +95 -0
- package/types/vendor/@akanjs/native/plugins/app/src/web.d.ts +2 -0
- package/types/vendor/@akanjs/native/plugins/app/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/app-state/src/index.d.ts +25 -0
- package/types/vendor/@akanjs/native/plugins/app-state/src/web.d.ts +2 -0
- package/types/vendor/@akanjs/native/plugins/app-state/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/appearance/src/desktop.d.ts +9 -0
- package/types/vendor/@akanjs/native/plugins/appearance/src/index.d.ts +32 -0
- package/types/vendor/@akanjs/native/plugins/appearance/src/setting.d.ts +6 -0
- package/types/vendor/@akanjs/native/plugins/appearance/src/web.d.ts +3 -0
- package/types/vendor/@akanjs/native/plugins/appearance/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/auth-session/src/args.d.ts +18 -0
- package/types/vendor/@akanjs/native/plugins/auth-session/src/desktop.d.ts +17 -0
- package/types/vendor/@akanjs/native/plugins/auth-session/src/index.d.ts +41 -0
- package/types/vendor/@akanjs/native/plugins/auth-session/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/autostart/src/desktop.d.ts +44 -0
- package/types/vendor/@akanjs/native/plugins/autostart/src/index.d.ts +44 -0
- package/types/vendor/@akanjs/native/plugins/autostart/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/badge/src/count.d.ts +4 -0
- package/types/vendor/@akanjs/native/plugins/badge/src/desktop.d.ts +3 -0
- package/types/vendor/@akanjs/native/plugins/badge/src/index.d.ts +37 -0
- package/types/vendor/@akanjs/native/plugins/badge/src/web.d.ts +2 -0
- package/types/vendor/@akanjs/native/plugins/badge/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/biometric/src/index.d.ts +53 -0
- package/types/vendor/@akanjs/native/plugins/biometric/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/browser/src/args.d.ts +8 -0
- package/types/vendor/@akanjs/native/plugins/browser/src/desktop.d.ts +9 -0
- package/types/vendor/@akanjs/native/plugins/browser/src/index.d.ts +36 -0
- package/types/vendor/@akanjs/native/plugins/browser/src/web.d.ts +2 -0
- package/types/vendor/@akanjs/native/plugins/browser/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/camera/src/desktop.d.ts +5 -0
- package/types/vendor/@akanjs/native/plugins/camera/src/index.d.ts +55 -0
- package/types/vendor/@akanjs/native/plugins/camera/src/web.d.ts +2 -0
- package/types/vendor/@akanjs/native/plugins/camera/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/clipboard/src/desktop.d.ts +8 -0
- package/types/vendor/@akanjs/native/plugins/clipboard/src/index.d.ts +40 -0
- package/types/vendor/@akanjs/native/plugins/clipboard/src/web.d.ts +2 -0
- package/types/vendor/@akanjs/native/plugins/clipboard/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/contacts/src/index.d.ts +43 -0
- package/types/vendor/@akanjs/native/plugins/contacts/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/device/src/desktop.d.ts +33 -0
- package/types/vendor/@akanjs/native/plugins/device/src/index.d.ts +55 -0
- package/types/vendor/@akanjs/native/plugins/device/src/web.d.ts +22 -0
- package/types/vendor/@akanjs/native/plugins/device/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/dialog/src/desktop.d.ts +3 -0
- package/types/vendor/@akanjs/native/plugins/dialog/src/index.d.ts +60 -0
- package/types/vendor/@akanjs/native/plugins/dialog/src/options.d.ts +29 -0
- package/types/vendor/@akanjs/native/plugins/dialog/src/web.d.ts +2 -0
- package/types/vendor/@akanjs/native/plugins/dialog/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/dock/src/desktop.d.ts +3 -0
- package/types/vendor/@akanjs/native/plugins/dock/src/index.d.ts +46 -0
- package/types/vendor/@akanjs/native/plugins/dock/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/file-picker/src/common.d.ts +33 -0
- package/types/vendor/@akanjs/native/plugins/file-picker/src/desktop.d.ts +9 -0
- package/types/vendor/@akanjs/native/plugins/file-picker/src/index.d.ts +103 -0
- package/types/vendor/@akanjs/native/plugins/file-picker/src/web.d.ts +6 -0
- package/types/vendor/@akanjs/native/plugins/file-picker/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/filesystem/src/common.d.ts +49 -0
- package/types/vendor/@akanjs/native/plugins/filesystem/src/desktop.d.ts +8 -0
- package/types/vendor/@akanjs/native/plugins/filesystem/src/index.d.ts +123 -0
- package/types/vendor/@akanjs/native/plugins/filesystem/src/web.d.ts +2 -0
- package/types/vendor/@akanjs/native/plugins/filesystem/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/geolocation/src/index.d.ts +93 -0
- package/types/vendor/@akanjs/native/plugins/geolocation/src/web.d.ts +11 -0
- package/types/vendor/@akanjs/native/plugins/geolocation/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/global-shortcut/src/desktop.d.ts +3 -0
- package/types/vendor/@akanjs/native/plugins/global-shortcut/src/index.d.ts +52 -0
- package/types/vendor/@akanjs/native/plugins/global-shortcut/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/haptics/src/index.d.ts +31 -0
- package/types/vendor/@akanjs/native/plugins/haptics/src/web.d.ts +2 -0
- package/types/vendor/@akanjs/native/plugins/haptics/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/http/src/common.d.ts +71 -0
- package/types/vendor/@akanjs/native/plugins/http/src/desktop.d.ts +5 -0
- package/types/vendor/@akanjs/native/plugins/http/src/index.d.ts +104 -0
- package/types/vendor/@akanjs/native/plugins/http/src/web.d.ts +2 -0
- package/types/vendor/@akanjs/native/plugins/http/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/iap/src/index.d.ts +171 -0
- package/types/vendor/@akanjs/native/plugins/iap/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/keep-awake/src/desktop.d.ts +15 -0
- package/types/vendor/@akanjs/native/plugins/keep-awake/src/index.d.ts +33 -0
- package/types/vendor/@akanjs/native/plugins/keep-awake/src/web.d.ts +2 -0
- package/types/vendor/@akanjs/native/plugins/keep-awake/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/keyboard/src/index.d.ts +42 -0
- package/types/vendor/@akanjs/native/plugins/keyboard/src/web.d.ts +2 -0
- package/types/vendor/@akanjs/native/plugins/keyboard/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/local-notifications/src/desktop.d.ts +29 -0
- package/types/vendor/@akanjs/native/plugins/local-notifications/src/index.d.ts +126 -0
- package/types/vendor/@akanjs/native/plugins/local-notifications/src/schedule.d.ts +38 -0
- package/types/vendor/@akanjs/native/plugins/local-notifications/src/timers.d.ts +25 -0
- package/types/vendor/@akanjs/native/plugins/local-notifications/src/web.d.ts +4 -0
- package/types/vendor/@akanjs/native/plugins/local-notifications/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/menu/src/desktop.d.ts +3 -0
- package/types/vendor/@akanjs/native/plugins/menu/src/index.d.ts +85 -0
- package/types/vendor/@akanjs/native/plugins/menu/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/network/src/index.d.ts +22 -0
- package/types/vendor/@akanjs/native/plugins/network/src/web.d.ts +3 -0
- package/types/vendor/@akanjs/native/plugins/network/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/opener/src/desktop.d.ts +14 -0
- package/types/vendor/@akanjs/native/plugins/opener/src/index.d.ts +33 -0
- package/types/vendor/@akanjs/native/plugins/opener/src/url.d.ts +16 -0
- package/types/vendor/@akanjs/native/plugins/opener/src/web.d.ts +2 -0
- package/types/vendor/@akanjs/native/plugins/opener/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/preferences/src/desktop.d.ts +3 -0
- package/types/vendor/@akanjs/native/plugins/preferences/src/index.d.ts +26 -0
- package/types/vendor/@akanjs/native/plugins/preferences/src/web.d.ts +2 -0
- package/types/vendor/@akanjs/native/plugins/preferences/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/push/src/index.d.ts +66 -0
- package/types/vendor/@akanjs/native/plugins/push/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/screen/src/desktop.d.ts +3 -0
- package/types/vendor/@akanjs/native/plugins/screen/src/index.d.ts +70 -0
- package/types/vendor/@akanjs/native/plugins/screen/src/web.d.ts +18 -0
- package/types/vendor/@akanjs/native/plugins/screen/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/screen-orientation/src/index.d.ts +32 -0
- package/types/vendor/@akanjs/native/plugins/screen-orientation/src/types.d.ts +8 -0
- package/types/vendor/@akanjs/native/plugins/screen-orientation/src/web.d.ts +3 -0
- package/types/vendor/@akanjs/native/plugins/screen-orientation/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/secure-storage/src/desktop.d.ts +16 -0
- package/types/vendor/@akanjs/native/plugins/secure-storage/src/index.d.ts +39 -0
- package/types/vendor/@akanjs/native/plugins/secure-storage/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/share/src/index.d.ts +55 -0
- package/types/vendor/@akanjs/native/plugins/share/src/options.d.ts +6 -0
- package/types/vendor/@akanjs/native/plugins/share/src/web.d.ts +5 -0
- package/types/vendor/@akanjs/native/plugins/share/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/single-instance/src/desktop.d.ts +8 -0
- package/types/vendor/@akanjs/native/plugins/single-instance/src/index.d.ts +25 -0
- package/types/vendor/@akanjs/native/plugins/single-instance/src/socket.d.ts +46 -0
- package/types/vendor/@akanjs/native/plugins/single-instance/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/splash-screen/src/index.d.ts +19 -0
- package/types/vendor/@akanjs/native/plugins/splash-screen/src/web.d.ts +4 -0
- package/types/vendor/@akanjs/native/plugins/splash-screen/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/sqlite/src/common.d.ts +34 -0
- package/types/vendor/@akanjs/native/plugins/sqlite/src/desktop.d.ts +6 -0
- package/types/vendor/@akanjs/native/plugins/sqlite/src/index.d.ts +115 -0
- package/types/vendor/@akanjs/native/plugins/sqlite/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/toast/src/index.d.ts +30 -0
- package/types/vendor/@akanjs/native/plugins/toast/src/queue.d.ts +23 -0
- package/types/vendor/@akanjs/native/plugins/toast/src/web.d.ts +2 -0
- package/types/vendor/@akanjs/native/plugins/toast/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/tray/src/desktop.d.ts +3 -0
- package/types/vendor/@akanjs/native/plugins/tray/src/index.d.ts +113 -0
- package/types/vendor/@akanjs/native/plugins/tray/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/updates/src/desktop.d.ts +38 -0
- package/types/vendor/@akanjs/native/plugins/updates/src/index.d.ts +80 -0
- package/types/vendor/@akanjs/native/plugins/updates/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/volume/src/common.d.ts +10 -0
- package/types/vendor/@akanjs/native/plugins/volume/src/desktop.d.ts +18 -0
- package/types/vendor/@akanjs/native/plugins/volume/src/index.d.ts +28 -0
- package/types/vendor/@akanjs/native/plugins/volume/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/window/src/desktop.d.ts +6 -0
- package/types/vendor/@akanjs/native/plugins/window/src/index.d.ts +185 -0
- package/types/vendor/@akanjs/native/plugins/window/src/web.d.ts +2 -0
- package/types/vendor/@akanjs/native/plugins/window/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/window-state/src/desktop.d.ts +7 -0
- package/types/vendor/@akanjs/native/plugins/window-state/src/index.d.ts +33 -0
- package/types/vendor/@akanjs/native/plugins/window-state/src/state.d.ts +39 -0
- package/types/vendor/@akanjs/native/plugins/window-state/src.d.ts +1 -0
- package/types/vendor/use-agentic/AgentActivity.d.ts +11 -0
- package/types/vendor/use-agentic/AgentGate.d.ts +10 -0
- package/types/vendor/use-agentic/AgentProgress.d.ts +12 -0
- package/types/vendor/use-agentic/AgentProvider.d.ts +1 -1
- package/types/vendor/use-agentic/AgentScope.d.ts +1 -1
- package/types/vendor/use-agentic/AgentSession.d.ts +41 -2
- package/types/vendor/use-agentic/AgenticSurface.d.ts +15 -5
- package/types/vendor/use-agentic/Compaction.d.ts +42 -5
- package/types/vendor/use-agentic/ToolRunner.d.ts +31 -1
- package/types/vendor/use-agentic/Transcript.d.ts +2 -0
- package/types/vendor/use-agentic/index.d.ts +2 -0
- package/types/vendor/use-agentic/surfaceContext.d.ts +3 -0
- package/types/vendor/use-agentic/types.d.ts +73 -1
- package/types/webkit/CsrRouteTable.d.ts +32 -0
- package/types/webkit/CsrStack.d.ts +45 -0
- package/types/webkit/RenderLayer.d.ts +11 -0
- package/types/webkit/bootCsr.d.ts +7 -8
- package/types/webkit/csrFrameDump.d.ts +42 -0
- package/types/webkit/index.d.ts +5 -5
- package/types/webkit/lazy.d.ts +3 -12
- package/types/webkit/nativeNavigation.d.ts +39 -0
- package/types/webkit/nativePurchase.d.ts +41 -0
- package/types/webkit/nativeUpdates.d.ts +8 -0
- package/types/webkit/seoPages.d.ts +19 -0
- package/types/webkit/useBodyScrollLock.d.ts +0 -1
- package/types/webkit/useCamera.d.ts +13 -15
- package/types/webkit/useCsrValues.d.ts +6 -4
- package/types/webkit/useDebounce.d.ts +0 -1
- package/types/webkit/useEscapeKey.d.ts +1 -4
- package/types/webkit/useFetch.d.ts +4 -7
- package/types/webkit/useFrameRuntime.d.ts +1 -2
- package/types/webkit/useGeoLocation.d.ts +5 -6
- package/types/webkit/useHistory.d.ts +5 -1
- package/types/webkit/usePageActivity.d.ts +2 -0
- package/types/webkit/usePageFocusEffect.d.ts +7 -0
- package/types/webkit/usePageLocation.d.ts +13 -0
- package/types/webkit/usePageTool.d.ts +2 -9
- package/types/webkit/usePurchase.d.ts +12 -19
- package/types/webkit/useScreenScope.d.ts +2 -13
- package/ui/Agent/Attach.tsx +8 -4
- package/ui/Agent/Bubble.tsx +49 -31
- package/ui/Agent/Chat.tsx +91 -115
- package/ui/Agent/ChatCommands.ts +5 -21
- package/ui/Agent/Composer.tsx +97 -32
- package/ui/Agent/Dock.tsx +176 -16
- package/ui/Agent/Guide.tsx +1 -5
- package/ui/Agent/History.tsx +1 -18
- package/ui/Agent/Launcher.tsx +2 -2
- package/ui/Agent/Markdown.tsx +40 -14
- package/ui/Agent/MentionNode.ts +54 -0
- package/ui/Agent/Menu.tsx +2 -4
- package/ui/Agent/Question.tsx +1 -6
- package/ui/Agent/Queued.tsx +1 -6
- package/ui/Agent/Refer.tsx +1 -5
- package/ui/Agent/RichInput.tsx +146 -0
- package/ui/Agent/Skip.tsx +3 -15
- package/ui/Agent/Steps.tsx +33 -0
- package/ui/Agent/ToolCard.tsx +32 -0
- package/ui/Agent/Zone.tsx +15 -31
- package/ui/Agent/agentSessionOf.ts +115 -15
- package/ui/Agent/attachment.ts +5 -42
- package/ui/Agent/fetchRunner.ts +3 -15
- package/ui/Agent/index.ts +1 -6
- package/ui/Agent/mentionDraft.ts +91 -0
- package/ui/Agent/tokenCount.ts +1 -5
- package/ui/Agent/useChatAttachments.ts +2 -9
- package/ui/Agent/useChatQueue.ts +3 -15
- package/ui/Agent/useChatReferences.ts +6 -22
- package/ui/Agent/useChatVoice.ts +2 -23
- package/ui/Agent/useDraftRecall.ts +0 -9
- package/ui/Agent/useKeyboardInset.ts +0 -7
- package/ui/Agent/useReferenceMenu.ts +4 -19
- package/ui/Agent/useSlashMenu.ts +0 -3
- package/ui/Agent/voice.ts +8 -43
- package/ui/Badge.tsx +0 -2
- package/ui/BottomSheet.tsx +2 -5
- package/ui/Button.tsx +9 -45
- package/ui/ClientSide.tsx +0 -2
- package/ui/Clipboard.tsx +0 -1
- package/ui/Constant/Doc.tsx +274 -265
- package/ui/Constant/Graph.tsx +11 -3
- package/ui/Constant/schemaGraph.ts +0 -9
- package/ui/Copy.tsx +2 -3
- package/ui/CsrImage.tsx +10 -9
- package/ui/Data/CardList.tsx +2 -17
- package/ui/Data/Dashboard.tsx +4 -7
- package/ui/Data/Item.tsx +8 -6
- package/ui/Data/ListContainer.tsx +17 -63
- package/ui/Data/Pagination.tsx +3 -22
- package/ui/Data/QueryMaker.tsx +1 -8
- package/ui/Data/RefPicker.tsx +1 -8
- package/ui/Data/TableList.tsx +2 -15
- package/ui/DatePicker.tsx +1 -12
- package/ui/Dialog/LegacyModal.tsx +3 -7
- package/ui/Dialog/Modal.tsx +3 -4
- package/ui/Dialog/Provider.tsx +85 -7
- package/ui/Dialog/index.tsx +1 -5
- package/ui/DraggableList.tsx +1 -4
- package/ui/Dropdown.tsx +4 -17
- package/ui/Empty.tsx +4 -12
- package/ui/Field/Choice.tsx +1 -1
- package/ui/Field/Collection.tsx +7 -29
- package/ui/Field/DateField.tsx +2 -7
- package/ui/Field/Label.tsx +0 -1
- package/ui/Field/NumberField.tsx +0 -1
- package/ui/Field/Relation.tsx +13 -53
- package/ui/Field/Text.tsx +25 -86
- package/ui/Field/index.tsx +0 -9
- package/ui/Field/lightRefCache.ts +1 -13
- package/ui/Field/useRelationOptions.ts +4 -13
- package/ui/Image.tsx +35 -65
- package/ui/InfiniteScroll.tsx +3 -21
- package/ui/Input.tsx +82 -174
- package/ui/Layout/BottomInset.tsx +1 -1
- package/ui/Layout/Navbar.tsx +1 -1
- package/ui/Layout/Role.tsx +42 -0
- package/ui/Layout/Sider.tsx +82 -1
- package/ui/Layout/TopInset.tsx +25 -2
- package/ui/Layout/index.ts +3 -9
- package/ui/LegacyModal.tsx +1 -12
- package/ui/Link/Action.tsx +29 -0
- package/ui/Link/Anchor.tsx +115 -0
- package/ui/Link/index.tsx +7 -8
- package/ui/Load/Edit_Client.tsx +2 -37
- package/ui/Load/Page.tsx +3 -6
- package/ui/Load/Pagination.tsx +4 -19
- package/ui/Load/Stream.tsx +0 -12
- package/ui/Load/Units.tsx +13 -86
- package/ui/Load/View.tsx +4 -21
- package/ui/Loading/ProgressBar.tsx +0 -4
- package/ui/Loading/Skeleton.tsx +14 -0
- package/ui/Loading/Spin.tsx +24 -15
- package/ui/Loading/index.ts +0 -5
- package/ui/Loading/index_.tsx +2 -12
- package/ui/Menu.tsx +3 -21
- package/ui/Modal.tsx +0 -17
- package/ui/Model/AdminPanel.tsx +2 -5
- package/ui/Model/DraftBar.tsx +3 -14
- package/ui/Model/EditModal.tsx +11 -48
- package/ui/Model/EditWrapper.tsx +2 -3
- package/ui/Model/LoadStore.tsx +18 -0
- package/ui/Model/NewWrapper_Client.tsx +1 -1
- package/ui/Model/Remove.tsx +4 -12
- package/ui/Model/RemoveWrapper.tsx +2 -3
- package/ui/Model/SureToRemove.tsx +4 -13
- package/ui/Model/ViewEditModal.tsx +0 -6
- package/ui/Model/ViewModal.tsx +1 -5
- package/ui/Model/ViewWrapper.tsx +1 -2
- package/ui/Model/draftScope.ts +0 -7
- package/ui/Model/index_.tsx +2 -22
- package/ui/Pagination.tsx +4 -12
- package/ui/Popconfirm.tsx +3 -18
- package/ui/Portal.tsx +2 -3
- package/ui/Radio.tsx +1 -5
- package/ui/RecentTime.tsx +19 -31
- package/ui/Reference/Panel.tsx +102 -6
- package/ui/Reference/Segmented.tsx +5 -11
- package/ui/Reference/docUi.ts +53 -0
- package/ui/Reference/index.ts +3 -7
- package/ui/Refresh.tsx +79 -13
- package/ui/ScreenNavigator.tsx +8 -13
- package/ui/Select.tsx +7 -25
- package/ui/Signal/Endpoint.tsx +154 -0
- package/ui/Signal/Listener.tsx +1 -4
- package/ui/Signal/Object.tsx +67 -73
- package/ui/Signal/RestApi.tsx +30 -76
- package/ui/Signal/WebSocket.tsx +253 -2
- package/ui/Signal/endpointEntries.ts +3 -5
- package/ui/Signal/index.ts +1 -3
- package/ui/Signal/style.ts +1 -2
- package/ui/Switch.tsx +1 -5
- package/ui/System/CSR.tsx +52 -167
- package/ui/System/Client.tsx +54 -54
- package/ui/System/Common.tsx +31 -22
- package/ui/System/Messages.tsx +2 -2
- package/ui/System/Reconnect.tsx +1 -6
- package/ui/System/Root.tsx +1 -4
- package/ui/System/SSR.tsx +11 -17
- package/ui/System/ThemeToggle.tsx +15 -0
- package/ui/System/index.tsx +2 -2
- package/ui/Tab/Provider.tsx +115 -7
- package/ui/Tab/index.tsx +1 -4
- package/ui/Table.tsx +7 -23
- package/ui/Toast.tsx +9 -16
- package/ui/ToggleSelect.tsx +10 -24
- package/ui/Tooltip.tsx +2 -8
- package/ui/UiOverride/UiOverride.tsx +155 -0
- package/ui/UiOverride/index.ts +9 -6
- package/ui/UiOverride/override.ts +2 -18
- package/ui/Unauthorized.tsx +1 -8
- package/ui/agentAttrs.ts +9 -12
- package/ui/index.ts +10 -5
- package/ui/overlayLayer.ts +4 -25
- package/ui/overlayPosition.ts +2 -14
- package/ui/recipe/badgeRecipe.ts +1 -1
- package/ui/recipe/buttonRecipe.ts +4 -4
- package/ui/recipe/factory.ts +1 -22
- package/ui/recipe/index.ts +1 -14
- package/ui/recipe/inputRecipe.ts +2 -2
- package/ui/sliceNamesOf.ts +26 -0
- package/ui/styles.css +195 -1
- package/ui/triggerSlot.tsx +2 -12
- package/vendor/@akanjs/native/LICENSE +21 -0
- package/vendor/@akanjs/native/README.ko.md +88 -0
- package/vendor/@akanjs/native/README.md +93 -0
- package/vendor/@akanjs/native/THIRD_PARTY_NOTICES.md +237 -0
- package/vendor/@akanjs/native/native/android/maven.lock.json +1751 -0
- package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativeAcl.kt +243 -0
- package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativeActivity.kt +984 -0
- package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativeApplication.kt +189 -0
- package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativeAssetServer.kt +225 -0
- package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativeBridge.kt +463 -0
- package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativeCompat.kt +55 -0
- package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativeContract.kt +99 -0
- package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativeEd25519.kt +100 -0
- package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativeFileProvider.kt +71 -0
- package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativeKernel.kt +324 -0
- package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativePlugin.kt +377 -0
- package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativeSpec.kt +100 -0
- package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativeUpdates.kt +305 -0
- package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativeVectors.kt +132 -0
- package/vendor/@akanjs/native/native/desktop/Cargo.lock +2565 -0
- package/vendor/@akanjs/native/native/desktop/Cargo.toml +49 -0
- package/vendor/@akanjs/native/native/desktop/build.rs +19 -0
- package/vendor/@akanjs/native/native/desktop/rust-toolchain.toml +7 -0
- package/vendor/@akanjs/native/native/desktop/src/accelerator.rs +466 -0
- package/vendor/@akanjs/native/native/desktop/src/autostart.rs +158 -0
- package/vendor/@akanjs/native/native/desktop/src/camera.rs +53 -0
- package/vendor/@akanjs/native/native/desktop/src/chrome.rs +710 -0
- package/vendor/@akanjs/native/native/desktop/src/contract.rs +105 -0
- package/vendor/@akanjs/native/native/desktop/src/devproxy.rs +234 -0
- package/vendor/@akanjs/native/native/desktop/src/dialog_args.rs +189 -0
- package/vendor/@akanjs/native/native/desktop/src/dock.rs +209 -0
- package/vendor/@akanjs/native/native/desktop/src/hotkey.rs +209 -0
- package/vendor/@akanjs/native/native/desktop/src/js_panels.rs +125 -0
- package/vendor/@akanjs/native/native/desktop/src/json.rs +272 -0
- package/vendor/@akanjs/native/native/desktop/src/keychain.rs +151 -0
- package/vendor/@akanjs/native/native/desktop/src/lib.rs +2321 -0
- package/vendor/@akanjs/native/native/desktop/src/linux/appearance.rs +177 -0
- package/vendor/@akanjs/native/native/desktop/src/linux/camera.rs +11 -0
- package/vendor/@akanjs/native/native/desktop/src/linux/clipboard.rs +48 -0
- package/vendor/@akanjs/native/native/desktop/src/linux/device.rs +9 -0
- package/vendor/@akanjs/native/native/desktop/src/linux/dialogs.rs +348 -0
- package/vendor/@akanjs/native/native/desktop/src/linux/dock.rs +146 -0
- package/vendor/@akanjs/native/native/desktop/src/linux/hotkey.rs +228 -0
- package/vendor/@akanjs/native/native/desktop/src/linux/keychain.rs +243 -0
- package/vendor/@akanjs/native/native/desktop/src/linux/menu.rs +445 -0
- package/vendor/@akanjs/native/native/desktop/src/linux/mod.rs +116 -0
- package/vendor/@akanjs/native/native/desktop/src/linux/notify.rs +211 -0
- package/vendor/@akanjs/native/native/desktop/src/linux/open.rs +79 -0
- package/vendor/@akanjs/native/native/desktop/src/linux/power.rs +155 -0
- package/vendor/@akanjs/native/native/desktop/src/linux/screen.rs +158 -0
- package/vendor/@akanjs/native/native/desktop/src/linux/tray.rs +604 -0
- package/vendor/@akanjs/native/native/desktop/src/menu.rs +517 -0
- package/vendor/@akanjs/native/native/desktop/src/navigation.rs +381 -0
- package/vendor/@akanjs/native/native/desktop/src/notify.rs +411 -0
- package/vendor/@akanjs/native/native/desktop/src/notify_schedule.rs +382 -0
- package/vendor/@akanjs/native/native/desktop/src/page_menu.rs +287 -0
- package/vendor/@akanjs/native/native/desktop/src/panels.rs +333 -0
- package/vendor/@akanjs/native/native/desktop/src/placement.rs +92 -0
- package/vendor/@akanjs/native/native/desktop/src/routes.rs +153 -0
- package/vendor/@akanjs/native/native/desktop/src/screen.rs +190 -0
- package/vendor/@akanjs/native/native/desktop/src/tray.rs +279 -0
- package/vendor/@akanjs/native/native/desktop/src/vectors.rs +126 -0
- package/vendor/@akanjs/native/native/desktop/src/volume.rs +184 -0
- package/vendor/@akanjs/native/native/desktop/src/win/appearance.rs +51 -0
- package/vendor/@akanjs/native/native/desktop/src/win/autostart.rs +77 -0
- package/vendor/@akanjs/native/native/desktop/src/win/camera.rs +34 -0
- package/vendor/@akanjs/native/native/desktop/src/win/clipboard.rs +106 -0
- package/vendor/@akanjs/native/native/desktop/src/win/device.rs +80 -0
- package/vendor/@akanjs/native/native/desktop/src/win/dialogs.rs +917 -0
- package/vendor/@akanjs/native/native/desktop/src/win/dock.rs +228 -0
- package/vendor/@akanjs/native/native/desktop/src/win/hotkey.rs +110 -0
- package/vendor/@akanjs/native/native/desktop/src/win/keychain.rs +103 -0
- package/vendor/@akanjs/native/native/desktop/src/win/menu.rs +500 -0
- package/vendor/@akanjs/native/native/desktop/src/win/mod.rs +102 -0
- package/vendor/@akanjs/native/native/desktop/src/win/msgwin.rs +86 -0
- package/vendor/@akanjs/native/native/desktop/src/win/notify.rs +334 -0
- package/vendor/@akanjs/native/native/desktop/src/win/open.rs +127 -0
- package/vendor/@akanjs/native/native/desktop/src/win/power.rs +64 -0
- package/vendor/@akanjs/native/native/desktop/src/win/registry.rs +87 -0
- package/vendor/@akanjs/native/native/desktop/src/win/screen.rs +127 -0
- package/vendor/@akanjs/native/native/desktop/src/win/tray.rs +280 -0
- package/vendor/@akanjs/native/native/desktop/src/win/volume.rs +71 -0
- package/vendor/@akanjs/native/native/ios/Sources/AkanNativeAcl.swift +241 -0
- package/vendor/@akanjs/native/native/ios/Sources/AkanNativeApp.swift +285 -0
- package/vendor/@akanjs/native/native/ios/Sources/AkanNativeBridge.swift +407 -0
- package/vendor/@akanjs/native/native/ios/Sources/AkanNativeContract.swift +106 -0
- package/vendor/@akanjs/native/native/ios/Sources/AkanNativeKernel.swift +317 -0
- package/vendor/@akanjs/native/native/ios/Sources/AkanNativePlugin.swift +250 -0
- package/vendor/@akanjs/native/native/ios/Sources/AkanNativeSchemeHandler.swift +209 -0
- package/vendor/@akanjs/native/native/ios/Sources/AkanNativeShell.swift +171 -0
- package/vendor/@akanjs/native/native/ios/Sources/AkanNativeSpec.swift +143 -0
- package/vendor/@akanjs/native/native/ios/Sources/AkanNativeUpdates.swift +270 -0
- package/vendor/@akanjs/native/native/ios/Sources/AkanNativeVectors.swift +155 -0
- package/vendor/@akanjs/native/native/ios/Sources/AkanNativeViewController.swift +371 -0
- package/vendor/@akanjs/native/packages/cli/src/api.ts +796 -0
- package/vendor/@akanjs/native/packages/cli/src/commands/build.ts +137 -0
- package/vendor/@akanjs/native/packages/cli/src/commands/compat.ts +53 -0
- package/vendor/@akanjs/native/packages/cli/src/commands/dev.ts +249 -0
- package/vendor/@akanjs/native/packages/cli/src/commands/doctor.ts +536 -0
- package/vendor/@akanjs/native/packages/cli/src/commands/plugin.ts +164 -0
- package/vendor/@akanjs/native/packages/cli/src/commands/signing.ts +32 -0
- package/vendor/@akanjs/native/packages/cli/src/commands/test.ts +130 -0
- package/vendor/@akanjs/native/packages/cli/src/commands/toolchain.ts +143 -0
- package/vendor/@akanjs/native/packages/cli/src/commands/update.ts +114 -0
- package/vendor/@akanjs/native/packages/cli/src/config.ts +305 -0
- package/vendor/@akanjs/native/packages/cli/src/index.ts +77 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/acl.ts +420 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/addons.ts +218 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/apilevel.ts +245 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/apk.ts +203 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/args.ts +44 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/boot.ts +73 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/chrome.ts +89 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/codegen.ts +1128 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/compat.ts +185 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/configkeys.ts +99 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/csp.ts +198 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/desktop-server.ts +58 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/env.ts +257 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/exec.ts +114 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/googleservices.ts +53 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/hmr.ts +536 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/html.ts +63 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/icons.ts +316 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/image.ts +175 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/iossigning.ts +295 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/launch.ts +98 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/log.ts +105 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/macossigning.ts +357 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/manifestmerge.ts +107 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/maven.ts +244 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/names.ts +202 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/native-plugins.ts +326 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/nativeconfig.ts +68 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/permissions.ts +80 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/plist.ts +139 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/png.ts +240 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/prepare.ts +331 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/privacy.ts +64 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/project.ts +747 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/publish.ts +121 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/root.ts +18 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/routes.ts +3 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/serve.ts +83 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/signing.ts +118 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/spec.ts +521 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/toolchains.ts +603 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/updates.ts +242 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/vectors.ts +121 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/windowssigning.ts +155 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/xml.ts +72 -0
- package/vendor/@akanjs/native/packages/cli/src/platforms/android.ts +1321 -0
- package/vendor/@akanjs/native/packages/cli/src/platforms/desktop-update.ts +105 -0
- package/vendor/@akanjs/native/packages/cli/src/platforms/desktop.ts +312 -0
- package/vendor/@akanjs/native/packages/cli/src/platforms/index.ts +31 -0
- package/vendor/@akanjs/native/packages/cli/src/platforms/ios.ts +801 -0
- package/vendor/@akanjs/native/packages/cli/src/platforms/linux-appimage.ts +84 -0
- package/vendor/@akanjs/native/packages/cli/src/platforms/linux.ts +55 -0
- package/vendor/@akanjs/native/packages/cli/src/platforms/macos.ts +212 -0
- package/vendor/@akanjs/native/packages/cli/src/platforms/targets.ts +12 -0
- package/vendor/@akanjs/native/packages/cli/src/platforms/web-run.ts +69 -0
- package/vendor/@akanjs/native/packages/cli/src/platforms/web.ts +28 -0
- package/vendor/@akanjs/native/packages/cli/src/platforms/windows-installer.ts +628 -0
- package/vendor/@akanjs/native/packages/cli/src/platforms/windows.ts +95 -0
- package/vendor/@akanjs/native/packages/core/contract.json +96 -0
- package/vendor/@akanjs/native/packages/core/src/acl.ts +272 -0
- package/vendor/@akanjs/native/packages/core/src/boot.ts +97 -0
- package/vendor/@akanjs/native/packages/core/src/contract.ts +100 -0
- package/vendor/@akanjs/native/packages/core/src/errors.ts +95 -0
- package/vendor/@akanjs/native/packages/core/src/files.ts +105 -0
- package/vendor/@akanjs/native/packages/core/src/index.ts +35 -0
- package/vendor/@akanjs/native/packages/core/src/kernel.ts +281 -0
- package/vendor/@akanjs/native/packages/core/src/live.ts +62 -0
- package/vendor/@akanjs/native/packages/core/src/mime.ts +8 -0
- package/vendor/@akanjs/native/packages/core/src/plugin.ts +358 -0
- package/vendor/@akanjs/native/packages/core/src/protocol.ts +194 -0
- package/vendor/@akanjs/native/packages/core/src/runtime.ts +541 -0
- package/vendor/@akanjs/native/packages/core/src/state.ts +46 -0
- package/vendor/@akanjs/native/packages/core/src/testing.ts +176 -0
- package/vendor/@akanjs/native/packages/core/src/version.ts +2 -0
- package/vendor/@akanjs/native/packages/core/src/veto.ts +55 -0
- package/vendor/@akanjs/native/packages/core/vectors/acl.json +57 -0
- package/vendor/@akanjs/native/packages/core/vectors/bridge.json +76 -0
- package/vendor/@akanjs/native/packages/core/vectors/ed25519.json +29 -0
- package/vendor/@akanjs/native/packages/core/vectors/ids.json +73 -0
- package/vendor/@akanjs/native/packages/core/vectors/navigation.json +75 -0
- package/vendor/@akanjs/native/packages/core/vectors/ranges.json +39 -0
- package/vendor/@akanjs/native/packages/core/vectors/retained.json +17 -0
- package/vendor/@akanjs/native/packages/core/vectors/routes.json +66 -0
- package/vendor/@akanjs/native/packages/core/vectors/scope.json +143 -0
- package/vendor/@akanjs/native/packages/desktop/src/deeplinks.ts +143 -0
- package/vendor/@akanjs/native/packages/desktop/src/delta.ts +174 -0
- package/vendor/@akanjs/native/packages/desktop/src/dispatcher.ts +706 -0
- package/vendor/@akanjs/native/packages/desktop/src/ffi.ts +76 -0
- package/vendor/@akanjs/native/packages/desktop/src/grants.ts +47 -0
- package/vendor/@akanjs/native/packages/desktop/src/host.ts +455 -0
- package/vendor/@akanjs/native/packages/desktop/src/lifecycle.ts +142 -0
- package/vendor/@akanjs/native/packages/desktop/src/main.ts +181 -0
- package/vendor/@akanjs/native/packages/desktop/src/page-veto.ts +103 -0
- package/vendor/@akanjs/native/packages/desktop/src/paths.ts +93 -0
- package/vendor/@akanjs/native/packages/desktop/src/plugin.ts +275 -0
- package/vendor/@akanjs/native/packages/desktop/src/relaunch.ts +236 -0
- package/vendor/@akanjs/native/packages/desktop/src/server.ts +610 -0
- package/vendor/@akanjs/native/packages/react/src/index.ts +23 -0
- package/vendor/@akanjs/native/plugins/accessibility/android/AccessibilityPlugin.kt +96 -0
- package/vendor/@akanjs/native/plugins/accessibility/ios/AccessibilityPlugin.swift +92 -0
- package/vendor/@akanjs/native/plugins/accessibility/native-plugin.json +21 -0
- package/vendor/@akanjs/native/plugins/accessibility/src/announce.ts +71 -0
- package/vendor/@akanjs/native/plugins/accessibility/src/index.ts +77 -0
- package/vendor/@akanjs/native/plugins/accessibility/src/web.ts +52 -0
- package/vendor/@akanjs/native/plugins/app/android/AppPlugin.kt +106 -0
- package/vendor/@akanjs/native/plugins/app/ios/AppPlugin.swift +52 -0
- package/vendor/@akanjs/native/plugins/app/native-plugin.json +21 -0
- package/vendor/@akanjs/native/plugins/app/src/desktop.ts +77 -0
- package/vendor/@akanjs/native/plugins/app/src/index.ts +99 -0
- package/vendor/@akanjs/native/plugins/app/src/web.ts +15 -0
- package/vendor/@akanjs/native/plugins/app-state/android/AppStatePlugin.kt +90 -0
- package/vendor/@akanjs/native/plugins/app-state/ios/AppStatePlugin.swift +77 -0
- package/vendor/@akanjs/native/plugins/app-state/native-plugin.json +17 -0
- package/vendor/@akanjs/native/plugins/app-state/src/index.ts +47 -0
- package/vendor/@akanjs/native/plugins/app-state/src/web.ts +33 -0
- package/vendor/@akanjs/native/plugins/appearance/android/AppearancePlugin.kt +133 -0
- package/vendor/@akanjs/native/plugins/appearance/ios/AppearancePlugin.swift +109 -0
- package/vendor/@akanjs/native/plugins/appearance/native-plugin.json +18 -0
- package/vendor/@akanjs/native/plugins/appearance/src/desktop.ts +133 -0
- package/vendor/@akanjs/native/plugins/appearance/src/index.ts +62 -0
- package/vendor/@akanjs/native/plugins/appearance/src/setting.ts +18 -0
- package/vendor/@akanjs/native/plugins/appearance/src/web.ts +25 -0
- package/vendor/@akanjs/native/plugins/auth-session/android/AuthSessionPlugin.kt +171 -0
- package/vendor/@akanjs/native/plugins/auth-session/ios/AuthSessionPlugin.swift +112 -0
- package/vendor/@akanjs/native/plugins/auth-session/native-plugin.json +19 -0
- package/vendor/@akanjs/native/plugins/auth-session/src/args.ts +62 -0
- package/vendor/@akanjs/native/plugins/auth-session/src/desktop.ts +133 -0
- package/vendor/@akanjs/native/plugins/auth-session/src/index.ts +39 -0
- package/vendor/@akanjs/native/plugins/autostart/native-plugin.json +10 -0
- package/vendor/@akanjs/native/plugins/autostart/src/desktop.ts +189 -0
- package/vendor/@akanjs/native/plugins/autostart/src/index.ts +51 -0
- package/vendor/@akanjs/native/plugins/badge/ios/BadgePlugin.swift +92 -0
- package/vendor/@akanjs/native/plugins/badge/native-plugin.json +15 -0
- package/vendor/@akanjs/native/plugins/badge/src/count.ts +12 -0
- package/vendor/@akanjs/native/plugins/badge/src/desktop.ts +24 -0
- package/vendor/@akanjs/native/plugins/badge/src/index.ts +40 -0
- package/vendor/@akanjs/native/plugins/badge/src/web.ts +37 -0
- package/vendor/@akanjs/native/plugins/biometric/android/BiometricPlugin.kt +179 -0
- package/vendor/@akanjs/native/plugins/biometric/ios/BiometricPlugin.swift +129 -0
- package/vendor/@akanjs/native/plugins/biometric/native-plugin.json +22 -0
- package/vendor/@akanjs/native/plugins/biometric/src/index.ts +100 -0
- package/vendor/@akanjs/native/plugins/browser/android/BrowserPlugin.kt +178 -0
- package/vendor/@akanjs/native/plugins/browser/ios/BrowserPlugin.swift +63 -0
- package/vendor/@akanjs/native/plugins/browser/native-plugin.json +22 -0
- package/vendor/@akanjs/native/plugins/browser/src/args.ts +34 -0
- package/vendor/@akanjs/native/plugins/browser/src/desktop.ts +40 -0
- package/vendor/@akanjs/native/plugins/browser/src/index.ts +47 -0
- package/vendor/@akanjs/native/plugins/browser/src/web.ts +60 -0
- package/vendor/@akanjs/native/plugins/camera/android/CameraPlugin.kt +365 -0
- package/vendor/@akanjs/native/plugins/camera/ios/CameraPlugin.swift +296 -0
- package/vendor/@akanjs/native/plugins/camera/native-plugin.json +32 -0
- package/vendor/@akanjs/native/plugins/camera/src/desktop.ts +27 -0
- package/vendor/@akanjs/native/plugins/camera/src/index.ts +85 -0
- package/vendor/@akanjs/native/plugins/camera/src/web.ts +267 -0
- package/vendor/@akanjs/native/plugins/clipboard/android/ClipboardPlugin.kt +51 -0
- package/vendor/@akanjs/native/plugins/clipboard/ios/ClipboardPlugin.swift +35 -0
- package/vendor/@akanjs/native/plugins/clipboard/native-plugin.json +17 -0
- package/vendor/@akanjs/native/plugins/clipboard/src/desktop.ts +66 -0
- package/vendor/@akanjs/native/plugins/clipboard/src/index.ts +72 -0
- package/vendor/@akanjs/native/plugins/clipboard/src/web.ts +69 -0
- package/vendor/@akanjs/native/plugins/contacts/android/ContactsPlugin.kt +84 -0
- package/vendor/@akanjs/native/plugins/contacts/ios/ContactsPlugin.swift +86 -0
- package/vendor/@akanjs/native/plugins/contacts/native-plugin.json +22 -0
- package/vendor/@akanjs/native/plugins/contacts/src/index.ts +43 -0
- package/vendor/@akanjs/native/plugins/device/android/DevicePlugin.kt +70 -0
- package/vendor/@akanjs/native/plugins/device/ios/DevicePlugin.swift +80 -0
- package/vendor/@akanjs/native/plugins/device/native-plugin.json +18 -0
- package/vendor/@akanjs/native/plugins/device/src/desktop.ts +276 -0
- package/vendor/@akanjs/native/plugins/device/src/index.ts +72 -0
- package/vendor/@akanjs/native/plugins/device/src/web.ts +162 -0
- package/vendor/@akanjs/native/plugins/dialog/android/DialogPlugin.kt +260 -0
- package/vendor/@akanjs/native/plugins/dialog/ios/DialogPlugin.swift +198 -0
- package/vendor/@akanjs/native/plugins/dialog/native-plugin.json +18 -0
- package/vendor/@akanjs/native/plugins/dialog/src/desktop.ts +80 -0
- package/vendor/@akanjs/native/plugins/dialog/src/index.ts +87 -0
- package/vendor/@akanjs/native/plugins/dialog/src/options.ts +111 -0
- package/vendor/@akanjs/native/plugins/dialog/src/web.ts +296 -0
- package/vendor/@akanjs/native/plugins/dock/native-plugin.json +10 -0
- package/vendor/@akanjs/native/plugins/dock/src/desktop.ts +34 -0
- package/vendor/@akanjs/native/plugins/dock/src/index.ts +46 -0
- package/vendor/@akanjs/native/plugins/file-picker/android/FilePickerPlugin.kt +316 -0
- package/vendor/@akanjs/native/plugins/file-picker/ios/FilePickerPlugin.swift +366 -0
- package/vendor/@akanjs/native/plugins/file-picker/native-plugin.json +18 -0
- package/vendor/@akanjs/native/plugins/file-picker/src/common.ts +125 -0
- package/vendor/@akanjs/native/plugins/file-picker/src/desktop.ts +201 -0
- package/vendor/@akanjs/native/plugins/file-picker/src/index.ts +222 -0
- package/vendor/@akanjs/native/plugins/file-picker/src/web.ts +158 -0
- package/vendor/@akanjs/native/plugins/filesystem/android/FilesystemPlugin.kt +561 -0
- package/vendor/@akanjs/native/plugins/filesystem/ios/FilesystemPlugin.swift +596 -0
- package/vendor/@akanjs/native/plugins/filesystem/native-plugin.json +45 -0
- package/vendor/@akanjs/native/plugins/filesystem/src/common.ts +150 -0
- package/vendor/@akanjs/native/plugins/filesystem/src/desktop.ts +438 -0
- package/vendor/@akanjs/native/plugins/filesystem/src/index.ts +179 -0
- package/vendor/@akanjs/native/plugins/filesystem/src/web.ts +334 -0
- package/vendor/@akanjs/native/plugins/geolocation/android/GeolocationPlugin.kt +360 -0
- package/vendor/@akanjs/native/plugins/geolocation/ios/GeolocationPlugin.swift +284 -0
- package/vendor/@akanjs/native/plugins/geolocation/native-plugin.json +23 -0
- package/vendor/@akanjs/native/plugins/geolocation/src/index.ts +155 -0
- package/vendor/@akanjs/native/plugins/geolocation/src/web.ts +132 -0
- package/vendor/@akanjs/native/plugins/global-shortcut/native-plugin.json +10 -0
- package/vendor/@akanjs/native/plugins/global-shortcut/src/desktop.ts +36 -0
- package/vendor/@akanjs/native/plugins/global-shortcut/src/index.ts +55 -0
- package/vendor/@akanjs/native/plugins/haptics/android/HapticsPlugin.kt +127 -0
- package/vendor/@akanjs/native/plugins/haptics/ios/HapticsPlugin.swift +127 -0
- package/vendor/@akanjs/native/plugins/haptics/native-plugin.json +19 -0
- package/vendor/@akanjs/native/plugins/haptics/src/index.ts +34 -0
- package/vendor/@akanjs/native/plugins/haptics/src/web.ts +53 -0
- package/vendor/@akanjs/native/plugins/http/android/HttpPlugin.kt +234 -0
- package/vendor/@akanjs/native/plugins/http/android/HttpUrl.kt +182 -0
- package/vendor/@akanjs/native/plugins/http/ios/HttpPlugin.swift +228 -0
- package/vendor/@akanjs/native/plugins/http/ios/HttpUrl.swift +166 -0
- package/vendor/@akanjs/native/plugins/http/native-plugin.json +27 -0
- package/vendor/@akanjs/native/plugins/http/src/common.ts +294 -0
- package/vendor/@akanjs/native/plugins/http/src/desktop.ts +69 -0
- package/vendor/@akanjs/native/plugins/http/src/index.ts +181 -0
- package/vendor/@akanjs/native/plugins/http/src/web.ts +40 -0
- package/vendor/@akanjs/native/plugins/iap/android/IapPlugin.kt +358 -0
- package/vendor/@akanjs/native/plugins/iap/ios/IapPlugin.swift +306 -0
- package/vendor/@akanjs/native/plugins/iap/native-plugin.json +28 -0
- package/vendor/@akanjs/native/plugins/iap/src/index.ts +206 -0
- package/vendor/@akanjs/native/plugins/keep-awake/android/KeepAwakePlugin.kt +48 -0
- package/vendor/@akanjs/native/plugins/keep-awake/ios/KeepAwakePlugin.swift +36 -0
- package/vendor/@akanjs/native/plugins/keep-awake/native-plugin.json +17 -0
- package/vendor/@akanjs/native/plugins/keep-awake/src/desktop.ts +127 -0
- package/vendor/@akanjs/native/plugins/keep-awake/src/index.ts +79 -0
- package/vendor/@akanjs/native/plugins/keep-awake/src/web.ts +78 -0
- package/vendor/@akanjs/native/plugins/keyboard/android/KeyboardPlugin.kt +77 -0
- package/vendor/@akanjs/native/plugins/keyboard/ios/KeyboardPlugin.swift +93 -0
- package/vendor/@akanjs/native/plugins/keyboard/native-plugin.json +18 -0
- package/vendor/@akanjs/native/plugins/keyboard/src/index.ts +78 -0
- package/vendor/@akanjs/native/plugins/keyboard/src/web.ts +57 -0
- package/vendor/@akanjs/native/plugins/local-notifications/android/LocalNotificationReceiver.kt +38 -0
- package/vendor/@akanjs/native/plugins/local-notifications/android/LocalNotifications.kt +284 -0
- package/vendor/@akanjs/native/plugins/local-notifications/android/LocalNotificationsPlugin.kt +248 -0
- package/vendor/@akanjs/native/plugins/local-notifications/ios/LocalNotificationsPlugin.swift +279 -0
- package/vendor/@akanjs/native/plugins/local-notifications/native-plugin.json +35 -0
- package/vendor/@akanjs/native/plugins/local-notifications/src/desktop.ts +196 -0
- package/vendor/@akanjs/native/plugins/local-notifications/src/index.ts +174 -0
- package/vendor/@akanjs/native/plugins/local-notifications/src/schedule.ts +164 -0
- package/vendor/@akanjs/native/plugins/local-notifications/src/timers.ts +72 -0
- package/vendor/@akanjs/native/plugins/local-notifications/src/web.ts +158 -0
- package/vendor/@akanjs/native/plugins/menu/native-plugin.json +10 -0
- package/vendor/@akanjs/native/plugins/menu/src/desktop.ts +52 -0
- package/vendor/@akanjs/native/plugins/menu/src/index.ts +107 -0
- package/vendor/@akanjs/native/plugins/network/android/NetworkPlugin.kt +124 -0
- package/vendor/@akanjs/native/plugins/network/ios/NetworkPlugin.swift +82 -0
- package/vendor/@akanjs/native/plugins/network/native-plugin.json +19 -0
- package/vendor/@akanjs/native/plugins/network/src/index.ts +59 -0
- package/vendor/@akanjs/native/plugins/network/src/web.ts +43 -0
- package/vendor/@akanjs/native/plugins/opener/android/OpenerPlugin.kt +81 -0
- package/vendor/@akanjs/native/plugins/opener/ios/OpenerPlugin.swift +83 -0
- package/vendor/@akanjs/native/plugins/opener/native-plugin.json +25 -0
- package/vendor/@akanjs/native/plugins/opener/src/desktop.ts +88 -0
- package/vendor/@akanjs/native/plugins/opener/src/index.ts +35 -0
- package/vendor/@akanjs/native/plugins/opener/src/url.ts +39 -0
- package/vendor/@akanjs/native/plugins/opener/src/web.ts +33 -0
- package/vendor/@akanjs/native/plugins/preferences/android/PreferencesPlugin.kt +44 -0
- package/vendor/@akanjs/native/plugins/preferences/ios/PreferencesPlugin.swift +47 -0
- package/vendor/@akanjs/native/plugins/preferences/native-plugin.json +18 -0
- package/vendor/@akanjs/native/plugins/preferences/src/desktop.ts +59 -0
- package/vendor/@akanjs/native/plugins/preferences/src/index.ts +75 -0
- package/vendor/@akanjs/native/plugins/preferences/src/web.ts +55 -0
- package/vendor/@akanjs/native/plugins/push/android/AkanNativeMessagingService.kt +17 -0
- package/vendor/@akanjs/native/plugins/push/android/PushPlugin.kt +265 -0
- package/vendor/@akanjs/native/plugins/push/ios/PushPlugin.swift +173 -0
- package/vendor/@akanjs/native/plugins/push/native-plugin.json +23 -0
- package/vendor/@akanjs/native/plugins/push/src/index.ts +83 -0
- package/vendor/@akanjs/native/plugins/screen/native-plugin.json +10 -0
- package/vendor/@akanjs/native/plugins/screen/src/desktop.ts +50 -0
- package/vendor/@akanjs/native/plugins/screen/src/index.ts +107 -0
- package/vendor/@akanjs/native/plugins/screen/src/web.ts +92 -0
- package/vendor/@akanjs/native/plugins/screen-orientation/android/ScreenOrientationPlugin.kt +113 -0
- package/vendor/@akanjs/native/plugins/screen-orientation/ios/ScreenOrientationPlugin.swift +150 -0
- package/vendor/@akanjs/native/plugins/screen-orientation/native-plugin.json +17 -0
- package/vendor/@akanjs/native/plugins/screen-orientation/src/index.ts +69 -0
- package/vendor/@akanjs/native/plugins/screen-orientation/src/types.ts +26 -0
- package/vendor/@akanjs/native/plugins/screen-orientation/src/web.ts +67 -0
- package/vendor/@akanjs/native/plugins/secure-storage/android/SecureStoragePlugin.kt +184 -0
- package/vendor/@akanjs/native/plugins/secure-storage/ios/SecureStoragePlugin.swift +145 -0
- package/vendor/@akanjs/native/plugins/secure-storage/native-plugin.json +18 -0
- package/vendor/@akanjs/native/plugins/secure-storage/src/desktop.ts +332 -0
- package/vendor/@akanjs/native/plugins/secure-storage/src/index.ts +33 -0
- package/vendor/@akanjs/native/plugins/share/android/SharePlugin.kt +218 -0
- package/vendor/@akanjs/native/plugins/share/ios/SharePlugin.swift +142 -0
- package/vendor/@akanjs/native/plugins/share/native-plugin.json +18 -0
- package/vendor/@akanjs/native/plugins/share/src/index.ts +87 -0
- package/vendor/@akanjs/native/plugins/share/src/options.ts +43 -0
- package/vendor/@akanjs/native/plugins/share/src/web.ts +116 -0
- package/vendor/@akanjs/native/plugins/single-instance/native-plugin.json +10 -0
- package/vendor/@akanjs/native/plugins/single-instance/src/desktop.ts +63 -0
- package/vendor/@akanjs/native/plugins/single-instance/src/index.ts +32 -0
- package/vendor/@akanjs/native/plugins/single-instance/src/socket.ts +248 -0
- package/vendor/@akanjs/native/plugins/splash-screen/android/SplashScreenPlugin.kt +19 -0
- package/vendor/@akanjs/native/plugins/splash-screen/ios/SplashScreenPlugin.swift +20 -0
- package/vendor/@akanjs/native/plugins/splash-screen/native-plugin.json +17 -0
- package/vendor/@akanjs/native/plugins/splash-screen/src/index.ts +24 -0
- package/vendor/@akanjs/native/plugins/splash-screen/src/web.ts +17 -0
- package/vendor/@akanjs/native/plugins/sqlite/android/SqlStatements.kt +121 -0
- package/vendor/@akanjs/native/plugins/sqlite/android/SqlitePlugin.kt +327 -0
- package/vendor/@akanjs/native/plugins/sqlite/ios/SqlitePlugin.swift +361 -0
- package/vendor/@akanjs/native/plugins/sqlite/native-plugin.json +18 -0
- package/vendor/@akanjs/native/plugins/sqlite/src/common.ts +221 -0
- package/vendor/@akanjs/native/plugins/sqlite/src/desktop.ts +140 -0
- package/vendor/@akanjs/native/plugins/sqlite/src/index.ts +114 -0
- package/vendor/@akanjs/native/plugins/toast/android/ToastPlugin.kt +27 -0
- package/vendor/@akanjs/native/plugins/toast/native-plugin.json +14 -0
- package/vendor/@akanjs/native/plugins/toast/src/index.ts +41 -0
- package/vendor/@akanjs/native/plugins/toast/src/queue.ts +77 -0
- package/vendor/@akanjs/native/plugins/toast/src/web.ts +130 -0
- package/vendor/@akanjs/native/plugins/tray/native-plugin.json +10 -0
- package/vendor/@akanjs/native/plugins/tray/src/desktop.ts +73 -0
- package/vendor/@akanjs/native/plugins/tray/src/index.ts +111 -0
- package/vendor/@akanjs/native/plugins/updates/android/UpdatesPlugin.kt +290 -0
- package/vendor/@akanjs/native/plugins/updates/ios/UpdatesPlugin.swift +292 -0
- package/vendor/@akanjs/native/plugins/updates/native-plugin.json +19 -0
- package/vendor/@akanjs/native/plugins/updates/src/desktop.ts +869 -0
- package/vendor/@akanjs/native/plugins/updates/src/index.ts +107 -0
- package/vendor/@akanjs/native/plugins/volume/android/VolumePlugin.kt +107 -0
- package/vendor/@akanjs/native/plugins/volume/native-plugin.json +14 -0
- package/vendor/@akanjs/native/plugins/volume/src/common.ts +28 -0
- package/vendor/@akanjs/native/plugins/volume/src/desktop.ts +185 -0
- package/vendor/@akanjs/native/plugins/volume/src/index.ts +32 -0
- package/vendor/@akanjs/native/plugins/window/native-plugin.json +32 -0
- package/vendor/@akanjs/native/plugins/window/src/desktop.ts +170 -0
- package/vendor/@akanjs/native/plugins/window/src/index.ts +342 -0
- package/vendor/@akanjs/native/plugins/window/src/web.ts +43 -0
- package/vendor/@akanjs/native/plugins/window-state/native-plugin.json +10 -0
- package/vendor/@akanjs/native/plugins/window-state/src/desktop.ts +73 -0
- package/vendor/@akanjs/native/plugins/window-state/src/index.ts +35 -0
- package/vendor/@akanjs/native/plugins/window-state/src/state.ts +146 -0
- package/vendor/use-agentic/AgentActivity.tsx +26 -0
- package/vendor/use-agentic/AgentGate.ts +25 -0
- package/vendor/use-agentic/AgentProgress.ts +13 -1
- package/vendor/use-agentic/AgentSession.ts +183 -28
- package/vendor/use-agentic/AgenticSurface.ts +94 -34
- package/vendor/use-agentic/CHANGELOG.md +663 -0
- package/vendor/use-agentic/Compaction.ts +82 -8
- package/vendor/use-agentic/ToolRunner.ts +77 -2
- package/vendor/use-agentic/Transcript.ts +6 -1
- package/vendor/use-agentic/WIRE.md +16 -2
- package/vendor/use-agentic/httpRunner.ts +19 -4
- package/vendor/use-agentic/index.ts +2 -1
- package/vendor/use-agentic/surfaceContext.ts +3 -0
- package/vendor/use-agentic/types.ts +83 -3
- package/webkit/CsrRouteTable.ts +276 -0
- package/webkit/CsrStack.ts +98 -0
- package/webkit/RenderLayer.tsx +132 -0
- package/webkit/bootCsr.tsx +41 -283
- package/webkit/csrFrameDump.ts +67 -0
- package/webkit/index.ts +5 -5
- package/webkit/lazy.tsx +3 -13
- package/webkit/nativeNavigation.ts +206 -0
- package/webkit/nativePurchase.ts +103 -0
- package/webkit/nativeUpdates.ts +55 -0
- package/webkit/seoPages.ts +20 -0
- package/webkit/useBodyScrollLock.tsx +0 -6
- package/webkit/useCamera.tsx +76 -89
- package/webkit/useCsrValues.ts +359 -565
- package/webkit/useDebounce.ts +0 -3
- package/webkit/useEscapeKey.tsx +1 -12
- package/webkit/useFetch.ts +15 -14
- package/webkit/useFrameRuntime.ts +5 -43
- package/webkit/useGeoLocation.tsx +12 -14
- package/webkit/useHistory.ts +23 -6
- package/webkit/useLocation.ts +11 -11
- package/webkit/usePageActivity.ts +6 -0
- package/webkit/usePageFocusEffect.ts +13 -0
- package/webkit/usePageLocation.ts +17 -0
- package/webkit/usePageTool.tsx +2 -9
- package/webkit/usePurchase.tsx +69 -140
- package/webkit/useScreenScope.tsx +2 -13
- package/capacitor.base.config.ts +0 -141
- package/client/capacitor.ts +0 -297
- package/client/fetch.ts +0 -1
- package/client/frameDebug.ts +0 -29
- package/common/deepObjectify.ts +0 -42
- package/common/dynamicRecord.ts +0 -12
- package/common/formatPhone.ts +0 -7
- package/common/getAllPropertyDescriptors.ts +0 -13
- package/common/isPhoneNumber.ts +0 -8
- package/common/lowerlize.ts +0 -4
- package/common/mergeVersion.ts +0 -10
- package/common/pathGet.ts +0 -23
- package/common/pathGetLoose.ts +0 -31
- package/common/pathSet.ts +0 -27
- package/common/plainFieldsOf.ts +0 -13
- package/common/randomPicks.ts +0 -12
- package/common/splitVersion.ts +0 -11
- package/common/toPathSegments.ts +0 -10
- package/common/websocketAuth.ts +0 -24
- package/common/websocketBinaryFrame.ts +0 -46
- package/constant/deserialize.ts +0 -98
- package/dictionary/agentTurn.dictionary.ts +0 -33
- package/document/schema.ts +0 -24
- package/fetch/fetchType/clientSignal.type.ts +0 -22
- package/local/apps/akan/akan-local.db +0 -0
- package/local/apps/akan/akan-local.db-shm +0 -0
- package/local/apps/akan/akan-local.db-wal +0 -0
- package/local/apps/akan/akan-local_solid.db +0 -0
- package/local/apps/akan/akan-local_solid.db-shm +0 -0
- package/local/apps/akan/akan-local_solid.db-wal +0 -0
- package/local/apps/serverLifecycle/serverLifecycle-local.db +0 -0
- package/local/apps/serverLifecycle/serverLifecycle-local.db-shm +0 -0
- package/local/apps/serverLifecycle/serverLifecycle-local.db-wal +0 -0
- package/local/apps/serverLifecycle/serverLifecycle-local_solid.db +0 -0
- package/local/apps/serverLifecycle/serverLifecycle-local_solid.db-shm +0 -0
- package/local/apps/serverLifecycle/serverLifecycle-local_solid.db-wal +0 -0
- package/server/artifact/manifestTypes.ts +0 -19
- package/server/assetEncoding.ts +0 -27
- package/server/consoleEvaluator.ts +0 -51
- package/server/di/index.ts +0 -4
- package/server/di/resolveAdaptorHierarchy.ts +0 -91
- package/server/di/resolveServiceHierarchy.ts +0 -47
- package/server/hmr/changeBatch.ts +0 -14
- package/server/hmr/index.ts +0 -4
- package/server/metadata.tsx +0 -198
- package/server/proxy/akanResponse.ts +0 -16
- package/server/proxy/bunRequestFields.ts +0 -12
- package/server/routing/eventStream.ts +0 -93
- package/server/rscPartialCommit.ts +0 -3
- package/server/rscPatchSafety.ts +0 -57
- package/server/rscWorkerReplay.ts +0 -49
- package/server/subRouteIndexDocument.tsx +0 -61
- package/service/predefinedAdaptor/deepseekLlm.ts +0 -82
- package/service/predefinedAdaptor/sqlDescriptor.ts +0 -25
- package/store/agent/storeSurface.ts +0 -28
- package/store/agent/types.ts +0 -16
- package/store/agentic/useFileFieldTool.ts +0 -221
- package/store/stateInfo.ts +0 -66
- package/test/playwright.config.base.ts +0 -48
- package/test/playwright.pageAgent.ts +0 -41
- package/test/sample.ts +0 -19
- package/types/capacitor.base.config.d.ts +0 -3
- package/types/client/capacitor.d.ts +0 -290
- package/types/client/fetch.d.ts +0 -1
- package/types/client/frameDebug.d.ts +0 -3
- package/types/common/deepObjectify.d.ts +0 -6
- package/types/common/dynamicRecord.d.ts +0 -14
- package/types/common/formatPhone.d.ts +0 -2
- package/types/common/getAllPropertyDescriptors.d.ts +0 -5
- package/types/common/isPhoneNumber.d.ts +0 -2
- package/types/common/lowerlize.d.ts +0 -2
- package/types/common/mergeVersion.d.ts +0 -10
- package/types/common/pathGet.d.ts +0 -1
- package/types/common/pathGetLoose.d.ts +0 -8
- package/types/common/pathSet.d.ts +0 -3
- package/types/common/plainFieldsOf.d.ts +0 -6
- package/types/common/randomPicks.d.ts +0 -1
- package/types/common/splitVersion.d.ts +0 -11
- package/types/common/toPathSegments.d.ts +0 -9
- package/types/common/websocketAuth.d.ts +0 -19
- package/types/common/websocketBinaryFrame.d.ts +0 -17
- package/types/constant/deserialize.d.ts +0 -10
- package/types/dictionary/agentTurn.dictionary.d.ts +0 -1
- package/types/document/schema.d.ts +0 -5
- package/types/fetch/fetchType/clientSignal.type.d.ts +0 -16
- package/types/server/artifact/manifestTypes.d.ts +0 -16
- package/types/server/assetEncoding.d.ts +0 -7
- package/types/server/consoleEvaluator.d.ts +0 -2
- package/types/server/di/index.d.ts +0 -4
- package/types/server/di/resolveAdaptorHierarchy.d.ts +0 -21
- package/types/server/di/resolveServiceHierarchy.d.ts +0 -13
- package/types/server/di.d.ts +0 -1
- package/types/server/hmr/changeBatch.d.ts +0 -13
- package/types/server/hmr/index.d.ts +0 -4
- package/types/server/hmr.d.ts +0 -1
- package/types/server/metadata.d.ts +0 -22
- package/types/server/proxy/akanResponse.d.ts +0 -7
- package/types/server/proxy/bunRequestFields.d.ts +0 -1
- package/types/server/routing/eventStream.d.ts +0 -23
- package/types/server/rscPartialCommit.d.ts +0 -1
- package/types/server/rscPatchSafety.d.ts +0 -8
- package/types/server/rscWorkerReplay.d.ts +0 -32
- package/types/server/subRouteIndexDocument.d.ts +0 -8
- package/types/service/predefinedAdaptor/deepseekLlm.d.ts +0 -19
- package/types/service/predefinedAdaptor/sqlDescriptor.d.ts +0 -5
- package/types/store/agent/storeSurface.d.ts +0 -14
- package/types/store/agent/types.d.ts +0 -15
- package/types/store/agentic/useFileFieldTool.d.ts +0 -41
- package/types/store/stateInfo.d.ts +0 -23
- package/types/test/playwright.config.base.d.ts +0 -9
- package/types/test/playwright.pageAgent.d.ts +0 -12
- package/types/test/sample.d.ts +0 -15
- package/types/ui/Agent/Context.d.ts +0 -13
- package/types/ui/Agent/Mic.d.ts +0 -8
- package/types/ui/Agent/Section.d.ts +0 -10
- package/types/ui/Agent/StateKey.d.ts +0 -16
- package/types/ui/Agent/Tool.d.ts +0 -15
- package/types/ui/Agent/Transcript.d.ts +0 -13
- package/types/ui/Agent/markdownBlocks.d.ts +0 -35
- package/types/ui/Agent/markdownSpans.d.ts +0 -2
- package/types/ui/Agent/markdownTable.d.ts +0 -16
- package/types/ui/Agent/sessionHistory.d.ts +0 -14
- package/types/ui/Agent/sessionView.d.ts +0 -15
- package/types/ui/Dialog/Action.d.ts +0 -5
- package/types/ui/Dialog/Close.d.ts +0 -6
- package/types/ui/Dialog/Content.d.ts +0 -6
- package/types/ui/Dialog/Title.d.ts +0 -5
- package/types/ui/Dialog/Trigger.d.ts +0 -6
- package/types/ui/Dialog/context.d.ts +0 -18
- package/types/ui/Layout/LeftSider.d.ts +0 -11
- package/types/ui/Layout/RightSider.d.ts +0 -12
- package/types/ui/Layout/Template.d.ts +0 -7
- package/types/ui/Layout/TopLeftAction.d.ts +0 -6
- package/types/ui/Layout/Unit.d.ts +0 -9
- package/types/ui/Layout/View.d.ts +0 -8
- package/types/ui/Layout/Zone.d.ts +0 -6
- package/types/ui/Link/Back.d.ts +0 -7
- package/types/ui/Link/Close.d.ts +0 -7
- package/types/ui/Link/CsrLink.d.ts +0 -2
- package/types/ui/Link/Lang.d.ts +0 -8
- package/types/ui/Link/SsrLink.d.ts +0 -2
- package/types/ui/Link/types.d.ts +0 -50
- package/types/ui/Loading/Area.d.ts +0 -9
- package/types/ui/Loading/Button.d.ts +0 -7
- package/types/ui/Loading/Input.d.ts +0 -7
- package/types/ui/Model/LoadInit.d.ts +0 -10
- package/types/ui/Model/LoadView.d.ts +0 -10
- package/types/ui/Reference/Collapse.d.ts +0 -11
- package/types/ui/Reference/Summary.d.ts +0 -13
- package/types/ui/Reference/Toolbar.d.ts +0 -21
- package/types/ui/Reference/dictText.d.ts +0 -6
- package/types/ui/Reference/style.d.ts +0 -20
- package/types/ui/Signal/Message.d.ts +0 -23
- package/types/ui/Signal/PubSub.d.ts +0 -24
- package/types/ui/Signal/Request.d.ts +0 -8
- package/types/ui/System/DevModeToggle.d.ts +0 -1
- package/types/ui/System/Gtag.d.ts +0 -4
- package/types/ui/System/frameCssVars.d.ts +0 -5
- package/types/ui/Tab/Menu.d.ts +0 -12
- package/types/ui/Tab/Menus.d.ts +0 -6
- package/types/ui/Tab/Panel.d.ts +0 -8
- package/types/ui/Tab/context.d.ts +0 -11
- package/types/ui/UiOverride/Provider.d.ts +0 -15
- package/types/ui/UiOverride/context.d.ts +0 -127
- package/types/ui/UiOverride/createOverridable.d.ts +0 -9
- package/types/ui/UiOverride/useUiOverride.d.ts +0 -7
- package/types/ui/UiOverride/useUiRecipe.d.ts +0 -8
- package/types/webkit/createRobotPage.d.ts +0 -15
- package/types/webkit/createSitemapPage.d.ts +0 -4
- package/types/webkit/useCodepush.d.ts +0 -16
- package/types/webkit/useContact.d.ts +0 -11
- package/ui/Agent/Context.tsx +0 -49
- package/ui/Agent/Mic.tsx +0 -27
- package/ui/Agent/Section.tsx +0 -24
- package/ui/Agent/StateKey.tsx +0 -46
- package/ui/Agent/Tool.tsx +0 -59
- package/ui/Agent/Transcript.tsx +0 -33
- package/ui/Agent/markdownBlocks.ts +0 -137
- package/ui/Agent/markdownSpans.tsx +0 -49
- package/ui/Agent/markdownTable.ts +0 -54
- package/ui/Agent/sessionHistory.ts +0 -88
- package/ui/Agent/sessionView.ts +0 -38
- package/ui/Dialog/Action.tsx +0 -15
- package/ui/Dialog/Close.tsx +0 -18
- package/ui/Dialog/Content.tsx +0 -11
- package/ui/Dialog/Title.tsx +0 -15
- package/ui/Dialog/Trigger.tsx +0 -18
- package/ui/Dialog/context.ts +0 -32
- package/ui/Layout/LeftSider.tsx +0 -43
- package/ui/Layout/RightSider.tsx +0 -47
- package/ui/Layout/Template.tsx +0 -11
- package/ui/Layout/TopLeftAction.tsx +0 -28
- package/ui/Layout/Unit.tsx +0 -19
- package/ui/Layout/View.tsx +0 -12
- package/ui/Layout/Zone.tsx +0 -10
- package/ui/Link/Back.tsx +0 -15
- package/ui/Link/Close.tsx +0 -20
- package/ui/Link/CsrLink.tsx +0 -46
- package/ui/Link/Lang.tsx +0 -16
- package/ui/Link/SsrLink.tsx +0 -72
- package/ui/Link/types.ts +0 -55
- package/ui/Loading/Area.tsx +0 -27
- package/ui/Loading/Button.tsx +0 -15
- package/ui/Loading/Input.tsx +0 -15
- package/ui/Model/LoadInit.tsx +0 -11
- package/ui/Model/LoadView.tsx +0 -11
- package/ui/Reference/Collapse.tsx +0 -26
- package/ui/Reference/Summary.tsx +0 -25
- package/ui/Reference/Toolbar.tsx +0 -44
- package/ui/Reference/dictText.ts +0 -9
- package/ui/Reference/style.ts +0 -45
- package/ui/Signal/Message.tsx +0 -215
- package/ui/Signal/PubSub.tsx +0 -201
- package/ui/Signal/Request.tsx +0 -11
- package/ui/System/DevModeToggle.tsx +0 -19
- package/ui/System/Gtag.tsx +0 -69
- package/ui/System/frameCssVars.ts +0 -25
- package/ui/Tab/Menu.tsx +0 -70
- package/ui/Tab/Menus.tsx +0 -13
- package/ui/Tab/Panel.tsx +0 -25
- package/ui/Tab/context.ts +0 -20
- package/ui/UiOverride/Provider.tsx +0 -26
- package/ui/UiOverride/context.ts +0 -143
- package/ui/UiOverride/createOverridable.tsx +0 -25
- package/ui/UiOverride/useUiOverride.ts +0 -15
- package/ui/UiOverride/useUiRecipe.ts +0 -15
- package/webkit/createRobotPage.ts +0 -15
- package/webkit/createSitemapPage.ts +0 -4
- package/webkit/useCodepush.tsx +0 -99
- package/webkit/useContact.tsx +0 -52
|
@@ -0,0 +1,2321 @@
|
|
|
1
|
+
//! akan-native desktop shell: TAO window + WRY webview behind a C ABI for bun:ffi (docs/architecture.md §3.3, §9).
|
|
2
|
+
//!
|
|
3
|
+
//! Threads
|
|
4
|
+
//! - akan_native_run: process main thread only. Never returns (tao run → process::exit).
|
|
5
|
+
//! - every other akan_native_*: any thread. UI work goes to the main thread through EventLoopProxy.
|
|
6
|
+
//! - native → JS: messages are queued and a data-less wake() is called; JS drains with akan_native_poll.
|
|
7
|
+
//! The wake callback is a Bun threadsafe JSCallback: it runs on the Worker that created it and
|
|
8
|
+
//! never blocks the caller (verified, docs/research/desktop-macos.md §1 Q3).
|
|
9
|
+
#![allow(clippy::missing_safety_doc)]
|
|
10
|
+
|
|
11
|
+
// Before the modules, so that they can use it too.
|
|
12
|
+
macro_rules! log {
|
|
13
|
+
($($arg:tt)*) => { eprintln!("[akan-native native] {}", format!($($arg)*)) };
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
mod contract;
|
|
17
|
+
mod devproxy;
|
|
18
|
+
mod json;
|
|
19
|
+
mod navigation;
|
|
20
|
+
mod page_menu;
|
|
21
|
+
mod placement;
|
|
22
|
+
mod routes;
|
|
23
|
+
#[cfg(test)]
|
|
24
|
+
mod vectors;
|
|
25
|
+
#[cfg(target_os = "macos")]
|
|
26
|
+
mod notify;
|
|
27
|
+
// The local notifications' schedule on Windows and Linux (win/notify.rs, linux/notify.rs).
|
|
28
|
+
#[cfg(not(target_os = "macos"))]
|
|
29
|
+
mod notify_schedule;
|
|
30
|
+
#[cfg(target_os = "macos")]
|
|
31
|
+
mod camera;
|
|
32
|
+
#[cfg(target_os = "macos")]
|
|
33
|
+
mod js_panels;
|
|
34
|
+
#[cfg(target_os = "macos")]
|
|
35
|
+
mod panels;
|
|
36
|
+
mod dialog_args;
|
|
37
|
+
mod accelerator;
|
|
38
|
+
// Menu trees, roles and dock arguments of the Windows and Linux shells (unit tested everywhere).
|
|
39
|
+
mod chrome;
|
|
40
|
+
#[cfg(target_os = "macos")]
|
|
41
|
+
mod hotkey;
|
|
42
|
+
#[cfg(target_os = "macos")]
|
|
43
|
+
mod menu;
|
|
44
|
+
#[cfg(target_os = "macos")]
|
|
45
|
+
mod tray;
|
|
46
|
+
#[cfg(target_os = "macos")]
|
|
47
|
+
mod dock;
|
|
48
|
+
#[cfg(target_os = "macos")]
|
|
49
|
+
mod screen;
|
|
50
|
+
#[cfg(target_os = "macos")]
|
|
51
|
+
mod volume;
|
|
52
|
+
#[cfg(target_os = "macos")]
|
|
53
|
+
mod autostart;
|
|
54
|
+
#[cfg(target_os = "macos")]
|
|
55
|
+
mod keychain;
|
|
56
|
+
#[cfg(target_os = "windows")]
|
|
57
|
+
mod win;
|
|
58
|
+
#[cfg(target_os = "linux")]
|
|
59
|
+
mod linux;
|
|
60
|
+
|
|
61
|
+
use std::{
|
|
62
|
+
collections::{HashMap, VecDeque},
|
|
63
|
+
ffi::{c_char, CStr},
|
|
64
|
+
path::{Component, Path, PathBuf},
|
|
65
|
+
sync::{
|
|
66
|
+
atomic::{AtomicBool, AtomicU64, AtomicUsize, Ordering},
|
|
67
|
+
Arc, LazyLock, Mutex, OnceLock, RwLock,
|
|
68
|
+
},
|
|
69
|
+
time::Duration,
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
use routes::{asset_mime, is_host_path, parse_range, route, RangeAnswer, Route};
|
|
73
|
+
use tao::{
|
|
74
|
+
dpi::LogicalSize,
|
|
75
|
+
event::{Event, StartCause, WindowEvent},
|
|
76
|
+
event_loop::{ControlFlow, EventLoopBuilder, EventLoopProxy, EventLoopWindowTarget},
|
|
77
|
+
window::WindowBuilder,
|
|
78
|
+
};
|
|
79
|
+
use wry::{
|
|
80
|
+
http::{header::CONTENT_TYPE, Request, Response},
|
|
81
|
+
DragDropEvent, NewWindowResponse, PageLoadEvent, PermissionKind, PermissionResponse, RequestAsyncResponder, WebView, WebViewBuilder,
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
/// The page origin (WV-1). WebView2 has no custom schemes of its own: wry serves app://localhost
|
|
85
|
+
/// as https://app.localhost with with_https_scheme (webview2/mod.rs custom_protocol_workaround),
|
|
86
|
+
/// the same origin as on Android. WebKit (macOS, WebKitGTK) serves the scheme itself.
|
|
87
|
+
#[cfg(target_os = "windows")]
|
|
88
|
+
const ORIGIN: &str = "https://app.localhost";
|
|
89
|
+
#[cfg(not(target_os = "windows"))]
|
|
90
|
+
const ORIGIN: &str = "app://localhost";
|
|
91
|
+
/// What windows load: wry rewrites it to ORIGIN on Windows.
|
|
92
|
+
const START_URL: &str = "app://localhost";
|
|
93
|
+
|
|
94
|
+
/// `url` is ORIGIN itself or a path, query or fragment on it.
|
|
95
|
+
fn on_origin(url: &str) -> bool {
|
|
96
|
+
url.strip_prefix(ORIGIN).is_some_and(|rest| rest.is_empty() || rest.starts_with(['/', '?', '#']))
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// ───────────────────────── native → JS queue ─────────────────────────
|
|
100
|
+
// Frame (little endian): [u8 kind][u64 reqId][u32 webviewId][body...]
|
|
101
|
+
// kind 1 = IPC request (body = the bytes the page POSTed)
|
|
102
|
+
// kind 2 = native event (body = JSON text). reqId is 0, or a watch id (see push_watched).
|
|
103
|
+
const KIND_IPC: u8 = 1;
|
|
104
|
+
const KIND_EVENT: u8 = 2;
|
|
105
|
+
|
|
106
|
+
struct Queue {
|
|
107
|
+
items: VecDeque<Vec<u8>>,
|
|
108
|
+
wake_pending: bool,
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
static QUEUE: Mutex<Queue> = Mutex::new(Queue { items: VecDeque::new(), wake_pending: false });
|
|
112
|
+
static WAKE: AtomicUsize = AtomicUsize::new(0);
|
|
113
|
+
|
|
114
|
+
/// The idle wake budget (architecture review stage 5): how often native code woke the Worker, how
|
|
115
|
+
/// often it polled, frames in and out, the deepest the queue got. The dev shell op `debug.stats`
|
|
116
|
+
/// reads them; an idle app should wake the Worker zero times.
|
|
117
|
+
struct Stats {
|
|
118
|
+
wakes: AtomicU64,
|
|
119
|
+
polls: AtomicU64,
|
|
120
|
+
frames_in: AtomicU64,
|
|
121
|
+
frames_out: AtomicU64,
|
|
122
|
+
max_depth: AtomicU64,
|
|
123
|
+
}
|
|
124
|
+
static STATS: Stats = Stats { wakes: AtomicU64::new(0), polls: AtomicU64::new(0), frames_in: AtomicU64::new(0), frames_out: AtomicU64::new(0), max_depth: AtomicU64::new(0) };
|
|
125
|
+
|
|
126
|
+
fn stats_json() -> String {
|
|
127
|
+
let queued = QUEUE.lock().unwrap().items.len();
|
|
128
|
+
let pending = PENDING.lock().unwrap().len();
|
|
129
|
+
format!(
|
|
130
|
+
r#"{{"wakes":{},"polls":{},"framesIn":{},"framesOut":{},"maxDepth":{},"queued":{queued},"pending":{pending}}}"#,
|
|
131
|
+
STATS.wakes.load(Ordering::Relaxed),
|
|
132
|
+
STATS.polls.load(Ordering::Relaxed),
|
|
133
|
+
STATS.frames_in.load(Ordering::Relaxed),
|
|
134
|
+
STATS.frames_out.load(Ordering::Relaxed),
|
|
135
|
+
STATS.max_depth.load(Ordering::Relaxed),
|
|
136
|
+
)
|
|
137
|
+
}
|
|
138
|
+
/// reqId → (webview id, responder). A webview's entries are dropped on the main thread when its
|
|
139
|
+
/// page starts loading a new document (they can never be answered) or its window is destroyed.
|
|
140
|
+
static PENDING: LazyLock<Mutex<HashMap<u64, (u32, RequestAsyncResponder)>>> = LazyLock::new(|| Mutex::new(HashMap::new()));
|
|
141
|
+
static NEXT_REQ: AtomicU64 = AtomicU64::new(1);
|
|
142
|
+
/// Calls waiting for the host (and frames waiting for it to poll) beyond which IPC is answered 503.
|
|
143
|
+
const MAX_PENDING: usize = 10_000;
|
|
144
|
+
/// Files registered by plugins: id → (path, mime). Served at /__akan_native/file/<id>.
|
|
145
|
+
static FILES: LazyLock<Mutex<HashMap<String, (PathBuf, String)>>> = LazyLock::new(|| Mutex::new(HashMap::new()));
|
|
146
|
+
static PROXY: OnceLock<Mutex<EventLoopProxy<UserEvent>>> = OnceLock::new();
|
|
147
|
+
|
|
148
|
+
// Quit flow (plugins.md D4). AppKit asks applicationShouldTerminate: (Cmd+Q, Dock, AppleScript,
|
|
149
|
+
// logout); the shell cancels, the host runs its sequence (page veto, plugin cleanup) and calls
|
|
150
|
+
// akan_native_quit, which ends the TAO loop without asking AppKit again.
|
|
151
|
+
/// akan_native_quit was called (or the watchdog fired): a terminate: from now on proceeds.
|
|
152
|
+
static QUITTING: AtomicBool = AtomicBool::new(false);
|
|
153
|
+
/// applicationShouldTerminate: answered NSTerminateLater (logout, restart, shutdown), so the host's
|
|
154
|
+
/// decision goes back through replyToApplicationShouldTerminate:.
|
|
155
|
+
#[cfg_attr(not(target_os = "macos"), allow(dead_code))]
|
|
156
|
+
static TERMINATE_LATER: AtomicBool = AtomicBool::new(false);
|
|
157
|
+
/// Events the host must act on (quitRequested, closeRequested) carry a watch id in the frame's
|
|
158
|
+
/// reqId; akan_native_poll records the highest id the Worker took.
|
|
159
|
+
static WATCH_SEQ: AtomicU64 = AtomicU64::new(0);
|
|
160
|
+
static WATCH_TAKEN: AtomicU64 = AtomicU64::new(0);
|
|
161
|
+
const WATCH_TIMEOUT: Duration = Duration::from_millis(2000);
|
|
162
|
+
|
|
163
|
+
fn frame(kind: u8, req_id: u64, webview_id: u32, body: &[u8]) -> Vec<u8> {
|
|
164
|
+
let mut v = Vec::with_capacity(13 + body.len());
|
|
165
|
+
v.push(kind);
|
|
166
|
+
v.extend_from_slice(&req_id.to_le_bytes());
|
|
167
|
+
v.extend_from_slice(&webview_id.to_le_bytes());
|
|
168
|
+
v.extend_from_slice(body);
|
|
169
|
+
v
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/// Held (shared) while the wake callback is being called: akan_native_set_wake takes it exclusively, so
|
|
173
|
+
/// once it returns no thread still calls the callback the host is about to close.
|
|
174
|
+
static WAKE_CALLS: RwLock<()> = RwLock::new(());
|
|
175
|
+
|
|
176
|
+
fn call_wake() {
|
|
177
|
+
let _calling = WAKE_CALLS.read().unwrap_or_else(|e| e.into_inner());
|
|
178
|
+
let f = WAKE.load(Ordering::Acquire);
|
|
179
|
+
if f != 0 {
|
|
180
|
+
STATS.wakes.fetch_add(1, Ordering::Relaxed);
|
|
181
|
+
let f: extern "C" fn() = unsafe { std::mem::transmute(f) };
|
|
182
|
+
f();
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/// Queues a message and wakes JS once per batch (coalesced wakes keep the Worker queue small).
|
|
187
|
+
fn push(msg: Vec<u8>) {
|
|
188
|
+
let need_wake = {
|
|
189
|
+
let mut q = QUEUE.lock().unwrap();
|
|
190
|
+
q.items.push_back(msg);
|
|
191
|
+
STATS.frames_in.fetch_add(1, Ordering::Relaxed);
|
|
192
|
+
STATS.max_depth.fetch_max(q.items.len() as u64, Ordering::Relaxed);
|
|
193
|
+
let need = !q.wake_pending;
|
|
194
|
+
q.wake_pending = true;
|
|
195
|
+
need
|
|
196
|
+
};
|
|
197
|
+
if need_wake {
|
|
198
|
+
call_wake();
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
fn push_event(json: &str) {
|
|
203
|
+
push(frame(KIND_EVENT, 0, 0, json.as_bytes()));
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/// Pushes an event the host must act on and acts by itself if the Worker has not taken it within
|
|
207
|
+
/// WATCH_TIMEOUT: a hung plugin host must never make the app impossible to quit or a window
|
|
208
|
+
/// impossible to close. Once taken, the decision is the host's, which may wait for the user (an
|
|
209
|
+
/// unsaved-changes dialog in the page). A window's close request (`window`) only closes that
|
|
210
|
+
/// window, unless it is the last one: a Worker busy with a long synchronous call (a big query, a
|
|
211
|
+
/// large file copy) looks the same as a hung one, and closing a second window must not end the app.
|
|
212
|
+
fn push_watched(json: &str, window: Option<u32>) {
|
|
213
|
+
let id = WATCH_SEQ.fetch_add(1, Ordering::AcqRel) + 1;
|
|
214
|
+
push(frame(KIND_EVENT, id, 0, json.as_bytes()));
|
|
215
|
+
let json = json.to_string();
|
|
216
|
+
std::thread::spawn(move || {
|
|
217
|
+
std::thread::sleep(WATCH_TIMEOUT);
|
|
218
|
+
if WATCH_TAKEN.load(Ordering::Acquire) < id && !QUITTING.load(Ordering::Acquire) {
|
|
219
|
+
match window {
|
|
220
|
+
Some(window) => send(UserEvent::CloseUntaken { watch: id, window }),
|
|
221
|
+
None => {
|
|
222
|
+
log!("the plugin host did not take {json} within {WATCH_TIMEOUT:?}; quitting");
|
|
223
|
+
akan_native_quit(0);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// ───────────────────────── SIGTERM ─────────────────────────
|
|
231
|
+
|
|
232
|
+
/// SIGTERM (`akan-native run`/`akan-native test` stopping the app, `kill`, launchd) ended the app without its
|
|
233
|
+
/// quit hooks: a Bun Worker gets no signal handlers while the main thread is inside akan_native_run
|
|
234
|
+
/// (verified), so window-state could not flush and single-instance left its socket behind.
|
|
235
|
+
/// The handler only writes a byte to a pipe (async-signal-safe); a thread turns it into a
|
|
236
|
+
/// `signal` event, and the host quits through its lifecycle (onQuit hooks, no veto, then
|
|
237
|
+
/// akan_native_quit). A second SIGTERM, a Worker that does not take the event (push_watched) or a quit
|
|
238
|
+
/// that has not happened after 5 s ends the process directly. libc is declared here, no crate.
|
|
239
|
+
#[cfg(unix)]
|
|
240
|
+
mod sigterm {
|
|
241
|
+
use std::sync::atomic::{AtomicI32, Ordering};
|
|
242
|
+
use std::time::Duration;
|
|
243
|
+
|
|
244
|
+
extern "C" {
|
|
245
|
+
fn pipe(fds: *mut i32) -> i32;
|
|
246
|
+
fn read(fd: i32, buf: *mut u8, count: usize) -> isize;
|
|
247
|
+
fn write(fd: i32, buf: *const u8, count: usize) -> isize;
|
|
248
|
+
fn signal(signum: i32, handler: extern "C" fn(i32)) -> usize;
|
|
249
|
+
}
|
|
250
|
+
const SIGHUP: i32 = 1;
|
|
251
|
+
const SIGINT: i32 = 2;
|
|
252
|
+
const SIGTERM: i32 = 15;
|
|
253
|
+
static WRITE_FD: AtomicI32 = AtomicI32::new(-1);
|
|
254
|
+
|
|
255
|
+
/// The signal number goes through the pipe (async-signal-safe: one write).
|
|
256
|
+
extern "C" fn on_signal(signum: i32) {
|
|
257
|
+
let fd = WRITE_FD.load(Ordering::Relaxed);
|
|
258
|
+
if fd >= 0 {
|
|
259
|
+
let byte = signum as u8;
|
|
260
|
+
unsafe { write(fd, &byte, 1) };
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/// SIGTERM (a service manager, `akan-native run`), SIGINT (Ctrl+C in a terminal) and SIGHUP (the
|
|
265
|
+
/// terminal closed) all quit through the host's quit hooks (N5); a second signal or 5 s: exit.
|
|
266
|
+
pub fn install() {
|
|
267
|
+
let mut fds = [0i32; 2];
|
|
268
|
+
if unsafe { pipe(fds.as_mut_ptr()) } != 0 {
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
WRITE_FD.store(fds[1], Ordering::Relaxed);
|
|
272
|
+
let read_fd = fds[0];
|
|
273
|
+
std::thread::spawn(move || {
|
|
274
|
+
let mut byte = 0u8;
|
|
275
|
+
let mut count = 0;
|
|
276
|
+
while unsafe { read(read_fd, &mut byte, 1) } == 1 {
|
|
277
|
+
count += 1;
|
|
278
|
+
let (name, code) = match byte as i32 {
|
|
279
|
+
SIGINT => ("SIGINT", 130),
|
|
280
|
+
SIGHUP => ("SIGHUP", 129),
|
|
281
|
+
_ => ("SIGTERM", 143),
|
|
282
|
+
};
|
|
283
|
+
if count > 1 || super::WAKE.load(Ordering::Acquire) == 0 {
|
|
284
|
+
std::process::exit(code);
|
|
285
|
+
}
|
|
286
|
+
super::push_watched(&format!(r#"{{"type":"signal","signal":"{name}"}}"#), None);
|
|
287
|
+
std::thread::spawn(move || {
|
|
288
|
+
std::thread::sleep(Duration::from_secs(5));
|
|
289
|
+
std::process::exit(code);
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
});
|
|
293
|
+
for signum in [SIGTERM, SIGINT, SIGHUP] {
|
|
294
|
+
unsafe { signal(signum, on_signal) };
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/// Windows has no SIGTERM: `akan-native run`/`akan-native test` stop the app with TerminateProcess, which skips
|
|
300
|
+
/// the quit hooks. So when the CLI starts the app it sets AKAN_NATIVE_QUIT_ON_STDIN=1 and gives it a pipe
|
|
301
|
+
/// as stdin: a line "quit", or the pipe closing (the CLI is gone), becomes the same `signal` event
|
|
302
|
+
/// as a SIGTERM on macOS and Linux, with the same fallbacks (a second request or 5 s: exit).
|
|
303
|
+
#[cfg(target_os = "windows")]
|
|
304
|
+
mod stdin_quit {
|
|
305
|
+
use std::io::BufRead;
|
|
306
|
+
use std::time::Duration;
|
|
307
|
+
|
|
308
|
+
pub fn install() {
|
|
309
|
+
if std::env::var_os("AKAN_NATIVE_QUIT_ON_STDIN").is_none_or(|v| v != "1") {
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
std::thread::spawn(|| {
|
|
313
|
+
let mut lines = std::io::stdin().lock().lines();
|
|
314
|
+
let mut requested = false;
|
|
315
|
+
loop {
|
|
316
|
+
let line = lines.next();
|
|
317
|
+
let quit = match &line {
|
|
318
|
+
Some(Ok(text)) => text.trim() == "quit",
|
|
319
|
+
_ => true, // closed or unreadable
|
|
320
|
+
};
|
|
321
|
+
if quit {
|
|
322
|
+
if requested || super::WAKE.load(std::sync::atomic::Ordering::Acquire) == 0 {
|
|
323
|
+
std::process::exit(143);
|
|
324
|
+
}
|
|
325
|
+
requested = true;
|
|
326
|
+
super::push_watched(r#"{"type":"signal","signal":"SIGTERM"}"#, None);
|
|
327
|
+
std::thread::spawn(|| {
|
|
328
|
+
std::thread::sleep(Duration::from_secs(5));
|
|
329
|
+
std::process::exit(143);
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
if !matches!(line, Some(Ok(_))) {
|
|
333
|
+
return;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
/// Answer to applicationShouldTerminate: (AppKit, main thread). `session_end`: logout, restart or
|
|
341
|
+
/// shutdown, where NSTerminateLater keeps the system waiting for the host instead of aborting the logout.
|
|
342
|
+
#[cfg(target_os = "macos")]
|
|
343
|
+
fn should_terminate(session_end: bool) -> macos::TerminateReply {
|
|
344
|
+
if QUITTING.load(Ordering::Acquire) || WAKE.load(Ordering::Acquire) == 0 {
|
|
345
|
+
return macos::TerminateReply::Now;
|
|
346
|
+
}
|
|
347
|
+
let reason = if session_end { "session" } else { "user" };
|
|
348
|
+
push_watched(&format!(r#"{{"type":"quitRequested","reason":"{reason}"}}"#), None);
|
|
349
|
+
if session_end {
|
|
350
|
+
TERMINATE_LATER.store(true, Ordering::Release);
|
|
351
|
+
macos::TerminateReply::Later
|
|
352
|
+
} else {
|
|
353
|
+
macos::TerminateReply::Cancel
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
fn send(ev: UserEvent) {
|
|
358
|
+
if let Some(p) = PROXY.get() {
|
|
359
|
+
let _ = p.lock().unwrap().send_event(ev);
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
enum UserEvent {
|
|
364
|
+
Respond(RequestAsyncResponder, Response<Vec<u8>>),
|
|
365
|
+
Emit { webview_id: u32, js: String },
|
|
366
|
+
Quit(i32),
|
|
367
|
+
/// A window's first page load finished (or the fallback timer fired): show it (D2).
|
|
368
|
+
Show(u32),
|
|
369
|
+
/// A shell command from the plugin host (window plugin, app plugin); answered with a
|
|
370
|
+
/// `shellReply` event carrying the same id.
|
|
371
|
+
Shell { id: u64, json: String },
|
|
372
|
+
/// The host kept the app running after a logout asked it to quit (akan_native_quit_cancel).
|
|
373
|
+
CancelTerminate,
|
|
374
|
+
/// A destroyed window's page is unloaded (about:blank finished, or the fallback timer): drop it.
|
|
375
|
+
Unloaded(u32),
|
|
376
|
+
/// The host did not take a window's close request in time (push_watched).
|
|
377
|
+
CloseUntaken { watch: u64, window: u32 },
|
|
378
|
+
/// What the windows draw changed without a TAO ThemeChanged (Linux: GTK's settings, the desktop
|
|
379
|
+
/// portal; linux/appearance.rs): repaint them and report themeChanged.
|
|
380
|
+
#[cfg_attr(not(target_os = "linux"), allow(dead_code))]
|
|
381
|
+
ThemeChanged,
|
|
382
|
+
/// A window's web content process ended (crashed, killed, out of memory): its document is gone (N2).
|
|
383
|
+
WebviewGone { window: u32, reason: &'static str },
|
|
384
|
+
/// desktop.recovery "reload": the wait after a window's page ended in a row is over; load it again.
|
|
385
|
+
ReloadGone(u32),
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// ───────────────────────── C ABI ─────────────────────────
|
|
389
|
+
|
|
390
|
+
/// Registers the wake callback (a threadsafe JSCallback). NULL = the host is gone: pending and
|
|
391
|
+
/// later IPC fail with 503 instead of calling a dead callback (which segfaults the process).
|
|
392
|
+
#[no_mangle]
|
|
393
|
+
pub extern "C" fn akan_native_set_wake(f: Option<extern "C" fn()>) {
|
|
394
|
+
{
|
|
395
|
+
let _no_calls = WAKE_CALLS.write().unwrap_or_else(|e| e.into_inner());
|
|
396
|
+
WAKE.store(f.map_or(0, |f| f as usize), Ordering::Release);
|
|
397
|
+
}
|
|
398
|
+
if f.is_none() {
|
|
399
|
+
let pending: Vec<_> = PENDING.lock().unwrap().drain().collect();
|
|
400
|
+
for (_, (_, r)) in pending {
|
|
401
|
+
send(UserEvent::Respond(r, text(503, "akan-native host is not running")));
|
|
402
|
+
}
|
|
403
|
+
return;
|
|
404
|
+
}
|
|
405
|
+
let need = {
|
|
406
|
+
let mut q = QUEUE.lock().unwrap();
|
|
407
|
+
let need = !q.items.is_empty();
|
|
408
|
+
q.wake_pending |= need;
|
|
409
|
+
need
|
|
410
|
+
};
|
|
411
|
+
if need {
|
|
412
|
+
call_wake();
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
/// Copies the next message into buf. 0 = empty. A message larger than cap is not consumed and its
|
|
417
|
+
/// size is returned. Every call clears the wake flag, so a drain that stopped halfway (exception)
|
|
418
|
+
/// still gets woken by the next push.
|
|
419
|
+
#[no_mangle]
|
|
420
|
+
pub unsafe extern "C" fn akan_native_poll(buf: *mut u8, cap: u32) -> u32 {
|
|
421
|
+
let mut q = QUEUE.lock().unwrap();
|
|
422
|
+
q.wake_pending = false;
|
|
423
|
+
STATS.polls.fetch_add(1, Ordering::Relaxed);
|
|
424
|
+
match q.items.front() {
|
|
425
|
+
None => 0,
|
|
426
|
+
Some(m) if m.len() > cap as usize => m.len() as u32,
|
|
427
|
+
Some(_) => {
|
|
428
|
+
let m = q.items.pop_front().unwrap();
|
|
429
|
+
if m[0] == KIND_EVENT {
|
|
430
|
+
let watch = u64::from_le_bytes(m[1..9].try_into().unwrap());
|
|
431
|
+
if watch != 0 {
|
|
432
|
+
WATCH_TAKEN.fetch_max(watch, Ordering::AcqRel);
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
std::ptr::copy_nonoverlapping(m.as_ptr(), buf, m.len());
|
|
436
|
+
STATS.frames_out.fetch_add(1, Ordering::Relaxed);
|
|
437
|
+
m.len() as u32
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
/// Completes a pending IPC request. Returns at once; the response is delivered on the main thread
|
|
443
|
+
/// (responding from the Worker would block it while the main thread is busy).
|
|
444
|
+
#[no_mangle]
|
|
445
|
+
pub unsafe extern "C" fn akan_native_respond(req_id: u64, status: u16, content_type: *const c_char, body: *const u8, len: u32) {
|
|
446
|
+
let Some((_, responder)) = PENDING.lock().unwrap().remove(&req_id) else {
|
|
447
|
+
return; // the page reloaded meanwhile
|
|
448
|
+
};
|
|
449
|
+
let ct = if content_type.is_null() { "application/json".to_string() } else { CStr::from_ptr(content_type).to_string_lossy().into_owned() };
|
|
450
|
+
let body = if len == 0 || body.is_null() { Vec::new() } else { std::slice::from_raw_parts(body, len as usize).to_vec() };
|
|
451
|
+
// A panic here would abort the process (extern "C"): a bad status or header is a 500 instead.
|
|
452
|
+
let resp = Response::builder()
|
|
453
|
+
.status(status)
|
|
454
|
+
.header(CONTENT_TYPE, ct)
|
|
455
|
+
.header("Cache-Control", "no-store")
|
|
456
|
+
.body(body)
|
|
457
|
+
.unwrap_or_else(|e| text(500, &e.to_string()));
|
|
458
|
+
send(UserEvent::Respond(responder, resp));
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
/// Evaluates JS in a webview (main thread). Used for host → page events.
|
|
462
|
+
#[no_mangle]
|
|
463
|
+
pub unsafe extern "C" fn akan_native_emit(webview_id: u32, js: *const c_char) {
|
|
464
|
+
if js.is_null() {
|
|
465
|
+
return;
|
|
466
|
+
}
|
|
467
|
+
let js = CStr::from_ptr(js).to_string_lossy().into_owned();
|
|
468
|
+
send(UserEvent::Emit { webview_id, js });
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
/// Serves `path` at /__akan_native/file/<id> for the rest of the session.
|
|
472
|
+
#[no_mangle]
|
|
473
|
+
pub unsafe extern "C" fn akan_native_register_file(id: *const c_char, path: *const c_char, mime: *const c_char) {
|
|
474
|
+
if id.is_null() || path.is_null() {
|
|
475
|
+
return;
|
|
476
|
+
}
|
|
477
|
+
let id = CStr::from_ptr(id).to_string_lossy().into_owned();
|
|
478
|
+
let path = PathBuf::from(CStr::from_ptr(path).to_string_lossy().into_owned());
|
|
479
|
+
let mime = if mime.is_null() { asset_mime(&id) } else { CStr::from_ptr(mime).to_string_lossy().into_owned() };
|
|
480
|
+
FILES.lock().unwrap().insert(id, (path, mime));
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
/// Stops serving a FileRef ($bridge.release, ABI 0.2). 1 when the id was registered.
|
|
484
|
+
#[no_mangle]
|
|
485
|
+
pub unsafe extern "C" fn akan_native_unregister_file(id: *const c_char) -> u8 {
|
|
486
|
+
if id.is_null() {
|
|
487
|
+
return 0;
|
|
488
|
+
}
|
|
489
|
+
let id = CStr::from_ptr(id).to_string_lossy().into_owned();
|
|
490
|
+
u8::from(FILES.lock().unwrap().remove(&id).is_some())
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
/// Ends the app. Also the host's "yes" to a quit request (quitRequested).
|
|
494
|
+
#[no_mangle]
|
|
495
|
+
pub extern "C" fn akan_native_quit(code: i32) {
|
|
496
|
+
QUITTING.store(true, Ordering::Release);
|
|
497
|
+
send(UserEvent::Quit(code));
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
/// The host's "no" to a quitRequested with reason "session": AppKit cancels the logout, restart or
|
|
501
|
+
/// shutdown. For other quit requests the shell already said no to AppKit, so this does nothing.
|
|
502
|
+
/// The C ABI version (docs/architecture.md §9): major << 16 | minor. main.ts refuses a library of
|
|
503
|
+
/// another major version right after loading it.
|
|
504
|
+
pub const ABI: u32 = 2; // 0.2: akan_native_unregister_file
|
|
505
|
+
|
|
506
|
+
#[no_mangle]
|
|
507
|
+
pub extern "C" fn akan_native_abi() -> u32 {
|
|
508
|
+
ABI
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
/// Why akan_native_run failed, for the message main.ts shows (and the crash marker later).
|
|
512
|
+
static LAST_ERROR: Mutex<String> = Mutex::new(String::new());
|
|
513
|
+
|
|
514
|
+
fn set_last_error(message: &str) {
|
|
515
|
+
*LAST_ERROR.lock().unwrap_or_else(|e| e.into_inner()) = message.to_string();
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
/// Copies the last error (UTF-8, not NUL-terminated) into `buf`; returns its full length.
|
|
519
|
+
///
|
|
520
|
+
/// # Safety
|
|
521
|
+
/// `buf` must hold `cap` writable bytes (or be null with `cap` 0).
|
|
522
|
+
#[no_mangle]
|
|
523
|
+
pub unsafe extern "C" fn akan_native_last_error(buf: *mut u8, cap: usize) -> usize {
|
|
524
|
+
let text = LAST_ERROR.lock().unwrap_or_else(|e| e.into_inner()).clone();
|
|
525
|
+
if !buf.is_null() {
|
|
526
|
+
std::ptr::copy_nonoverlapping(text.as_ptr(), buf, text.len().min(cap));
|
|
527
|
+
}
|
|
528
|
+
text.len()
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
/// Called by main.ts before it starts the plugin host Worker, so no other akan-native thread runs yet.
|
|
532
|
+
/// Release builds (`dev` 0) drop the engines' debugging variables: a WEBVIEW2_* or WEBKIT_* setting
|
|
533
|
+
/// in the user's environment would open a debugger port or switch off WebKit's sandbox, and
|
|
534
|
+
/// SSLKEYLOGFILE would log TLS keys (Tauri CEF #15995). The debug port is never taken from argv.
|
|
535
|
+
#[no_mangle]
|
|
536
|
+
pub extern "C" fn akan_native_init(dev: u8) -> i32 {
|
|
537
|
+
if dev == 0 {
|
|
538
|
+
let dropped: Vec<String> = std::env::vars_os()
|
|
539
|
+
.filter_map(|(k, _)| k.into_string().ok())
|
|
540
|
+
.filter(|k| k.starts_with("WEBVIEW2_") || k.starts_with("WEBKIT_INSPECTOR") || k.starts_with("WEBKIT_DISABLE_SANDBOX") || k == "WEBKIT_FORCE_SANDBOX" || k == "SSLKEYLOGFILE")
|
|
541
|
+
.collect();
|
|
542
|
+
for key in &dropped {
|
|
543
|
+
std::env::remove_var(key);
|
|
544
|
+
}
|
|
545
|
+
if !dropped.is_empty() {
|
|
546
|
+
log!("release build: ignoring the engine settings {}", dropped.join(", "));
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
0
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
#[no_mangle]
|
|
553
|
+
pub extern "C" fn akan_native_quit_cancel() {
|
|
554
|
+
send(UserEvent::CancelTerminate);
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
/// 1 when an external open may happen now (and counts it), 0 when the one-per-second limit (L0)
|
|
558
|
+
/// was reached. The page's links and the plugins' opens share this one limit.
|
|
559
|
+
#[no_mangle]
|
|
560
|
+
pub extern "C" fn akan_native_external_open_allowed() -> u8 {
|
|
561
|
+
navigation::external_open_allowed() as u8
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
/// Runs a shell command on the main thread: `{"op":"window.setTitle","title":"…"}` etc.
|
|
565
|
+
/// The answer arrives as a native event `{"type":"shellReply","id":…,"ok":…,"result"|"error":…}`.
|
|
566
|
+
#[no_mangle]
|
|
567
|
+
pub unsafe extern "C" fn akan_native_shell(id: u64, json: *const c_char) {
|
|
568
|
+
if json.is_null() {
|
|
569
|
+
return;
|
|
570
|
+
}
|
|
571
|
+
let json = CStr::from_ptr(json).to_string_lossy().into_owned();
|
|
572
|
+
send(UserEvent::Shell { id, json });
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
fn reply(id: u64, result: Result<String, String>) {
|
|
576
|
+
match result {
|
|
577
|
+
Ok(value) => push_event(&format!(r#"{{"type":"shellReply","id":{id},"ok":true,"result":{value}}}"#)),
|
|
578
|
+
Err(message) => push_event(&format!(r#"{{"type":"shellReply","id":{id},"ok":false,"error":{}}}"#, json::quote(&message))),
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
/// Window state as JSON, in logical pixels (CSS px). tao applies several setters asynchronously on
|
|
583
|
+
/// macOS (set_title, set_inner_size, …), so a state read right after a setter can still show the old
|
|
584
|
+
/// value; `title` lets setTitle report what it set.
|
|
585
|
+
fn window_state(window: &tao::window::Window, webview: Option<&WebView>) -> String {
|
|
586
|
+
window_state_with(window, webview, &Requested::default())
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
/// The window's minimum inner size, logical points.
|
|
590
|
+
const MIN_INNER: (f64, f64) = (320.0, 240.0);
|
|
591
|
+
|
|
592
|
+
/// What a shell op just asked for. On macOS tao applies titles, sizes, positions, zoom and full
|
|
593
|
+
/// screen asynchronously on the main queue (tao/src/platform_impl/macos/util/async.rs), so the
|
|
594
|
+
/// window still reports the old values right after the call; the reply shows the requested ones.
|
|
595
|
+
/// (A maximize reports maximized: true; the zoomed frame is only known once it happened.)
|
|
596
|
+
#[derive(Default)]
|
|
597
|
+
struct Requested<'a> {
|
|
598
|
+
title: Option<&'a str>,
|
|
599
|
+
size: Option<(f64, f64)>,
|
|
600
|
+
position: Option<(f64, f64)>,
|
|
601
|
+
maximized: Option<bool>,
|
|
602
|
+
minimized: Option<bool>,
|
|
603
|
+
fullscreen: Option<bool>,
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
/// Logical inner size. On macOS wry replaces the window's content view with its own parent
|
|
607
|
+
/// view, so tao's inner_size() (and the size in its Resized events) keeps reporting the size
|
|
608
|
+
/// the window was created with. The webview fills the window, so its frame is the inner size;
|
|
609
|
+
/// tauri-runtime-wry does the same (src/lib.rs:578-590, 5314-5329).
|
|
610
|
+
fn inner_size(window: &tao::window::Window, webview: Option<&WebView>) -> LogicalSize<f64> {
|
|
611
|
+
#[cfg(target_os = "macos")]
|
|
612
|
+
if let Some(wv) = webview {
|
|
613
|
+
use wry::WebViewExtMacOS;
|
|
614
|
+
let frame = wv.webview().frame();
|
|
615
|
+
return LogicalSize::new(frame.size.width, frame.size.height);
|
|
616
|
+
}
|
|
617
|
+
let _ = webview;
|
|
618
|
+
window.inner_size().to_logical(window.scale_factor())
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
fn theme_name(theme: tao::window::Theme) -> &'static str {
|
|
622
|
+
match theme {
|
|
623
|
+
tao::window::Theme::Dark => "dark",
|
|
624
|
+
_ => "light",
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
/// The theme a window is drawn in. Linux: TAO's answer is Light unless the app set one (its portal
|
|
629
|
+
/// code needs its dbus feature), so the shell's own reading of GTK and the portal counts.
|
|
630
|
+
fn window_theme(window: &tao::window::Window) -> tao::window::Theme {
|
|
631
|
+
#[cfg(target_os = "linux")]
|
|
632
|
+
{
|
|
633
|
+
let _ = window;
|
|
634
|
+
linux::appearance::theme()
|
|
635
|
+
}
|
|
636
|
+
#[cfg(not(target_os = "linux"))]
|
|
637
|
+
window.theme()
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
fn window_state_with(window: &tao::window::Window, webview: Option<&WebView>, req: &Requested) -> String {
|
|
641
|
+
let scale = window.scale_factor();
|
|
642
|
+
let (width, height) = req.size.unwrap_or_else(|| {
|
|
643
|
+
let size = inner_size(window, webview);
|
|
644
|
+
(size.width, size.height)
|
|
645
|
+
});
|
|
646
|
+
let (x, y) = req
|
|
647
|
+
.position
|
|
648
|
+
.or_else(|| window.outer_position().ok().map(|p| { let l = p.to_logical::<f64>(scale); (l.x, l.y) }))
|
|
649
|
+
.unwrap_or((0.0, 0.0));
|
|
650
|
+
format!(
|
|
651
|
+
r#"{{"x":{x},"y":{y},"width":{width},"height":{height},"maximized":{},"minimized":{},"fullscreen":{},"focused":{},"visible":{},"theme":"{}","title":{}}}"#,
|
|
652
|
+
req.maximized.unwrap_or_else(|| window.is_maximized()),
|
|
653
|
+
req.minimized.unwrap_or_else(|| window.is_minimized()),
|
|
654
|
+
req.fullscreen.unwrap_or_else(|| window.fullscreen().is_some()),
|
|
655
|
+
window.is_focused(),
|
|
656
|
+
window.is_visible(),
|
|
657
|
+
theme_name(window_theme(window)),
|
|
658
|
+
json::quote(req.title.map(str::to_string).unwrap_or_else(|| window.title()).as_str())
|
|
659
|
+
)
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
/// One window's shell op: everything but the ops on the set of windows (Windows::shell).
|
|
663
|
+
fn window_op(window: &tao::window::Window, webview: Option<&WebView>, cmd: &json::V, op: &str) -> Result<String, String> {
|
|
664
|
+
let num = |k: &str| cmd.get(k).and_then(|v| v.as_f64()).ok_or_else(|| format!("{k} must be a number"));
|
|
665
|
+
let flag = |k: &str| cmd.get(k).and_then(|v| v.as_bool()).ok_or_else(|| format!("{k} must be a boolean"));
|
|
666
|
+
let mut req = Requested::default();
|
|
667
|
+
match op {
|
|
668
|
+
"window.getState" => return Ok(window_state(window, webview)),
|
|
669
|
+
"window.setTitle" => {
|
|
670
|
+
let title = cmd.get("title").and_then(|v| v.as_str()).ok_or("title must be a string")?;
|
|
671
|
+
window.set_title(title);
|
|
672
|
+
req.title = Some(title);
|
|
673
|
+
}
|
|
674
|
+
"window.setSize" => {
|
|
675
|
+
let (w, h) = (num("width")?, num("height")?);
|
|
676
|
+
if !(w >= 1.0 && h >= 1.0) {
|
|
677
|
+
return Err("width and height must be positive".into());
|
|
678
|
+
}
|
|
679
|
+
window.set_inner_size(LogicalSize::new(w, h));
|
|
680
|
+
req.size = Some((w.max(MIN_INNER.0), h.max(MIN_INNER.1)));
|
|
681
|
+
}
|
|
682
|
+
"window.setPosition" => {
|
|
683
|
+
let (x, y) = (num("x")?, num("y")?);
|
|
684
|
+
window.set_outer_position(tao::dpi::LogicalPosition::new(x, y));
|
|
685
|
+
req.position = Some((x, y));
|
|
686
|
+
}
|
|
687
|
+
"window.center" => {
|
|
688
|
+
if let Some(monitor) = window.current_monitor() {
|
|
689
|
+
let scale = window.scale_factor();
|
|
690
|
+
let screen = monitor.size().to_logical::<f64>(monitor.scale_factor());
|
|
691
|
+
let origin = monitor.position().to_logical::<f64>(monitor.scale_factor());
|
|
692
|
+
let size = window.outer_size().to_logical::<f64>(scale);
|
|
693
|
+
let (x, y) = (origin.x + (screen.width - size.width) / 2.0, origin.y + (screen.height - size.height) / 2.0);
|
|
694
|
+
window.set_outer_position(tao::dpi::LogicalPosition::new(x, y));
|
|
695
|
+
req.position = Some((x, y));
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
"window.minimize" => {
|
|
699
|
+
window.set_minimized(true);
|
|
700
|
+
req.minimized = Some(true);
|
|
701
|
+
}
|
|
702
|
+
"window.maximize" => {
|
|
703
|
+
window.set_maximized(true);
|
|
704
|
+
req.maximized = Some(true);
|
|
705
|
+
}
|
|
706
|
+
"window.unmaximize" => {
|
|
707
|
+
window.set_maximized(false);
|
|
708
|
+
req.maximized = Some(false);
|
|
709
|
+
}
|
|
710
|
+
"window.restore" => {
|
|
711
|
+
window.set_minimized(false);
|
|
712
|
+
window.set_maximized(false);
|
|
713
|
+
window.set_focus();
|
|
714
|
+
(req.minimized, req.maximized) = (Some(false), Some(false));
|
|
715
|
+
}
|
|
716
|
+
"window.setFullscreen" => {
|
|
717
|
+
let value = flag("value")?;
|
|
718
|
+
window.set_fullscreen(if value { Some(tao::window::Fullscreen::Borderless(None)) } else { None });
|
|
719
|
+
req.fullscreen = Some(value);
|
|
720
|
+
}
|
|
721
|
+
"window.setAlwaysOnTop" => window.set_always_on_top(flag("value")?),
|
|
722
|
+
"window.show" => window.set_visible(true),
|
|
723
|
+
"window.hide" => window.set_visible(false),
|
|
724
|
+
"window.focus" => window.set_focus(),
|
|
725
|
+
// Unlike window.restore, keeps a maximized window maximized (single-instance).
|
|
726
|
+
"window.unminimize" => {
|
|
727
|
+
window.set_minimized(false);
|
|
728
|
+
req.minimized = Some(false);
|
|
729
|
+
}
|
|
730
|
+
// D3: must run while the left button is still down (tao drag_window docs); the page calls it on mousedown.
|
|
731
|
+
"window.startDragging" => window.drag_window().map_err(|e| e.to_string())?,
|
|
732
|
+
_ => return Err(format!("unknown op {op}")),
|
|
733
|
+
}
|
|
734
|
+
Ok(window_state_with(window, webview, &req))
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
// ───────────────────────── config ─────────────────────────
|
|
738
|
+
|
|
739
|
+
struct Config {
|
|
740
|
+
title: String,
|
|
741
|
+
width: f64,
|
|
742
|
+
height: f64,
|
|
743
|
+
app_dir: PathBuf,
|
|
744
|
+
init_js: String,
|
|
745
|
+
devtools: bool,
|
|
746
|
+
menu: bool,
|
|
747
|
+
background_light: (u8, u8, u8, u8),
|
|
748
|
+
background_dark: (u8, u8, u8, u8),
|
|
749
|
+
/// "regular" | "prohibited" (tests: do not steal focus)
|
|
750
|
+
activation: String,
|
|
751
|
+
/// Saved outer position from the launch phase (window-state), logical points.
|
|
752
|
+
position: Option<(f64, f64)>,
|
|
753
|
+
maximized: bool,
|
|
754
|
+
/// akan-native dev --hmr (dev builds only, main.ts): pages come from this gateway (devproxy.rs).
|
|
755
|
+
dev_server: Option<String>,
|
|
756
|
+
/// The main window's first page (dev builds only, main.ts), e.g. the page a framework's dev server answers.
|
|
757
|
+
start_path: String,
|
|
758
|
+
/// Where the webview keeps its storage and cache (Windows, Linux; WKWebView picks its own).
|
|
759
|
+
data_dir: Option<PathBuf>,
|
|
760
|
+
/// Window icon (Windows, Linux): [u32 width LE][u32 height LE][RGBA], written by the CLI.
|
|
761
|
+
icon: Option<PathBuf>,
|
|
762
|
+
/// app.id (Linux: the desktop entry the dock plugin's launcher badge names).
|
|
763
|
+
app_id: String,
|
|
764
|
+
/// security.shell.externalSchemes (L0): schemes links may also hand to the OS (navigation.rs).
|
|
765
|
+
external_schemes: Vec<String>,
|
|
766
|
+
/// desktop.recovery "reload": a page that ends is always loaded again, and a browser process that ends
|
|
767
|
+
/// is the host's to relaunch (host.ts), instead of an error page and a quit.
|
|
768
|
+
recovery_reload: bool,
|
|
769
|
+
/// The main window from its first frame (desktop.window, or the launch phase): borderless fullscreen on
|
|
770
|
+
/// the display it is placed on, and no taskbar button (Windows, Linux).
|
|
771
|
+
fullscreen: bool,
|
|
772
|
+
skip_taskbar: bool,
|
|
773
|
+
/// desktop.screenCapture "auto" (Windows): the page captures the first screen without the picker.
|
|
774
|
+
screen_capture_auto: bool,
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
#[derive(Clone, Copy, PartialEq)]
|
|
778
|
+
struct Colors {
|
|
779
|
+
light: (u8, u8, u8, u8),
|
|
780
|
+
dark: (u8, u8, u8, u8),
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
/// SH-3 background for the current appearance, on the window and the webview.
|
|
784
|
+
fn paint(window: &tao::window::Window, webview: Option<&WebView>, colors: &Colors, dark: bool) {
|
|
785
|
+
let c = if dark { colors.dark } else { colors.light };
|
|
786
|
+
window.set_background_color(Some(c));
|
|
787
|
+
if let Some(wv) = webview {
|
|
788
|
+
let _ = wv.set_background_color(c);
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
fn parse_color(s: &str) -> Option<(u8, u8, u8, u8)> {
|
|
793
|
+
let hex = s.strip_prefix('#')?;
|
|
794
|
+
let byte = |i: usize| u8::from_str_radix(hex.get(i..i + 2)?, 16).ok();
|
|
795
|
+
match hex.len() {
|
|
796
|
+
6 => Some((byte(0)?, byte(2)?, byte(4)?, 255)),
|
|
797
|
+
8 => Some((byte(0)?, byte(2)?, byte(4)?, byte(6)?)),
|
|
798
|
+
_ => None,
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
fn parse_config(s: &str) -> Result<Config, String> {
|
|
803
|
+
let j = json::parse(s)?;
|
|
804
|
+
let get_s = |k: &str| j.get(k).and_then(|v| v.as_str()).map(str::to_string);
|
|
805
|
+
let get_n = |k: &str, d: f64| j.get(k).and_then(|v| v.as_f64()).unwrap_or(d);
|
|
806
|
+
let get_b = |k: &str, d: bool| j.get(k).and_then(|v| v.as_bool()).unwrap_or(d);
|
|
807
|
+
let light = get_s("backgroundColor").and_then(|c| parse_color(&c)).unwrap_or((255, 255, 255, 255));
|
|
808
|
+
Ok(Config {
|
|
809
|
+
title: get_s("title").unwrap_or_else(|| "akan-native".into()),
|
|
810
|
+
width: get_n("width", 1024.0),
|
|
811
|
+
height: get_n("height", 720.0),
|
|
812
|
+
app_dir: PathBuf::from(get_s("appDir").ok_or("appDir is required")?),
|
|
813
|
+
init_js: get_s("initJs").ok_or("initJs is required")?,
|
|
814
|
+
devtools: get_b("devtools", false),
|
|
815
|
+
menu: get_b("menu", true),
|
|
816
|
+
background_light: light,
|
|
817
|
+
background_dark: get_s("backgroundColorDark").and_then(|c| parse_color(&c)).unwrap_or(light),
|
|
818
|
+
activation: get_s("activation").unwrap_or_else(|| "regular".into()),
|
|
819
|
+
position: match (j.get("x").and_then(|v| v.as_f64()), j.get("y").and_then(|v| v.as_f64())) {
|
|
820
|
+
(Some(x), Some(y)) if x.is_finite() && y.is_finite() => Some((x, y)),
|
|
821
|
+
_ => None,
|
|
822
|
+
},
|
|
823
|
+
maximized: get_b("maximized", false),
|
|
824
|
+
dev_server: get_s("devServer"),
|
|
825
|
+
start_path: match get_s("startPath") {
|
|
826
|
+
Some(path) if is_app_path(&path) => path,
|
|
827
|
+
Some(path) => return Err(format!("startPath must be an app path like /settings, not {path:?}")),
|
|
828
|
+
None => "/".into(),
|
|
829
|
+
},
|
|
830
|
+
data_dir: get_s("dataDir").map(PathBuf::from),
|
|
831
|
+
icon: get_s("icon").map(PathBuf::from),
|
|
832
|
+
app_id: get_s("appId").unwrap_or_default(),
|
|
833
|
+
external_schemes: match j.get("externalSchemes") {
|
|
834
|
+
Some(json::V::Arr(a)) => a.iter().filter_map(|v| v.as_str().map(str::to_string)).collect(),
|
|
835
|
+
_ => Vec::new(),
|
|
836
|
+
},
|
|
837
|
+
recovery_reload: match get_s("recovery").as_deref() {
|
|
838
|
+
None | Some("errorPage") => false,
|
|
839
|
+
Some("reload") => true,
|
|
840
|
+
Some(other) => return Err(format!("recovery must be \"errorPage\" or \"reload\", not {other:?}")),
|
|
841
|
+
},
|
|
842
|
+
fullscreen: get_b("fullscreen", false),
|
|
843
|
+
skip_taskbar: get_b("skipTaskbar", false),
|
|
844
|
+
screen_capture_auto: match get_s("screenCapture").as_deref() {
|
|
845
|
+
None | Some("picker") => false,
|
|
846
|
+
Some("auto") => true,
|
|
847
|
+
Some(other) => return Err(format!("screenCapture must be \"picker\" or \"auto\", not {other:?}")),
|
|
848
|
+
},
|
|
849
|
+
})
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
// ───────────────────────── custom protocol ─────────────────────────
|
|
853
|
+
|
|
854
|
+
fn text(status: u16, body: &str) -> Response<Vec<u8>> {
|
|
855
|
+
Response::builder().status(status).header(CONTENT_TYPE, "text/plain; charset=utf-8").body(body.as_bytes().to_vec()).unwrap()
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
/// Reads a file off the main thread, then responds on the main thread. A Range request reads only
|
|
859
|
+
/// that part (at most contract::MAX_RANGE_BYTES, Tauri's 1000 KiB: media elements ask for the rest,
|
|
860
|
+
/// so a large video is read piece by piece); a request without one gets the whole file.
|
|
861
|
+
fn respond_file(responder: RequestAsyncResponder, path: PathBuf, mime: String, kind: Served, range: Option<String>) {
|
|
862
|
+
std::thread::spawn(move || {
|
|
863
|
+
let resp = match read_file(&path, &mime, kind, range.as_deref()) {
|
|
864
|
+
Ok(resp) => resp,
|
|
865
|
+
Err(e) if e.kind() == std::io::ErrorKind::NotFound => text(404, "not found"),
|
|
866
|
+
Err(e) => text(500, &e.to_string()),
|
|
867
|
+
};
|
|
868
|
+
send(UserEvent::Respond(responder, resp));
|
|
869
|
+
});
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
/// What a file response is: an app asset (index.html is not cached) or a FileRef, which a plugin
|
|
873
|
+
/// registered and whose content the app does not control.
|
|
874
|
+
#[derive(Clone, Copy, PartialEq, Eq)]
|
|
875
|
+
enum Served {
|
|
876
|
+
Asset,
|
|
877
|
+
Index,
|
|
878
|
+
FileRef,
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
/// A FileRef bigger than this, requested without Range, gets a warning (read_file).
|
|
882
|
+
const LARGE_WHOLE_FILE: u64 = 32 << 20;
|
|
883
|
+
|
|
884
|
+
fn read_file(path: &Path, mime: &str, kind: Served, range: Option<&str>) -> std::io::Result<Response<Vec<u8>>> {
|
|
885
|
+
use std::io::{Read, Seek, SeekFrom};
|
|
886
|
+
let mut file = std::fs::File::open(path)?;
|
|
887
|
+
let total = file.metadata()?.len();
|
|
888
|
+
let mut b = Response::builder().header(CONTENT_TYPE, mime).header("Accept-Ranges", "bytes");
|
|
889
|
+
if kind == Served::Index {
|
|
890
|
+
b = b.header("Cache-Control", "no-cache");
|
|
891
|
+
}
|
|
892
|
+
// A FileRef (a picked, downloaded or written file) is never the app's document: no MIME sniffing,
|
|
893
|
+
// not embeddable by other origins, and anything but plain media opens sandboxed, with an opaque
|
|
894
|
+
// origin that neither the bridge nor the page trusts (kernel.ts fileRefSandboxed; N1).
|
|
895
|
+
if kind == Served::FileRef {
|
|
896
|
+
b = b.header("X-Content-Type-Options", "nosniff").header("Cross-Origin-Resource-Policy", "same-origin");
|
|
897
|
+
if routes::file_ref_sandboxed(mime) {
|
|
898
|
+
b = b.header("Content-Security-Policy", "sandbox");
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
// A header that is not one supported range is ignored (kernel.ts parseRange): the whole file.
|
|
902
|
+
let (b, body) = match parse_range(range, total) {
|
|
903
|
+
RangeAnswer::Whole => {
|
|
904
|
+
// WRY has no streaming responses: a whole file is read into memory. Big FileRefs should be
|
|
905
|
+
// read in Range pieces (fileStream / fileBlob in @akanjs/native/core; architecture review stage 4).
|
|
906
|
+
if kind == Served::FileRef && total > LARGE_WHOLE_FILE {
|
|
907
|
+
eprintln!("[akan-native] {} ({} MB) was requested whole: read big files with fileStream() from @akanjs/native/core (Range requests)", path.display(), total >> 20);
|
|
908
|
+
}
|
|
909
|
+
let mut bytes = Vec::with_capacity((total as usize).min(64 << 20));
|
|
910
|
+
file.read_to_end(&mut bytes)?;
|
|
911
|
+
(b.status(200), bytes)
|
|
912
|
+
}
|
|
913
|
+
RangeAnswer::Part(start, end) => {
|
|
914
|
+
let mut bytes = vec![0; (end - start + 1) as usize];
|
|
915
|
+
file.seek(SeekFrom::Start(start))?;
|
|
916
|
+
file.read_exact(&mut bytes)?;
|
|
917
|
+
(b.status(206).header("Content-Range", format!("bytes {start}-{end}/{total}")), bytes)
|
|
918
|
+
}
|
|
919
|
+
RangeAnswer::Unsatisfiable => (b.status(416).header("Content-Range", format!("bytes */{total}")), Vec::new()),
|
|
920
|
+
};
|
|
921
|
+
// A registered file's type comes from a plugin: one that is no valid header value is a 500, not a panic.
|
|
922
|
+
Ok(b.body(body).unwrap_or_else(|e| text(500, &e.to_string())))
|
|
923
|
+
}
|
|
924
|
+
|
|
925
|
+
/// SEC-1: WebKit sends no Origin header on same-origin fetch POSTs to a custom scheme, only a
|
|
926
|
+
/// Referer; opaque-origin frames send `Origin: null` or `Referer: about:srcdoc`. Custom schemes
|
|
927
|
+
/// get no CORS preflight, so the header check is the gate (docs/research/desktop-macos.md §4.4).
|
|
928
|
+
fn ipc_allowed(req: &Request<Vec<u8>>) -> bool {
|
|
929
|
+
let header = |name: &str| req.headers().get(name).and_then(|v| v.to_str().ok()).unwrap_or("");
|
|
930
|
+
let origin = header("origin");
|
|
931
|
+
// WebView2 (Chromium) always sends Origin on a POST; WebKit only a Referer on the same origin.
|
|
932
|
+
let origin_ok = if origin.is_empty() { header("referer").strip_prefix(ORIGIN).is_some_and(|path| path.is_empty() || path.starts_with('/')) } else { origin == ORIGIN };
|
|
933
|
+
origin_ok && req.headers().contains_key("x-akan-native-ipc")
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
/// Request headers the dev gateway does not get: devproxy writes the framing ones itself, and no validators, since
|
|
937
|
+
/// the answer is never a 304. Everything else goes, authorization included, as the iOS and Android hosts pass it.
|
|
938
|
+
const DEV_SKIP: [&str; 8] = [
|
|
939
|
+
"host",
|
|
940
|
+
"connection",
|
|
941
|
+
"keep-alive",
|
|
942
|
+
"content-length",
|
|
943
|
+
"transfer-encoding",
|
|
944
|
+
"accept-encoding",
|
|
945
|
+
"if-none-match",
|
|
946
|
+
"if-modified-since",
|
|
947
|
+
];
|
|
948
|
+
/// Hop-by-hop and framing headers of the gateway's reply: WebKit gets the decoded body as it is.
|
|
949
|
+
const DEV_DROP: [&str; 5] = ["connection", "keep-alive", "transfer-encoding", "content-length", "content-encoding"];
|
|
950
|
+
static DEV_WARNED: AtomicBool = AtomicBool::new(false);
|
|
951
|
+
|
|
952
|
+
/// Fetches an app:// request from the dev gateway (akan-native dev --hmr). Runs on its own thread.
|
|
953
|
+
fn dev_fetch(base: &str, req: &Request<Vec<u8>>) -> Result<Response<Vec<u8>>, String> {
|
|
954
|
+
use wry::http::header::{HeaderName, HeaderValue};
|
|
955
|
+
let authority = devproxy::authority(base).ok_or_else(|| format!("devServer {base:?} is not http://127.0.0.1:<port>"))?;
|
|
956
|
+
let target = req.uri().path_and_query().map_or("/", |p| p.as_str());
|
|
957
|
+
let headers: Vec<(String, String)> = req
|
|
958
|
+
.headers()
|
|
959
|
+
.iter()
|
|
960
|
+
.filter(|(name, _)| !DEV_SKIP.contains(&name.as_str()))
|
|
961
|
+
.filter_map(|(name, value)| Some((name.as_str().to_string(), value.to_str().ok()?.to_string())))
|
|
962
|
+
.collect();
|
|
963
|
+
let reply = devproxy::fetch(authority, req.method().as_str(), target, &headers, req.body())?;
|
|
964
|
+
let mut builder = Response::builder().status(reply.status);
|
|
965
|
+
for (name, value) in reply.headers {
|
|
966
|
+
if DEV_DROP.iter().any(|d| name.eq_ignore_ascii_case(d)) {
|
|
967
|
+
continue;
|
|
968
|
+
}
|
|
969
|
+
if let (Ok(name), Ok(value)) = (HeaderName::from_bytes(name.as_bytes()), HeaderValue::from_str(&value)) {
|
|
970
|
+
builder = builder.header(name, value);
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
builder.body(reply.body).map_err(|e| e.to_string())
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
fn handle_request(app_dir: &PathBuf, init_js: &str, dev_server: Option<&str>, webview_id: u32, req: Request<Vec<u8>>, responder: RequestAsyncResponder) {
|
|
977
|
+
let path = req.uri().path().to_string();
|
|
978
|
+
let range = req.headers().get("range").and_then(|v| v.to_str().ok()).map(str::to_string);
|
|
979
|
+
// akan-native dev --hmr: everything outside /__akan_native/* comes from the dev gateway; the page stays on
|
|
980
|
+
// app://localhost. Without the gateway (akan-native dev ended) the bundled files are served.
|
|
981
|
+
if let Some(base) = dev_server.filter(|_| !is_host_path(&path)) {
|
|
982
|
+
let (base, app_dir) = (base.to_string(), app_dir.clone());
|
|
983
|
+
std::thread::spawn(move || match dev_fetch(&base, &req) {
|
|
984
|
+
Ok(resp) => send(UserEvent::Respond(responder, resp)),
|
|
985
|
+
Err(e) => {
|
|
986
|
+
if !DEV_WARNED.swap(true, Ordering::AcqRel) {
|
|
987
|
+
log!("dev server {base}: {e}; serving the bundled files");
|
|
988
|
+
}
|
|
989
|
+
match route(&path, |rel| asset_path(&app_dir, rel).is_some_and(|p| p.is_file())) {
|
|
990
|
+
Route::Asset(rel) => {
|
|
991
|
+
let mime = asset_mime(&rel);
|
|
992
|
+
respond_asset(responder, &app_dir, &rel, mime, range);
|
|
993
|
+
}
|
|
994
|
+
_ => send(UserEvent::Respond(responder, text(404, "not found"))),
|
|
995
|
+
}
|
|
996
|
+
}
|
|
997
|
+
});
|
|
998
|
+
return;
|
|
999
|
+
}
|
|
1000
|
+
let exists = |rel: &str| asset_path(app_dir, rel).is_some_and(|p| p.is_file());
|
|
1001
|
+
match route(&path, exists) {
|
|
1002
|
+
// Every window gets the same boot data plus its own id (Tauri injects the current window
|
|
1003
|
+
// label the same way, tauri/crates/tauri/src/manager/webview.rs:186-191).
|
|
1004
|
+
Route::Init => responder.respond(
|
|
1005
|
+
Response::builder()
|
|
1006
|
+
.status(200)
|
|
1007
|
+
.header(CONTENT_TYPE, "text/javascript; charset=utf-8")
|
|
1008
|
+
.header("Cache-Control", "no-cache")
|
|
1009
|
+
.body(format!("{init_js}window.__AKAN_NATIVE__.windowId={webview_id};{}\n", engine_info()).into_bytes())
|
|
1010
|
+
.unwrap(),
|
|
1011
|
+
),
|
|
1012
|
+
Route::Ipc => {
|
|
1013
|
+
if req.method() != "POST" {
|
|
1014
|
+
return responder.respond(text(405, "POST only"));
|
|
1015
|
+
}
|
|
1016
|
+
if !ipc_allowed(&req) {
|
|
1017
|
+
log!("IPC rejected: origin={:?} referer={:?}", req.headers().get("origin"), req.headers().get("referer"));
|
|
1018
|
+
return responder.respond(text(403, "forbidden"));
|
|
1019
|
+
}
|
|
1020
|
+
if WAKE.load(Ordering::Acquire) == 0 {
|
|
1021
|
+
return responder.respond(text(503, "akan-native host is not running"));
|
|
1022
|
+
}
|
|
1023
|
+
// A page calling in a loop faster than the host answers must not grow memory without end.
|
|
1024
|
+
if PENDING.lock().unwrap().len() >= MAX_PENDING || QUEUE.lock().unwrap().items.len() >= MAX_PENDING {
|
|
1025
|
+
return responder.respond(text(503, "the plugin host is busy"));
|
|
1026
|
+
}
|
|
1027
|
+
let id = NEXT_REQ.fetch_add(1, Ordering::Relaxed);
|
|
1028
|
+
PENDING.lock().unwrap().insert(id, (webview_id, responder));
|
|
1029
|
+
push(frame(KIND_IPC, id, webview_id, req.body()));
|
|
1030
|
+
}
|
|
1031
|
+
Route::File(id) => {
|
|
1032
|
+
let entry = FILES.lock().unwrap().get(&id).cloned();
|
|
1033
|
+
match entry {
|
|
1034
|
+
Some((path, mime)) => respond_file(responder, path, mime, Served::FileRef, range),
|
|
1035
|
+
None => responder.respond(text(404, "not found")),
|
|
1036
|
+
}
|
|
1037
|
+
}
|
|
1038
|
+
Route::Asset(rel) => {
|
|
1039
|
+
let mime = asset_mime(&rel);
|
|
1040
|
+
respond_asset(responder, app_dir, &rel, mime, range);
|
|
1041
|
+
}
|
|
1042
|
+
Route::Hello | Route::NotFound => responder.respond(text(404, "not found")),
|
|
1043
|
+
}
|
|
1044
|
+
}
|
|
1045
|
+
|
|
1046
|
+
/// `rel` (from route()) inside `app_dir`, or None unless it is only plain names. A second guard
|
|
1047
|
+
/// behind route(): Path::join drops the base for an absolute path, and on Windows for a drive
|
|
1048
|
+
/// prefix ("C:/Users/…"), which would serve any file the user can read.
|
|
1049
|
+
fn asset_path(app_dir: &Path, rel: &str) -> Option<PathBuf> {
|
|
1050
|
+
let path = Path::new(rel);
|
|
1051
|
+
path.components().all(|c| matches!(c, Component::Normal(_))).then(|| app_dir.join(path))
|
|
1052
|
+
}
|
|
1053
|
+
|
|
1054
|
+
fn respond_asset(responder: RequestAsyncResponder, app_dir: &Path, rel: &str, mime: String, range: Option<String>) {
|
|
1055
|
+
match asset_path(app_dir, rel) {
|
|
1056
|
+
Some(path) => respond_file(responder, path, mime, if rel == "index.html" { Served::Index } else { Served::Asset }, range),
|
|
1057
|
+
None => send(UserEvent::Respond(responder, text(404, "not found"))),
|
|
1058
|
+
}
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1061
|
+
fn in_app(url: &str) -> bool {
|
|
1062
|
+
on_origin(url) || url.starts_with("about:")
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
/// Hands a link to the OS (navigation.rs): http(s) to the browser, mailto and tel to their apps.
|
|
1066
|
+
/// Any other scheme is refused, so the page cannot start other programs this way.
|
|
1067
|
+
fn open_external(url: &str) {
|
|
1068
|
+
if !navigation::opens_externally(url) {
|
|
1069
|
+
log!("not opening {}: only http, https, mailto, tel and security.shell.externalSchemes links leave the app", navigation::shown(url));
|
|
1070
|
+
return;
|
|
1071
|
+
}
|
|
1072
|
+
if !navigation::external_open_allowed() {
|
|
1073
|
+
log!("not opening {}: at most one link per second leaves the app", navigation::shown(url));
|
|
1074
|
+
return;
|
|
1075
|
+
}
|
|
1076
|
+
push_event(&format!(r#"{{"type":"external","url":{}}}"#, json::quote(url)));
|
|
1077
|
+
#[cfg(target_os = "macos")]
|
|
1078
|
+
macos::open_url(url);
|
|
1079
|
+
#[cfg(target_os = "windows")]
|
|
1080
|
+
win::open_url(url);
|
|
1081
|
+
#[cfg(target_os = "linux")]
|
|
1082
|
+
linux::open_url(url);
|
|
1083
|
+
}
|
|
1084
|
+
|
|
1085
|
+
/// Op families of the plugins' native parts (menu.rs, tray.rs, … on macOS; win/, linux/).
|
|
1086
|
+
#[cfg(not(target_os = "macos"))]
|
|
1087
|
+
const PLATFORM_OPS: [&str; 12] = ["menu.", "tray.", "hotkey.", "dock.", "screen.", "notify.", "camera.", "panel.", "alert.", "autostart.", "keychain.", "clipboard."];
|
|
1088
|
+
#[cfg(target_os = "windows")]
|
|
1089
|
+
const OS_NAME: &str = "Windows";
|
|
1090
|
+
#[cfg(target_os = "linux")]
|
|
1091
|
+
const OS_NAME: &str = "Linux";
|
|
1092
|
+
|
|
1093
|
+
// ───────────────────────── windows ─────────────────────────
|
|
1094
|
+
// SH-6 multi-window. Window ids are u32; the window akan_native_run opens is 1, window.create hands out
|
|
1095
|
+
// 2, 3, … (never reused). A window and its webview share the id: the webview id is the frame's
|
|
1096
|
+
// webviewId, the `window` field of native events and the `window` argument of shell ops.
|
|
1097
|
+
|
|
1098
|
+
/// What every window is built from.
|
|
1099
|
+
struct Shell {
|
|
1100
|
+
app_dir: PathBuf,
|
|
1101
|
+
init_js: Arc<str>,
|
|
1102
|
+
dev_server: Option<Arc<str>>,
|
|
1103
|
+
devtools: bool,
|
|
1104
|
+
colors: Colors,
|
|
1105
|
+
title: String,
|
|
1106
|
+
size: (f64, f64),
|
|
1107
|
+
/// false: `akan-native test` runs; showing a window does not take focus from the user's app.
|
|
1108
|
+
activate: bool,
|
|
1109
|
+
icon: Option<tao::window::Icon>,
|
|
1110
|
+
#[cfg_attr(not(target_os = "linux"), allow(dead_code))]
|
|
1111
|
+
app_id: String,
|
|
1112
|
+
recovery_reload: bool,
|
|
1113
|
+
#[cfg_attr(not(target_os = "windows"), allow(dead_code))]
|
|
1114
|
+
screen_capture_auto: bool,
|
|
1115
|
+
}
|
|
1116
|
+
|
|
1117
|
+
/// The CLI's icon.rgba (icons.ts windowIcon) as a tao icon.
|
|
1118
|
+
fn read_icon(path: &std::path::Path) -> Option<tao::window::Icon> {
|
|
1119
|
+
let bytes = std::fs::read(path).map_err(|e| log!("icon {}: {e}", path.display())).ok()?;
|
|
1120
|
+
let size = |at: usize| bytes.get(at..at + 4).map(|b| u32::from_le_bytes(b.try_into().unwrap()));
|
|
1121
|
+
let (width, height) = (size(0)?, size(4)?);
|
|
1122
|
+
tao::window::Icon::from_rgba(bytes[8..].to_vec(), width, height).map_err(|e| log!("icon {}: {e}", path.display())).ok()
|
|
1123
|
+
}
|
|
1124
|
+
|
|
1125
|
+
struct WindowOptions {
|
|
1126
|
+
/// App path, e.g. "/settings?tab=2" (always on the app origin).
|
|
1127
|
+
path: String,
|
|
1128
|
+
title: Option<String>,
|
|
1129
|
+
size: Option<(f64, f64)>,
|
|
1130
|
+
position: Option<(f64, f64)>,
|
|
1131
|
+
maximized: bool,
|
|
1132
|
+
fullscreen: bool,
|
|
1133
|
+
/// macOS has no taskbar: its Dock shows apps, not windows.
|
|
1134
|
+
#[cfg_attr(target_os = "macos", allow(dead_code))]
|
|
1135
|
+
skip_taskbar: bool,
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1138
|
+
/// One window. The webview is declared first so that it is dropped before its window.
|
|
1139
|
+
struct Win {
|
|
1140
|
+
webview: WebView,
|
|
1141
|
+
window: tao::window::Window,
|
|
1142
|
+
/// When its page was last loaded again after its web content process ended: an end within a minute
|
|
1143
|
+
/// of that shows an error page (a page that crashes on load would loop), or with desktop.recovery
|
|
1144
|
+
/// "reload" waits longer before the next load (recovery_wait).
|
|
1145
|
+
reloaded_at: Option<std::time::Instant>,
|
|
1146
|
+
/// Ends in a row, each within a minute of the load before (desktop.recovery "reload").
|
|
1147
|
+
gone_streak: u32,
|
|
1148
|
+
/// A reload is waiting out recovery_wait: ends reported meanwhile (an unresponsive page repeats its report) are
|
|
1149
|
+
/// the same end, and must neither raise the streak nor start a second wait.
|
|
1150
|
+
reload_pending: bool,
|
|
1151
|
+
}
|
|
1152
|
+
|
|
1153
|
+
struct Windows {
|
|
1154
|
+
shell: Shell,
|
|
1155
|
+
/// Shared by all webviews: one data directory, and on Linux one registration of the app scheme.
|
|
1156
|
+
web_context: wry::WebContext,
|
|
1157
|
+
map: HashMap<u32, Win>,
|
|
1158
|
+
/// Destroyed, hidden, and unloading their page before they are dropped (Windows::destroy).
|
|
1159
|
+
closing: HashMap<u32, Win>,
|
|
1160
|
+
ids: HashMap<tao::window::WindowId, u32>,
|
|
1161
|
+
/// Ids by last focus, most recent last.
|
|
1162
|
+
focus: Vec<u32>,
|
|
1163
|
+
next: u32,
|
|
1164
|
+
}
|
|
1165
|
+
|
|
1166
|
+
fn is_dark() -> bool {
|
|
1167
|
+
#[cfg(target_os = "macos")]
|
|
1168
|
+
return macos::is_dark_mode();
|
|
1169
|
+
#[cfg(not(target_os = "macos"))]
|
|
1170
|
+
false
|
|
1171
|
+
}
|
|
1172
|
+
|
|
1173
|
+
fn monitors(target: &EventLoopWindowTarget<UserEvent>) -> Vec<placement::Rect> {
|
|
1174
|
+
target.available_monitors().map(|m| logical_rect(&m)).collect()
|
|
1175
|
+
}
|
|
1176
|
+
|
|
1177
|
+
fn logical_rect(m: &tao::monitor::MonitorHandle) -> placement::Rect {
|
|
1178
|
+
let scale = m.scale_factor();
|
|
1179
|
+
let (p, s) = (m.position().to_logical::<f64>(scale), m.size().to_logical::<f64>(scale));
|
|
1180
|
+
placement::Rect { x: p.x, y: p.y, width: s.width, height: s.height }
|
|
1181
|
+
}
|
|
1182
|
+
|
|
1183
|
+
/// The display holding a logical point.
|
|
1184
|
+
fn monitor_at(target: &EventLoopWindowTarget<UserEvent>, x: f64, y: f64) -> Option<tao::monitor::MonitorHandle> {
|
|
1185
|
+
target.available_monitors().find(|m| {
|
|
1186
|
+
let r = logical_rect(m);
|
|
1187
|
+
x >= r.x && x < r.x + r.width && y >= r.y && y < r.y + r.height
|
|
1188
|
+
})
|
|
1189
|
+
}
|
|
1190
|
+
|
|
1191
|
+
/// desktop.recovery "reload": how long to wait before loading a page again after `streak` ends in a
|
|
1192
|
+
/// row. The first end reloads at once; then 1 s, doubling to a minute.
|
|
1193
|
+
fn recovery_wait(streak: u32) -> Option<std::time::Duration> {
|
|
1194
|
+
(streak > 0).then(|| std::time::Duration::from_secs((1u64 << (streak - 1).min(6)).min(60)))
|
|
1195
|
+
}
|
|
1196
|
+
|
|
1197
|
+
/// Drops the webview's pending bridge calls (main thread): its document is gone.
|
|
1198
|
+
/// Each window's current top-level page (Linux: its permission requests do not say which frame asks).
|
|
1199
|
+
#[cfg(target_os = "linux")]
|
|
1200
|
+
static TOP_URLS: Mutex<Option<HashMap<u32, String>>> = Mutex::new(None);
|
|
1201
|
+
|
|
1202
|
+
/// The web content's permission requests (L0: the app origin's main frame only).
|
|
1203
|
+
fn permission_for(id: u32, kind: PermissionKind) -> PermissionResponse {
|
|
1204
|
+
let _ = id;
|
|
1205
|
+
match kind {
|
|
1206
|
+
// macOS already asked the user (TCC prompt, NSCameraUsageDescription) before this runs, and
|
|
1207
|
+
// only the app origin's main frame gets it (navigation.rs mac::media_trusted).
|
|
1208
|
+
#[cfg(target_os = "macos")]
|
|
1209
|
+
PermissionKind::Camera | PermissionKind::Microphone => {
|
|
1210
|
+
if navigation::mac::media_trusted() { PermissionResponse::Allow } else { PermissionResponse::Deny }
|
|
1211
|
+
}
|
|
1212
|
+
// WebKitGTK does not say which frame asks: allow only while the window's page is the app's
|
|
1213
|
+
// (navigation.rs keeps it there); WebKit's Permissions Policy keeps camera and microphone
|
|
1214
|
+
// from cross-origin frames unless the page grants them with allow=. Linux has no OS prompt.
|
|
1215
|
+
#[cfg(target_os = "linux")]
|
|
1216
|
+
PermissionKind::Camera | PermissionKind::Microphone => {
|
|
1217
|
+
let top = TOP_URLS.lock().unwrap_or_else(|e| e.into_inner()).as_ref().and_then(|m| m.get(&id).cloned()).unwrap_or_default();
|
|
1218
|
+
if on_origin(&top) { PermissionResponse::Allow } else { PermissionResponse::Deny }
|
|
1219
|
+
}
|
|
1220
|
+
// Screen sharing is never given on its own, nor anything this code does not know.
|
|
1221
|
+
#[cfg(target_os = "linux")]
|
|
1222
|
+
PermissionKind::DisplayCapture | PermissionKind::Other => PermissionResponse::Deny,
|
|
1223
|
+
// WebView2 asks the user itself, naming the origin, and remembers the answer (Default).
|
|
1224
|
+
_ => PermissionResponse::Default,
|
|
1225
|
+
}
|
|
1226
|
+
}
|
|
1227
|
+
|
|
1228
|
+
/// init.js's tail: the shell's origin and engine, one value every origin comparison uses
|
|
1229
|
+
/// (`__AKAN_NATIVE__.origin`), and what the page runs in.
|
|
1230
|
+
fn engine_info() -> &'static str {
|
|
1231
|
+
static INFO: std::sync::OnceLock<String> = std::sync::OnceLock::new();
|
|
1232
|
+
INFO.get_or_init(|| {
|
|
1233
|
+
let engine = if cfg!(target_os = "windows") { "webview2" } else if cfg!(target_os = "macos") { "wkwebview" } else { "webkitgtk" };
|
|
1234
|
+
let version = engine_version().unwrap_or_default();
|
|
1235
|
+
format!("window.__AKAN_NATIVE__.origin={};window.__AKAN_NATIVE__.engine=\"{engine}\";window.__AKAN_NATIVE__.engineVersion={};", json::quote(ORIGIN), json::quote(&version))
|
|
1236
|
+
})
|
|
1237
|
+
}
|
|
1238
|
+
|
|
1239
|
+
/// The engine's version: WebView2's runtime, WebKitGTK's, or on macOS the system WebKit's (which
|
|
1240
|
+
/// Safari updates bring: its bundle version names it, as the device plugin reports).
|
|
1241
|
+
fn engine_version() -> Option<String> {
|
|
1242
|
+
#[cfg(target_os = "windows")]
|
|
1243
|
+
return win::device::webview_version();
|
|
1244
|
+
#[cfg(target_os = "linux")]
|
|
1245
|
+
return wry::webview_version().ok();
|
|
1246
|
+
#[cfg(target_os = "macos")]
|
|
1247
|
+
{
|
|
1248
|
+
let plist = std::fs::read_to_string("/Applications/Safari.app/Contents/Info.plist").ok()?;
|
|
1249
|
+
let after = plist.split("<key>CFBundleShortVersionString</key>").nth(1)?;
|
|
1250
|
+
let value = after.split("<string>").nth(1)?.split("</string>").next()?;
|
|
1251
|
+
Some(value.trim().to_string())
|
|
1252
|
+
}
|
|
1253
|
+
}
|
|
1254
|
+
|
|
1255
|
+
/// What a window shows when its page's process ended twice within a minute (N2).
|
|
1256
|
+
fn gone_page() -> String {
|
|
1257
|
+
format!(
|
|
1258
|
+
r#"<!doctype html><meta charset="utf-8"><meta name="color-scheme" content="light dark"><title>This window stopped working</title>
|
|
1259
|
+
<body style="font:15px system-ui;display:grid;place-items:center;height:90vh;margin:0"><div style="text-align:center">
|
|
1260
|
+
<p>This window stopped working.</p><p><a href="{ORIGIN}/">Reload</a></p></div></body>"#
|
|
1261
|
+
)
|
|
1262
|
+
}
|
|
1263
|
+
|
|
1264
|
+
/// Tells when a window's web content process ends (Windows: ProcessFailed; Linux:
|
|
1265
|
+
/// web-process-terminated; macOS: the builder's handler).
|
|
1266
|
+
fn watch_web_process(webview: &WebView, id: u32) {
|
|
1267
|
+
#[cfg(target_os = "windows")]
|
|
1268
|
+
{
|
|
1269
|
+
use webview2_com::{Microsoft::Web::WebView2::Win32::*, ProcessFailedEventHandler};
|
|
1270
|
+
use wry::WebViewExtWindows;
|
|
1271
|
+
let handler = ProcessFailedEventHandler::create(Box::new(move |_, args| {
|
|
1272
|
+
let Some(args) = args else { return Ok(()) };
|
|
1273
|
+
let mut kind = COREWEBVIEW2_PROCESS_FAILED_KIND_RENDER_PROCESS_EXITED;
|
|
1274
|
+
unsafe { args.ProcessFailedKind(&mut kind)? };
|
|
1275
|
+
let reason = match kind {
|
|
1276
|
+
COREWEBVIEW2_PROCESS_FAILED_KIND_BROWSER_PROCESS_EXITED => "browserExited",
|
|
1277
|
+
COREWEBVIEW2_PROCESS_FAILED_KIND_RENDER_PROCESS_EXITED => "crashed",
|
|
1278
|
+
COREWEBVIEW2_PROCESS_FAILED_KIND_RENDER_PROCESS_UNRESPONSIVE => "unresponsive",
|
|
1279
|
+
_ => return Ok(()), // a frame's, the GPU's or a utility process: WebView2 recovers by itself
|
|
1280
|
+
};
|
|
1281
|
+
send(UserEvent::WebviewGone { window: id, reason });
|
|
1282
|
+
Ok(())
|
|
1283
|
+
}));
|
|
1284
|
+
let mut token = 0;
|
|
1285
|
+
if let Err(e) = unsafe { webview.webview().add_ProcessFailed(&handler, &mut token) } {
|
|
1286
|
+
log!("window {id}: web process failures are not watched: {e}");
|
|
1287
|
+
}
|
|
1288
|
+
}
|
|
1289
|
+
#[cfg(target_os = "linux")]
|
|
1290
|
+
{
|
|
1291
|
+
use webkit2gtk::{WebProcessTerminationReason, WebViewExt};
|
|
1292
|
+
use wry::WebViewExtUnix;
|
|
1293
|
+
webview.webview().connect_web_process_terminated(move |_, reason| {
|
|
1294
|
+
let reason = match reason {
|
|
1295
|
+
WebProcessTerminationReason::ExceededMemoryLimit => "oom",
|
|
1296
|
+
WebProcessTerminationReason::TerminatedByApi => "killed",
|
|
1297
|
+
_ => "crashed",
|
|
1298
|
+
};
|
|
1299
|
+
send(UserEvent::WebviewGone { window: id, reason });
|
|
1300
|
+
});
|
|
1301
|
+
}
|
|
1302
|
+
let _ = (webview, id);
|
|
1303
|
+
}
|
|
1304
|
+
|
|
1305
|
+
fn drop_pending(webview: u32) {
|
|
1306
|
+
PENDING.lock().unwrap().retain(|_, (w, _)| *w != webview);
|
|
1307
|
+
}
|
|
1308
|
+
|
|
1309
|
+
fn open_window(target: &EventLoopWindowTarget<UserEvent>, shell: &Shell, context: &mut wry::WebContext, id: u32, opts: WindowOptions) -> Result<Win, String> {
|
|
1310
|
+
// SH-3: paint the window and the webview before the first frame (no white flash).
|
|
1311
|
+
#[allow(unused_mut)]
|
|
1312
|
+
let mut background = if is_dark() { shell.colors.dark } else { shell.colors.light };
|
|
1313
|
+
let (width, height) = opts.size.unwrap_or(shell.size);
|
|
1314
|
+
let mut builder = WindowBuilder::new()
|
|
1315
|
+
.with_title(opts.title.as_deref().unwrap_or(&shell.title))
|
|
1316
|
+
.with_inner_size(LogicalSize::new(width, height))
|
|
1317
|
+
.with_min_inner_size(LogicalSize::new(MIN_INNER.0, MIN_INNER.1))
|
|
1318
|
+
.with_background_color(background)
|
|
1319
|
+
// D2: stay hidden until the first page load finished, so no blank frame is ever shown.
|
|
1320
|
+
.with_visible(false)
|
|
1321
|
+
.with_window_icon(shell.icon.clone());
|
|
1322
|
+
// Reopen where asked, unless that display is gone (placement.rs; window-state for window 1).
|
|
1323
|
+
// Not WindowBuilder::with_position: on macOS tao takes that as the content's top-left corner
|
|
1324
|
+
// (tao/src/platform_impl/macos/window.rs:202-208), so the title bar would end up above it;
|
|
1325
|
+
// window.getState reports the outer position, and set_outer_position takes one.
|
|
1326
|
+
let mut outer_position = None;
|
|
1327
|
+
let mut placed = None;
|
|
1328
|
+
if let Some((x, y)) = opts.position {
|
|
1329
|
+
let wanted = placement::Rect { x, y, width, height };
|
|
1330
|
+
match placement::place(wanted, &monitors(target), MIN_INNER) {
|
|
1331
|
+
Some(r) => {
|
|
1332
|
+
builder = builder.with_inner_size(LogicalSize::new(r.width, r.height));
|
|
1333
|
+
outer_position = Some(tao::dpi::LogicalPosition::new(r.x, r.y));
|
|
1334
|
+
placed = Some(r);
|
|
1335
|
+
}
|
|
1336
|
+
None => log!("window {id}: position ({x}, {y}) is on no display; using the default"),
|
|
1337
|
+
}
|
|
1338
|
+
}
|
|
1339
|
+
if opts.fullscreen {
|
|
1340
|
+
// Set before the first frame, on the display the window was placed on (else the primary one).
|
|
1341
|
+
let monitor = placed.and_then(|r| monitor_at(target, r.x + r.width / 2.0, r.y + r.height / 2.0));
|
|
1342
|
+
builder = builder.with_fullscreen(Some(tao::window::Fullscreen::Borderless(monitor)));
|
|
1343
|
+
}
|
|
1344
|
+
#[cfg(target_os = "windows")]
|
|
1345
|
+
if opts.skip_taskbar {
|
|
1346
|
+
use tao::platform::windows::WindowBuilderExtWindows;
|
|
1347
|
+
builder = builder.with_skip_taskbar(true);
|
|
1348
|
+
}
|
|
1349
|
+
#[cfg(target_os = "linux")]
|
|
1350
|
+
if opts.skip_taskbar {
|
|
1351
|
+
use tao::platform::unix::WindowBuilderExtUnix;
|
|
1352
|
+
builder = builder.with_skip_taskbar(true);
|
|
1353
|
+
}
|
|
1354
|
+
let window = builder.build(target).map_err(|e| format!("window: {e}"))?;
|
|
1355
|
+
// Windows and Linux: the system theme is known once a window exists (tao reads it then).
|
|
1356
|
+
#[cfg(not(target_os = "macos"))]
|
|
1357
|
+
if window_theme(&window) == tao::window::Theme::Dark && background != shell.colors.dark {
|
|
1358
|
+
background = shell.colors.dark;
|
|
1359
|
+
window.set_background_color(Some(background));
|
|
1360
|
+
}
|
|
1361
|
+
// Still hidden (D2), so nothing visibly moves. Both calls are queued on the main queue in
|
|
1362
|
+
// this order: the window zooms on the saved display, and un-zooming returns to these bounds.
|
|
1363
|
+
if let Some(position) = outer_position {
|
|
1364
|
+
window.set_outer_position(position);
|
|
1365
|
+
}
|
|
1366
|
+
if opts.maximized {
|
|
1367
|
+
window.set_maximized(true);
|
|
1368
|
+
}
|
|
1369
|
+
|
|
1370
|
+
let app_dir = shell.app_dir.clone();
|
|
1371
|
+
let init_js = shell.init_js.clone();
|
|
1372
|
+
let dev_server = shell.dev_server.clone();
|
|
1373
|
+
let webview_id = id.to_string();
|
|
1374
|
+
// Linux: the scheme belongs to the shared context, so the first window registers it for all;
|
|
1375
|
+
// the handler tells windows apart by the webview id it is given (Windows::web_context).
|
|
1376
|
+
let register_scheme = !context.is_custom_protocol_registered("app");
|
|
1377
|
+
let mut builder = WebViewBuilder::new_with_web_context(context);
|
|
1378
|
+
// `akan-native test` (dev builds only): WebKit suspends a page whose window is covered by other apps
|
|
1379
|
+
// (visibilityState "hidden"), which stalled the self-test at the first sheet whenever the test
|
|
1380
|
+
// window opened behind the user's work. WRY sets WKPreferences.inactiveSchedulingPolicy (macOS 14+).
|
|
1381
|
+
if shell.devtools && std::env::var_os("AKAN_NATIVE_TEST_NO_THROTTLING").is_some() {
|
|
1382
|
+
builder = builder.with_background_throttling(wry::BackgroundThrottlingPolicy::Disabled);
|
|
1383
|
+
}
|
|
1384
|
+
if register_scheme {
|
|
1385
|
+
builder = builder.with_asynchronous_custom_protocol("app".into(), move |webview, req, responder| {
|
|
1386
|
+
handle_request(&app_dir, &init_js, dev_server.as_deref(), webview.parse().unwrap_or(id), req, responder)
|
|
1387
|
+
});
|
|
1388
|
+
}
|
|
1389
|
+
#[cfg(target_os = "windows")]
|
|
1390
|
+
let builder = {
|
|
1391
|
+
use wry::WebViewBuilderExtWindows;
|
|
1392
|
+
// Ctrl+R/F5, Ctrl+P, Ctrl+F, zoom and F12 are the browser's, not the app's: off in every build
|
|
1393
|
+
// (user decision 2026-09-26; page_menu.rs). Editing keys stay.
|
|
1394
|
+
let builder = builder.with_https_scheme(true).with_browser_accelerator_keys(false);
|
|
1395
|
+
// Dev builds: AKAN_NATIVE_WEBVIEW2_DEBUG_PORT opens the Chrome DevTools Protocol on that port, for
|
|
1396
|
+
// test automation. WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS does not apply: wry passes arguments of
|
|
1397
|
+
// its own, repeated here because these replace them (wry webview2/mod.rs, with autoplay on).
|
|
1398
|
+
let port = std::env::var("AKAN_NATIVE_WEBVIEW2_DEBUG_PORT").ok().filter(|_| shell.devtools).and_then(|p| p.parse::<u16>().ok());
|
|
1399
|
+
// desktop.screenCapture "auto": getDisplayMedia answers with the first screen, no picker, no user gesture. Not
|
|
1400
|
+
// --auto-select-desktop-capture-source: it matches the picker's title, which follows the UI language (verified).
|
|
1401
|
+
let capture = shell.screen_capture_auto.then(|| "--use-fake-ui-for-media-stream".to_string());
|
|
1402
|
+
let extra: Vec<String> = port.map(|p| format!("--remote-debugging-port={p}")).into_iter().chain(capture).collect();
|
|
1403
|
+
if extra.is_empty() {
|
|
1404
|
+
builder
|
|
1405
|
+
} else {
|
|
1406
|
+
builder.with_additional_browser_args(format!(
|
|
1407
|
+
"--disable-features=msWebOOUI,msPdfOOUI,msSmartScreenProtection --autoplay-policy=no-user-gesture-required {}",
|
|
1408
|
+
extra.join(" ")
|
|
1409
|
+
))
|
|
1410
|
+
}
|
|
1411
|
+
};
|
|
1412
|
+
// SH-4: pages never leave the app origin (navigation.rs). Linux decides in its own signal handlers.
|
|
1413
|
+
#[cfg(not(target_os = "linux"))]
|
|
1414
|
+
let builder = builder.with_navigation_handler(|url| navigation::allow(&url));
|
|
1415
|
+
let builder = builder
|
|
1416
|
+
.with_id(&webview_id)
|
|
1417
|
+
.with_url(format!("{START_URL}{}", opts.path))
|
|
1418
|
+
.with_background_color(background)
|
|
1419
|
+
.with_devtools(shell.devtools)
|
|
1420
|
+
.with_new_window_req_handler(|url, _features| {
|
|
1421
|
+
// window.open and target=_blank: links go to the OS; the app's own pages open no second
|
|
1422
|
+
// window this way (the window plugin opens app windows).
|
|
1423
|
+
if in_app(&url) {
|
|
1424
|
+
log!("window.open({}) opens nothing: app windows come from the window plugin", navigation::shown(&url));
|
|
1425
|
+
} else {
|
|
1426
|
+
open_external(&url);
|
|
1427
|
+
}
|
|
1428
|
+
NewWindowResponse::Deny
|
|
1429
|
+
})
|
|
1430
|
+
.with_drag_drop_handler({
|
|
1431
|
+
let files = std::cell::Cell::new(false);
|
|
1432
|
+
#[cfg(target_os = "windows")]
|
|
1433
|
+
let hwnd = {
|
|
1434
|
+
use tao::platform::windows::WindowExtWindows;
|
|
1435
|
+
window.hwnd()
|
|
1436
|
+
};
|
|
1437
|
+
move |event| {
|
|
1438
|
+
// WebView2's positions are physical pixels: the window's DPI now (it can move between screens).
|
|
1439
|
+
#[cfg(target_os = "windows")]
|
|
1440
|
+
let scale = match unsafe { windows::Win32::UI::HiDpi::GetDpiForWindow(windows::Win32::Foundation::HWND(hwnd as *mut _)) } {
|
|
1441
|
+
0 => 1.0,
|
|
1442
|
+
dpi => dpi as f64 / 96.0,
|
|
1443
|
+
};
|
|
1444
|
+
#[cfg(not(target_os = "windows"))]
|
|
1445
|
+
let scale = 1.0;
|
|
1446
|
+
if let Some(json) = drag_drop_event(id, &files, event, scale) {
|
|
1447
|
+
push_event(&json);
|
|
1448
|
+
}
|
|
1449
|
+
false // keep WebKit's own handling: HTML5 drop events with dataTransfer.files still work
|
|
1450
|
+
}
|
|
1451
|
+
})
|
|
1452
|
+
.with_permission_handler(move |kind| permission_for(id, kind))
|
|
1453
|
+
.with_on_page_load_handler(move |ev, url| {
|
|
1454
|
+
if url == "about:blank" {
|
|
1455
|
+
// Only a destroyed window loads it (Windows::destroy); not an app page.
|
|
1456
|
+
if matches!(ev, PageLoadEvent::Finished) {
|
|
1457
|
+
send(UserEvent::Unloaded(id));
|
|
1458
|
+
}
|
|
1459
|
+
return;
|
|
1460
|
+
}
|
|
1461
|
+
#[cfg(target_os = "linux")]
|
|
1462
|
+
TOP_URLS.lock().unwrap_or_else(|e| e.into_inner()).get_or_insert_with(HashMap::new).insert(id, url.clone());
|
|
1463
|
+
let e = match ev {
|
|
1464
|
+
PageLoadEvent::Started => {
|
|
1465
|
+
// New document: pending bridge calls of the previous page can never be answered.
|
|
1466
|
+
drop_pending(id);
|
|
1467
|
+
"started"
|
|
1468
|
+
}
|
|
1469
|
+
PageLoadEvent::Finished => {
|
|
1470
|
+
send(UserEvent::Show(id));
|
|
1471
|
+
"finished"
|
|
1472
|
+
}
|
|
1473
|
+
};
|
|
1474
|
+
push_event(&format!(r#"{{"type":"pageLoad","event":"{e}","window":{id},"url":{}}}"#, json::quote(&url)));
|
|
1475
|
+
});
|
|
1476
|
+
// macOS: WKWebView tells when its web content process ended; the other engines through watch_web_process.
|
|
1477
|
+
#[cfg(target_os = "macos")]
|
|
1478
|
+
let builder = {
|
|
1479
|
+
use wry::WebViewBuilderExtDarwin;
|
|
1480
|
+
builder.with_on_web_content_process_terminate_handler(move || send(UserEvent::WebviewGone { window: id, reason: "terminated" }))
|
|
1481
|
+
};
|
|
1482
|
+
// Linux: inside tao's GTK box, which works on Wayland as well as X11 (wry's build() is X11 only).
|
|
1483
|
+
#[cfg(target_os = "linux")]
|
|
1484
|
+
let webview = {
|
|
1485
|
+
use tao::platform::unix::WindowExtUnix;
|
|
1486
|
+
use wry::WebViewBuilderExtUnix;
|
|
1487
|
+
builder.build_gtk(window.default_vbox().ok_or("webview: the window has no GTK box")?)
|
|
1488
|
+
};
|
|
1489
|
+
#[cfg(not(target_os = "linux"))]
|
|
1490
|
+
let webview = builder.build(&window);
|
|
1491
|
+
let webview = webview.map_err(|e| format!("webview: {e}"))?;
|
|
1492
|
+
navigation::install(&webview);
|
|
1493
|
+
watch_web_process(&webview, id);
|
|
1494
|
+
// Release builds: the page's right-click menu without the browser's items.
|
|
1495
|
+
page_menu::install(shell.devtools, &webview);
|
|
1496
|
+
#[cfg(target_os = "macos")]
|
|
1497
|
+
js_panels::install(shell.devtools, &webview); // D7, once WRY's delegate class exists
|
|
1498
|
+
// D7 on Windows and Linux: the webview's own dialogs, answered by a timer under AKAN_NATIVE_TEST_PANELS.
|
|
1499
|
+
#[cfg(target_os = "linux")]
|
|
1500
|
+
linux::dialogs::install_js_dialogs(shell.devtools, &webview);
|
|
1501
|
+
#[cfg(target_os = "windows")]
|
|
1502
|
+
win::dialogs::install_js_dialogs(shell.devtools, &webview);
|
|
1503
|
+
// The app menu bar, menu accelerators and taskbar state of the menu and dock plugins.
|
|
1504
|
+
#[cfg(target_os = "linux")]
|
|
1505
|
+
linux::window_opened(id, &window);
|
|
1506
|
+
#[cfg(target_os = "windows")]
|
|
1507
|
+
win::window_opened(id, &window, &webview);
|
|
1508
|
+
// Show the window even if the page never finishes loading.
|
|
1509
|
+
std::thread::spawn(move || {
|
|
1510
|
+
std::thread::sleep(Duration::from_millis(3000));
|
|
1511
|
+
send(UserEvent::Show(id));
|
|
1512
|
+
});
|
|
1513
|
+
Ok(Win { webview, window, reloaded_at: None, gone_streak: 0, reload_pending: false })
|
|
1514
|
+
}
|
|
1515
|
+
|
|
1516
|
+
/// A `window` argument: a positive whole number.
|
|
1517
|
+
fn window_arg(cmd: &json::V) -> Result<Option<u32>, String> {
|
|
1518
|
+
match cmd.get("window") {
|
|
1519
|
+
None => Ok(None),
|
|
1520
|
+
Some(v) => match v.as_f64() {
|
|
1521
|
+
Some(n) if n >= 1.0 && n.fract() == 0.0 && n <= u32::MAX as f64 => Ok(Some(n as u32)),
|
|
1522
|
+
_ => Err("window must be a window id".into()),
|
|
1523
|
+
},
|
|
1524
|
+
}
|
|
1525
|
+
}
|
|
1526
|
+
|
|
1527
|
+
/// window.create's `path`: an absolute path on the app origin.
|
|
1528
|
+
fn app_path(cmd: &json::V) -> Result<String, String> {
|
|
1529
|
+
let Some(v) = cmd.get("path") else { return Ok("/".into()) };
|
|
1530
|
+
let path = v.as_str().ok_or("path must be a string")?;
|
|
1531
|
+
if !is_app_path(path) {
|
|
1532
|
+
return Err(format!("path must be an app path like /settings, not {path:?}"));
|
|
1533
|
+
}
|
|
1534
|
+
Ok(path.to_string())
|
|
1535
|
+
}
|
|
1536
|
+
|
|
1537
|
+
fn is_app_path(path: &str) -> bool {
|
|
1538
|
+
path.starts_with('/') && !path.starts_with("//") && !path.contains('\\') && !path.chars().any(char::is_control)
|
|
1539
|
+
}
|
|
1540
|
+
|
|
1541
|
+
impl Windows {
|
|
1542
|
+
fn insert(&mut self, id: u32, win: Win) {
|
|
1543
|
+
self.ids.insert(win.window.id(), id);
|
|
1544
|
+
self.map.insert(id, win);
|
|
1545
|
+
}
|
|
1546
|
+
|
|
1547
|
+
/// Where ops without a `window` go (Dock reopen, single-instance, plugin setup): the most
|
|
1548
|
+
/// recently focused window, which is also the one macOS brings forward when the app is
|
|
1549
|
+
/// activated; before any focus change window 1, else the oldest.
|
|
1550
|
+
fn primary(&self) -> Option<u32> {
|
|
1551
|
+
self.focus.iter().rev().find(|id| self.map.contains_key(id)).copied().or_else(|| {
|
|
1552
|
+
if self.map.contains_key(&1) {
|
|
1553
|
+
Some(1)
|
|
1554
|
+
} else {
|
|
1555
|
+
self.map.keys().min().copied()
|
|
1556
|
+
}
|
|
1557
|
+
})
|
|
1558
|
+
}
|
|
1559
|
+
|
|
1560
|
+
fn focused(&mut self, id: u32) {
|
|
1561
|
+
self.focus.retain(|&f| f != id);
|
|
1562
|
+
self.focus.push(id);
|
|
1563
|
+
}
|
|
1564
|
+
|
|
1565
|
+
fn state(&self, id: u32, win: &Win) -> String {
|
|
1566
|
+
// {"id":N, ...state}
|
|
1567
|
+
format!(r#"{{"id":{id},{}"#, &window_state(&win.window, Some(&win.webview))[1..])
|
|
1568
|
+
}
|
|
1569
|
+
|
|
1570
|
+
fn create(&mut self, target: &EventLoopWindowTarget<UserEvent>, cmd: &json::V) -> Result<String, String> {
|
|
1571
|
+
let pair = |a: &str, b: &str| -> Result<Option<(f64, f64)>, String> {
|
|
1572
|
+
match (cmd.get(a), cmd.get(b)) {
|
|
1573
|
+
(None, None) => Ok(None),
|
|
1574
|
+
(Some(x), Some(y)) => match (x.as_f64(), y.as_f64()) {
|
|
1575
|
+
(Some(x), Some(y)) if x.is_finite() && y.is_finite() => Ok(Some((x, y))),
|
|
1576
|
+
_ => Err(format!("{a} and {b} must be numbers")),
|
|
1577
|
+
},
|
|
1578
|
+
_ => Err(format!("give both {a} and {b}")),
|
|
1579
|
+
}
|
|
1580
|
+
};
|
|
1581
|
+
let size = pair("width", "height")?;
|
|
1582
|
+
if size.is_some_and(|(w, h)| !(w >= 1.0 && h >= 1.0)) {
|
|
1583
|
+
return Err("width and height must be positive".into());
|
|
1584
|
+
}
|
|
1585
|
+
let title = match cmd.get("title") {
|
|
1586
|
+
None => None,
|
|
1587
|
+
Some(v) => Some(v.as_str().ok_or("title must be a string")?.to_string()),
|
|
1588
|
+
};
|
|
1589
|
+
// Without a position, cascade from the focused window like AppKit does for new documents.
|
|
1590
|
+
let position = match pair("x", "y")? {
|
|
1591
|
+
Some(p) => Some(p),
|
|
1592
|
+
None => self.focus.iter().rev().find_map(|id| self.map.get(id)).and_then(|w| {
|
|
1593
|
+
let scale = w.window.scale_factor();
|
|
1594
|
+
w.window.outer_position().ok().map(|p| {
|
|
1595
|
+
let l = p.to_logical::<f64>(scale);
|
|
1596
|
+
(l.x + 28.0, l.y + 28.0)
|
|
1597
|
+
})
|
|
1598
|
+
}),
|
|
1599
|
+
};
|
|
1600
|
+
let id = self.next;
|
|
1601
|
+
self.next += 1;
|
|
1602
|
+
let win = open_window(target, &self.shell, &mut self.web_context, id, WindowOptions { path: app_path(cmd)?, title, size, position, maximized: false, fullscreen: false, skip_taskbar: false })?;
|
|
1603
|
+
let state = self.state(id, &win);
|
|
1604
|
+
self.insert(id, win);
|
|
1605
|
+
push_event(&format!(r#"{{"type":"window","event":"created","window":{id}}}"#));
|
|
1606
|
+
Ok(state)
|
|
1607
|
+
}
|
|
1608
|
+
|
|
1609
|
+
fn destroy(&mut self, id: u32) -> Result<String, String> {
|
|
1610
|
+
if !self.map.contains_key(&id) {
|
|
1611
|
+
return Err(format!("no window {id}"));
|
|
1612
|
+
}
|
|
1613
|
+
if self.map.len() == 1 {
|
|
1614
|
+
return Err("the last window cannot be destroyed; hide it or quit".into());
|
|
1615
|
+
}
|
|
1616
|
+
let win = self.map.remove(&id).unwrap();
|
|
1617
|
+
self.ids.remove(&win.window.id());
|
|
1618
|
+
self.focus.retain(|&f| f != id);
|
|
1619
|
+
drop_pending(id);
|
|
1620
|
+
// wry keeps the WKWebView alive after its drop (it retains it and only removes it from the
|
|
1621
|
+
// window, wry/src/wkwebview/mod.rs:1433-1436), and a detached page keeps running (verified:
|
|
1622
|
+
// its timers went on). So hide the window now, let the page unload into about:blank, and drop
|
|
1623
|
+
// the window once that load finished (Unloaded).
|
|
1624
|
+
win.window.set_visible(false);
|
|
1625
|
+
let _ = win.webview.load_url("about:blank");
|
|
1626
|
+
self.closing.insert(id, win);
|
|
1627
|
+
std::thread::spawn(move || {
|
|
1628
|
+
std::thread::sleep(Duration::from_millis(1000));
|
|
1629
|
+
send(UserEvent::Unloaded(id));
|
|
1630
|
+
});
|
|
1631
|
+
push_event(&format!(r#"{{"type":"window","event":"destroyed","window":{id}}}"#));
|
|
1632
|
+
Ok(format!(r#"{{"id":{id}}}"#))
|
|
1633
|
+
}
|
|
1634
|
+
|
|
1635
|
+
fn shell_op(&mut self, target: &EventLoopWindowTarget<UserEvent>, json: &str) -> Result<String, String> {
|
|
1636
|
+
let cmd = json::parse(json)?;
|
|
1637
|
+
let op = cmd.get("op").and_then(|v| v.as_str()).ok_or("op is required")?;
|
|
1638
|
+
match op {
|
|
1639
|
+
"window.create" => return self.create(target, &cmd),
|
|
1640
|
+
"window.list" => {
|
|
1641
|
+
let mut ids: Vec<u32> = self.map.keys().copied().collect();
|
|
1642
|
+
ids.sort_unstable();
|
|
1643
|
+
let list: Vec<String> = ids.iter().map(|id| self.state(*id, &self.map[id])).collect();
|
|
1644
|
+
return Ok(format!("[{}]", list.join(",")));
|
|
1645
|
+
}
|
|
1646
|
+
"window.destroy" => return self.destroy(window_arg(&cmd)?.ok_or("window is required")?),
|
|
1647
|
+
// Dev builds: the idle wake budget counters (the self-test's K-idle check).
|
|
1648
|
+
"debug.stats" if self.shell.devtools => return Ok(stats_json()),
|
|
1649
|
+
_ => {}
|
|
1650
|
+
}
|
|
1651
|
+
// App-wide ops, not a window's: menu, tray, global shortcut, dock, screen and volume plugins
|
|
1652
|
+
// (menu.rs, tray.rs, hotkey.rs, dock.rs, screen.rs, volume.rs).
|
|
1653
|
+
#[cfg(target_os = "macos")]
|
|
1654
|
+
if let Some(result) = menu::shell_op(op, &cmd)
|
|
1655
|
+
.or_else(|| tray::shell_op(op, &cmd, &self.shell.app_dir))
|
|
1656
|
+
.or_else(|| hotkey::shell_op(op, &cmd))
|
|
1657
|
+
.or_else(|| dock::shell_op(op, &cmd, target))
|
|
1658
|
+
.or_else(|| screen::shell_op(op, target))
|
|
1659
|
+
.or_else(|| volume::shell_op(op, &cmd))
|
|
1660
|
+
{
|
|
1661
|
+
return result;
|
|
1662
|
+
}
|
|
1663
|
+
// The same plugins on Windows and Linux (win/, linux/).
|
|
1664
|
+
#[cfg(target_os = "windows")]
|
|
1665
|
+
if let Some(result) = win::shell_op(op, &cmd, target, &self.shell) {
|
|
1666
|
+
return result;
|
|
1667
|
+
}
|
|
1668
|
+
#[cfg(target_os = "linux")]
|
|
1669
|
+
if let Some(result) = linux::shell_op(op, &cmd, target, &self.shell) {
|
|
1670
|
+
return result;
|
|
1671
|
+
}
|
|
1672
|
+
let id = match window_arg(&cmd)? {
|
|
1673
|
+
Some(id) => id,
|
|
1674
|
+
None => self.primary().ok_or("there is no window")?,
|
|
1675
|
+
};
|
|
1676
|
+
let win = self.map.get(&id).ok_or_else(|| format!("no window {id}"))?;
|
|
1677
|
+
// Dev builds (the self-test): end the window's web content process, as a crash would (N2).
|
|
1678
|
+
if op == "webview.crashForTest" && self.shell.devtools {
|
|
1679
|
+
#[cfg(target_os = "macos")]
|
|
1680
|
+
unsafe {
|
|
1681
|
+
use objc2::{msg_send, runtime::AnyObject, sel};
|
|
1682
|
+
use wry::WebViewExtMacOS;
|
|
1683
|
+
let wk = win.webview.webview();
|
|
1684
|
+
let wk: &AnyObject = &wk;
|
|
1685
|
+
let can: bool = msg_send![wk, respondsToSelector: sel!(_killWebContentProcess)];
|
|
1686
|
+
if !can {
|
|
1687
|
+
return Err("UNSUPPORTED: this WebKit cannot end its web content process".into());
|
|
1688
|
+
}
|
|
1689
|
+
let _: () = msg_send![wk, _killWebContentProcess];
|
|
1690
|
+
return Ok("null".into());
|
|
1691
|
+
}
|
|
1692
|
+
#[cfg(target_os = "linux")]
|
|
1693
|
+
{
|
|
1694
|
+
use webkit2gtk::WebViewExt;
|
|
1695
|
+
use wry::WebViewExtUnix;
|
|
1696
|
+
win.webview.webview().terminate_web_process();
|
|
1697
|
+
return Ok("null".into());
|
|
1698
|
+
}
|
|
1699
|
+
#[cfg(target_os = "windows")]
|
|
1700
|
+
return Err("UNSUPPORTED: not on Windows".into());
|
|
1701
|
+
}
|
|
1702
|
+
#[cfg(target_os = "windows")]
|
|
1703
|
+
if let Some(result) = win::window_op(op, &cmd, id, win) {
|
|
1704
|
+
return result;
|
|
1705
|
+
}
|
|
1706
|
+
#[cfg(target_os = "linux")]
|
|
1707
|
+
if let Some(result) = linux::window_op(op, &cmd, id, win) {
|
|
1708
|
+
return result;
|
|
1709
|
+
}
|
|
1710
|
+
// What the macOS shell has and this OS does not (yet): the plugin reports UNSUPPORTED. After
|
|
1711
|
+
// window_op, which takes the families' window ops (menu.popup).
|
|
1712
|
+
#[cfg(not(target_os = "macos"))]
|
|
1713
|
+
if PLATFORM_OPS.iter().any(|family| op.starts_with(family)) {
|
|
1714
|
+
return Err(format!("UNSUPPORTED: {op} is not available on {OS_NAME} yet"));
|
|
1715
|
+
}
|
|
1716
|
+
#[cfg(target_os = "macos")]
|
|
1717
|
+
if op == "menu.popup" {
|
|
1718
|
+
return menu::popup_op(&cmd, id, &win.webview);
|
|
1719
|
+
}
|
|
1720
|
+
if op == "window.setTheme" {
|
|
1721
|
+
// appearance plugin: null = follow the system. The appearance is app-wide (NSApp), and tao
|
|
1722
|
+
// sends no ThemeChanged for a theme the app sets itself, so repaint every window here.
|
|
1723
|
+
let theme = match cmd.get("theme").and_then(|v| v.as_str()) {
|
|
1724
|
+
Some("dark") => Some(tao::window::Theme::Dark),
|
|
1725
|
+
Some("light") => Some(tao::window::Theme::Light),
|
|
1726
|
+
None => None,
|
|
1727
|
+
Some(other) => return Err(format!("unknown theme {other}")),
|
|
1728
|
+
};
|
|
1729
|
+
// Windows: TAO's app-wide theme (new windows too) and WebView2's color scheme, which
|
|
1730
|
+
// prefers-color-scheme follows (win/appearance.rs). Linux: GTK's settings, as TAO's would
|
|
1731
|
+
// switch a dark desktop to light for null (linux/appearance.rs).
|
|
1732
|
+
#[cfg(target_os = "macos")]
|
|
1733
|
+
win.window.set_theme(theme);
|
|
1734
|
+
#[cfg(target_os = "windows")]
|
|
1735
|
+
win::appearance::set_theme(target, theme, self.map.values().map(|w| &w.webview));
|
|
1736
|
+
#[cfg(target_os = "linux")]
|
|
1737
|
+
linux::appearance::set_theme(theme);
|
|
1738
|
+
let dark = theme.map_or_else(|| window_theme(&win.window) == tao::window::Theme::Dark, |t| t == tao::window::Theme::Dark);
|
|
1739
|
+
for w in self.map.values() {
|
|
1740
|
+
paint(&w.window, Some(&w.webview), &self.shell.colors, dark);
|
|
1741
|
+
}
|
|
1742
|
+
return Ok(window_state(&win.window, Some(&win.webview)));
|
|
1743
|
+
}
|
|
1744
|
+
if op == "webview.print" {
|
|
1745
|
+
// D8: WKWebView ignores window.print(); the page runtime calls this instead (Tauri does the
|
|
1746
|
+
// same, tauri/crates/tauri/src/webview/plugin.rs:198). A sheet on the window, not modal.
|
|
1747
|
+
win.webview.print().map_err(|e| e.to_string())?;
|
|
1748
|
+
return Ok("null".into());
|
|
1749
|
+
}
|
|
1750
|
+
window_op(&win.window, Some(&win.webview), &cmd, op)
|
|
1751
|
+
}
|
|
1752
|
+
}
|
|
1753
|
+
|
|
1754
|
+
/// D9: a file drag over a window, as a `dragDrop` native event. Only drags that carry files are
|
|
1755
|
+
/// reported: WRY sends Over/Drop/Leave for any drag, and only Enter says what is dragged.
|
|
1756
|
+
/// `scale`: physical pixels per CSS pixel of the positions (WebView2 gives physical pixels after
|
|
1757
|
+
/// ScreenToClient; WKWebView and WebKitGTK already give CSS pixels, so 1 there; N6).
|
|
1758
|
+
fn drag_drop_event(window: u32, files: &std::cell::Cell<bool>, event: DragDropEvent, scale: f64) -> Option<String> {
|
|
1759
|
+
let css = |v: i32| (v as f64 / scale * 100.0).round() / 100.0;
|
|
1760
|
+
let paths = |paths: &[PathBuf]| {
|
|
1761
|
+
let list: Vec<String> = paths.iter().map(|p| json::quote(&p.to_string_lossy())).collect();
|
|
1762
|
+
format!("[{}]", list.join(","))
|
|
1763
|
+
};
|
|
1764
|
+
let (name, detail) = match event {
|
|
1765
|
+
DragDropEvent::Enter { paths: p, position: (x, y) } => {
|
|
1766
|
+
files.set(!p.is_empty());
|
|
1767
|
+
("enter", format!(r#","paths":{},"x":{},"y":{}"#, paths(&p), css(x), css(y)))
|
|
1768
|
+
}
|
|
1769
|
+
DragDropEvent::Over { position: (x, y) } => ("over", format!(r#","x":{},"y":{}"#, css(x), css(y))),
|
|
1770
|
+
DragDropEvent::Drop { paths: p, position: (x, y) } => ("drop", format!(r#","paths":{},"x":{},"y":{}"#, paths(&p), css(x), css(y))),
|
|
1771
|
+
DragDropEvent::Leave => ("leave", String::new()),
|
|
1772
|
+
_ => return None,
|
|
1773
|
+
};
|
|
1774
|
+
if !files.get() {
|
|
1775
|
+
return None;
|
|
1776
|
+
}
|
|
1777
|
+
if name == "drop" || name == "leave" {
|
|
1778
|
+
files.set(false);
|
|
1779
|
+
}
|
|
1780
|
+
Some(format!(r#"{{"type":"dragDrop","window":{window},"event":"{name}"{detail}}}"#))
|
|
1781
|
+
}
|
|
1782
|
+
|
|
1783
|
+
// ───────────────────────── akan_native_run ─────────────────────────
|
|
1784
|
+
|
|
1785
|
+
#[no_mangle]
|
|
1786
|
+
pub unsafe extern "C" fn akan_native_run(config_json: *const c_char) -> i32 {
|
|
1787
|
+
#[cfg(target_os = "macos")]
|
|
1788
|
+
if !macos::is_main_thread() {
|
|
1789
|
+
log!("akan_native_run must be called on the process main thread");
|
|
1790
|
+
return -1;
|
|
1791
|
+
}
|
|
1792
|
+
if config_json.is_null() {
|
|
1793
|
+
return -2;
|
|
1794
|
+
}
|
|
1795
|
+
let cfg = match parse_config(&CStr::from_ptr(config_json).to_string_lossy()) {
|
|
1796
|
+
Ok(c) => c,
|
|
1797
|
+
Err(e) => {
|
|
1798
|
+
log!("bad config: {e}");
|
|
1799
|
+
set_last_error(&format!("bad config: {e}"));
|
|
1800
|
+
return -2;
|
|
1801
|
+
}
|
|
1802
|
+
};
|
|
1803
|
+
|
|
1804
|
+
if let Some(base) = &cfg.dev_server {
|
|
1805
|
+
log!("pages from {base} (akan-native dev --hmr)");
|
|
1806
|
+
}
|
|
1807
|
+
navigation::set_extra_schemes(cfg.external_schemes.clone());
|
|
1808
|
+
#[cfg(not(target_os = "windows"))]
|
|
1809
|
+
#[cfg_attr(not(target_os = "macos"), allow(unused_mut))]
|
|
1810
|
+
let mut event_loop = EventLoopBuilder::<UserEvent>::with_user_event().build();
|
|
1811
|
+
// Windows: every Win32 message passes win::msg_hook before tao dispatches it (hotkeys, tray icons).
|
|
1812
|
+
#[cfg(target_os = "windows")]
|
|
1813
|
+
let event_loop = {
|
|
1814
|
+
use tao::platform::windows::EventLoopBuilderExtWindows;
|
|
1815
|
+
EventLoopBuilder::<UserEvent>::with_user_event().with_msg_hook(win::msg_hook).build()
|
|
1816
|
+
};
|
|
1817
|
+
#[cfg(target_os = "macos")]
|
|
1818
|
+
if cfg.activation == "prohibited" {
|
|
1819
|
+
use tao::platform::macos::{ActivationPolicy, EventLoopExtMacOS};
|
|
1820
|
+
event_loop.set_activation_policy(ActivationPolicy::Prohibited);
|
|
1821
|
+
event_loop.set_activate_ignoring_other_apps(false);
|
|
1822
|
+
}
|
|
1823
|
+
let _ = PROXY.set(Mutex::new(event_loop.create_proxy()));
|
|
1824
|
+
#[cfg(target_os = "macos")]
|
|
1825
|
+
macos::install_terminate_handler();
|
|
1826
|
+
#[cfg(target_os = "macos")]
|
|
1827
|
+
notify::install_if_declared();
|
|
1828
|
+
#[cfg(unix)]
|
|
1829
|
+
sigterm::install();
|
|
1830
|
+
#[cfg(target_os = "windows")]
|
|
1831
|
+
stdin_quit::install();
|
|
1832
|
+
// The helper window receives sign-out and shutdown (WM_QUERYENDSESSION), so it exists from the start.
|
|
1833
|
+
#[cfg(target_os = "windows")]
|
|
1834
|
+
if let Err(e) = win::msgwin::hwnd() {
|
|
1835
|
+
log!("sign-out and shutdown are not watched: {e}");
|
|
1836
|
+
}
|
|
1837
|
+
#[cfg(target_os = "windows")]
|
|
1838
|
+
if !cfg.app_id.is_empty() {
|
|
1839
|
+
win::notify::claim_app_id(&cfg.app_id);
|
|
1840
|
+
}
|
|
1841
|
+
|
|
1842
|
+
let mut windows = Windows {
|
|
1843
|
+
shell: Shell {
|
|
1844
|
+
app_dir: cfg.app_dir.clone(),
|
|
1845
|
+
init_js: Arc::from(cfg.init_js.as_str()),
|
|
1846
|
+
dev_server: cfg.dev_server.as_deref().map(Arc::from),
|
|
1847
|
+
devtools: cfg.devtools,
|
|
1848
|
+
colors: Colors { light: cfg.background_light, dark: cfg.background_dark },
|
|
1849
|
+
title: cfg.title.clone(),
|
|
1850
|
+
size: (cfg.width, cfg.height),
|
|
1851
|
+
activate: cfg.activation != "prohibited",
|
|
1852
|
+
icon: cfg.icon.as_deref().and_then(read_icon),
|
|
1853
|
+
app_id: cfg.app_id.clone(),
|
|
1854
|
+
recovery_reload: cfg.recovery_reload,
|
|
1855
|
+
screen_capture_auto: cfg.screen_capture_auto,
|
|
1856
|
+
},
|
|
1857
|
+
web_context: wry::WebContext::new(cfg.data_dir.clone()),
|
|
1858
|
+
map: HashMap::new(),
|
|
1859
|
+
closing: HashMap::new(),
|
|
1860
|
+
ids: HashMap::new(),
|
|
1861
|
+
focus: Vec::new(),
|
|
1862
|
+
next: 2,
|
|
1863
|
+
};
|
|
1864
|
+
let main = WindowOptions {
|
|
1865
|
+
path: cfg.start_path.clone(),
|
|
1866
|
+
title: None,
|
|
1867
|
+
size: None,
|
|
1868
|
+
position: cfg.position,
|
|
1869
|
+
maximized: cfg.maximized,
|
|
1870
|
+
fullscreen: cfg.fullscreen,
|
|
1871
|
+
skip_taskbar: cfg.skip_taskbar,
|
|
1872
|
+
};
|
|
1873
|
+
match open_window(&event_loop, &windows.shell, &mut windows.web_context, 1, main) {
|
|
1874
|
+
Ok(win) => windows.insert(1, win),
|
|
1875
|
+
Err(e) => {
|
|
1876
|
+
log!("{e}");
|
|
1877
|
+
set_last_error(&e);
|
|
1878
|
+
// -5: the system has no webview engine (Windows without the WebView2 Runtime).
|
|
1879
|
+
#[cfg(target_os = "windows")]
|
|
1880
|
+
if e.starts_with("webview") && webview2_com::Microsoft::Web::WebView2::Win32::GetAvailableCoreWebView2BrowserVersionString(windows::core::PCWSTR::null(), &mut windows::core::PWSTR::null()).is_err() {
|
|
1881
|
+
set_last_error("the Microsoft Edge WebView2 Runtime is not installed (https://go.microsoft.com/fwlink/p/?LinkId=2124703)");
|
|
1882
|
+
return -5;
|
|
1883
|
+
}
|
|
1884
|
+
return if e.starts_with("window") { -3 } else { -4 };
|
|
1885
|
+
}
|
|
1886
|
+
}
|
|
1887
|
+
let menu = cfg.menu;
|
|
1888
|
+
let app_name = cfg.title.clone();
|
|
1889
|
+
|
|
1890
|
+
event_loop.run(move |event, target, control_flow| {
|
|
1891
|
+
*control_flow = ControlFlow::Wait;
|
|
1892
|
+
match event {
|
|
1893
|
+
Event::NewEvents(StartCause::Init) => {
|
|
1894
|
+
#[cfg(target_os = "macos")]
|
|
1895
|
+
if menu {
|
|
1896
|
+
// Without an app menu, Cmd+C/V/A/Z/Q do nothing in WKWebView.
|
|
1897
|
+
menu::install_default(&app_name);
|
|
1898
|
+
}
|
|
1899
|
+
let _ = (menu, &app_name);
|
|
1900
|
+
push_event(r#"{"type":"init"}"#);
|
|
1901
|
+
}
|
|
1902
|
+
Event::WindowEvent { window_id, event, .. } => {
|
|
1903
|
+
let Some(&id) = windows.ids.get(&window_id) else { return }; // destroyed meanwhile
|
|
1904
|
+
let win = &windows.map[&id];
|
|
1905
|
+
match event {
|
|
1906
|
+
WindowEvent::CloseRequested => {
|
|
1907
|
+
if WAKE.load(Ordering::Acquire) == 0 {
|
|
1908
|
+
*control_flow = ControlFlow::ExitWithCode(0);
|
|
1909
|
+
return;
|
|
1910
|
+
}
|
|
1911
|
+
// The host decides: ask that window's page, then destroy it, or quit or hide it when
|
|
1912
|
+
// it is the last one (desktop.quitOnLastWindowClosed).
|
|
1913
|
+
if !QUITTING.load(Ordering::Acquire) {
|
|
1914
|
+
push_watched(&format!(r#"{{"type":"window","event":"closeRequested","window":{id}}}"#), Some(id));
|
|
1915
|
+
}
|
|
1916
|
+
}
|
|
1917
|
+
WindowEvent::Focused(focused) => {
|
|
1918
|
+
push_event(&format!(r#"{{"type":"window","event":"focused","window":{id},"value":{focused}}}"#));
|
|
1919
|
+
if focused {
|
|
1920
|
+
windows.focused(id);
|
|
1921
|
+
}
|
|
1922
|
+
}
|
|
1923
|
+
WindowEvent::Resized(_) => {
|
|
1924
|
+
let logical = inner_size(&win.window, Some(&win.webview)); // not the event's size (see inner_size)
|
|
1925
|
+
push_event(&format!(r#"{{"type":"window","event":"resized","window":{id},"width":{},"height":{}}}"#, logical.width, logical.height));
|
|
1926
|
+
}
|
|
1927
|
+
WindowEvent::Moved(position) => {
|
|
1928
|
+
let logical = position.to_logical::<f64>(win.window.scale_factor());
|
|
1929
|
+
push_event(&format!(r#"{{"type":"window","event":"moved","window":{id},"x":{},"y":{}}}"#, logical.x, logical.y));
|
|
1930
|
+
}
|
|
1931
|
+
WindowEvent::ThemeChanged(theme) => {
|
|
1932
|
+
paint(&win.window, Some(&win.webview), &windows.shell.colors, theme == tao::window::Theme::Dark);
|
|
1933
|
+
push_event(&format!(r#"{{"type":"window","event":"themeChanged","window":{id},"theme":"{}"}}"#, theme_name(theme)));
|
|
1934
|
+
}
|
|
1935
|
+
_ => {}
|
|
1936
|
+
}
|
|
1937
|
+
}
|
|
1938
|
+
// Deep links and "open with" (plugins.md D6). The plugin host buffers them until the page listens (C2).
|
|
1939
|
+
Event::Opened { urls } => {
|
|
1940
|
+
let list: Vec<String> = urls.iter().map(|u| json::quote(u.as_str())).collect();
|
|
1941
|
+
push_event(&format!(r#"{{"type":"opened","urls":[{}]}}"#, list.join(",")));
|
|
1942
|
+
}
|
|
1943
|
+
// Dock icon clicked (D5): bring the primary window back.
|
|
1944
|
+
Event::Reopen { .. } => {
|
|
1945
|
+
if let Some(win) = windows.primary().and_then(|id| windows.map.get(&id)) {
|
|
1946
|
+
win.window.set_visible(true);
|
|
1947
|
+
win.window.set_minimized(false);
|
|
1948
|
+
win.window.set_focus();
|
|
1949
|
+
}
|
|
1950
|
+
}
|
|
1951
|
+
Event::UserEvent(UserEvent::Shell { id, json }) => {
|
|
1952
|
+
// notify.*, camera.*, panel.*, alert.* and autostart.* answer later, from completion
|
|
1953
|
+
// handlers or a thread (notify.rs, camera.rs, panels.rs, autostart.rs).
|
|
1954
|
+
#[cfg(target_os = "macos")]
|
|
1955
|
+
if notify::shell_op(id, &json) || camera::shell_op(id, &json) || panels::shell_op(id, &json, &windows) || autostart::shell_op(id, &json) || keychain::shell_op(id, &json) {
|
|
1956
|
+
return;
|
|
1957
|
+
}
|
|
1958
|
+
#[cfg(target_os = "windows")]
|
|
1959
|
+
if win::async_op(id, &json, &windows) {
|
|
1960
|
+
return;
|
|
1961
|
+
}
|
|
1962
|
+
#[cfg(target_os = "linux")]
|
|
1963
|
+
if linux::async_op(id, &json, &windows) {
|
|
1964
|
+
return;
|
|
1965
|
+
}
|
|
1966
|
+
reply(id, windows.shell_op(target, &json))
|
|
1967
|
+
}
|
|
1968
|
+
Event::UserEvent(UserEvent::Respond(r, resp)) => r.respond(resp),
|
|
1969
|
+
Event::UserEvent(UserEvent::WebviewGone { window, reason }) => {
|
|
1970
|
+
// The page and every call it had made are gone: the host ends its document (dispatcher.reset).
|
|
1971
|
+
drop_pending(window);
|
|
1972
|
+
push_event(&format!(r#"{{"type":"webview","event":"processTerminated","window":{window},"reason":"{reason}"}}"#));
|
|
1973
|
+
if reason == "browserExited" && windows.shell.recovery_reload {
|
|
1974
|
+
// The host relaunches the app on the event above (host.ts); should it not, this quits.
|
|
1975
|
+
log!("the webview's browser process ended; the app relaunches");
|
|
1976
|
+
std::thread::spawn(|| {
|
|
1977
|
+
std::thread::sleep(std::time::Duration::from_secs(10));
|
|
1978
|
+
send(UserEvent::Quit(1));
|
|
1979
|
+
});
|
|
1980
|
+
} else if reason == "browserExited" {
|
|
1981
|
+
log!("the webview's browser process ended; quitting");
|
|
1982
|
+
send(UserEvent::Quit(1));
|
|
1983
|
+
} else if let Some(win) = windows.map.get_mut(&window) {
|
|
1984
|
+
if win.reload_pending {
|
|
1985
|
+
log!("window {window}: the page stopped ({reason}) while its reload waits");
|
|
1986
|
+
return;
|
|
1987
|
+
}
|
|
1988
|
+
let now = std::time::Instant::now();
|
|
1989
|
+
let again = win.reloaded_at.is_some_and(|t| now.duration_since(t) < std::time::Duration::from_secs(60));
|
|
1990
|
+
win.gone_streak = if again { win.gone_streak + 1 } else { 0 };
|
|
1991
|
+
let wait = recovery_wait(win.gone_streak).filter(|_| windows.shell.recovery_reload);
|
|
1992
|
+
if again && !windows.shell.recovery_reload {
|
|
1993
|
+
log!("window {window}: the page stopped again ({reason}) within a minute; showing an error page");
|
|
1994
|
+
let _ = win.webview.load_html(&gone_page());
|
|
1995
|
+
} else if let Some(wait) = wait {
|
|
1996
|
+
log!("window {window}: the page stopped again ({reason}); loading it again in {} s", wait.as_secs());
|
|
1997
|
+
win.reload_pending = true;
|
|
1998
|
+
std::thread::spawn(move || {
|
|
1999
|
+
std::thread::sleep(wait);
|
|
2000
|
+
send(UserEvent::ReloadGone(window));
|
|
2001
|
+
});
|
|
2002
|
+
} else {
|
|
2003
|
+
log!("window {window}: the page stopped ({reason}); loading it again");
|
|
2004
|
+
win.reloaded_at = Some(now);
|
|
2005
|
+
let _ = win.webview.reload();
|
|
2006
|
+
}
|
|
2007
|
+
}
|
|
2008
|
+
}
|
|
2009
|
+
Event::UserEvent(UserEvent::ReloadGone(window)) => {
|
|
2010
|
+
if let Some(win) = windows.map.get_mut(&window) {
|
|
2011
|
+
win.reload_pending = false;
|
|
2012
|
+
win.reloaded_at = Some(std::time::Instant::now());
|
|
2013
|
+
let _ = win.webview.reload();
|
|
2014
|
+
}
|
|
2015
|
+
}
|
|
2016
|
+
Event::UserEvent(UserEvent::Emit { webview_id, js }) => {
|
|
2017
|
+
if let Some(win) = windows.map.get(&webview_id) {
|
|
2018
|
+
let _ = win.webview.evaluate_script(&js);
|
|
2019
|
+
}
|
|
2020
|
+
}
|
|
2021
|
+
Event::UserEvent(UserEvent::Show(id)) => {
|
|
2022
|
+
if let Some(win) = windows.map.get(&id) {
|
|
2023
|
+
if !win.window.is_visible() {
|
|
2024
|
+
win.window.set_visible(true);
|
|
2025
|
+
if windows.shell.activate {
|
|
2026
|
+
win.window.set_focus();
|
|
2027
|
+
}
|
|
2028
|
+
}
|
|
2029
|
+
}
|
|
2030
|
+
}
|
|
2031
|
+
Event::UserEvent(UserEvent::Quit(code)) => {
|
|
2032
|
+
// Drop pending responders on the main thread before the webviews go away.
|
|
2033
|
+
PENDING.lock().unwrap().clear();
|
|
2034
|
+
#[cfg(target_os = "macos")]
|
|
2035
|
+
if TERMINATE_LATER.swap(false, Ordering::AcqRel) {
|
|
2036
|
+
// AppKit's pending terminate: finishes (applicationWillTerminate, exit) and the logout goes on.
|
|
2037
|
+
macos::reply_to_terminate(true);
|
|
2038
|
+
return;
|
|
2039
|
+
}
|
|
2040
|
+
*control_flow = ControlFlow::ExitWithCode(code);
|
|
2041
|
+
}
|
|
2042
|
+
Event::UserEvent(UserEvent::Unloaded(id)) => drop(windows.closing.remove(&id)), // webview first, then the window
|
|
2043
|
+
Event::UserEvent(UserEvent::CloseUntaken { watch, window }) => {
|
|
2044
|
+
if WATCH_TAKEN.load(Ordering::Acquire) >= watch || QUITTING.load(Ordering::Acquire) || !windows.map.contains_key(&window) {
|
|
2045
|
+
return; // taken meanwhile, or gone
|
|
2046
|
+
}
|
|
2047
|
+
if windows.map.len() > 1 {
|
|
2048
|
+
log!("the plugin host did not take the close request of window {window} within {WATCH_TIMEOUT:?}; closing it");
|
|
2049
|
+
let _ = windows.destroy(window);
|
|
2050
|
+
} else {
|
|
2051
|
+
log!("the plugin host did not take the close request of the last window within {WATCH_TIMEOUT:?}; quitting");
|
|
2052
|
+
akan_native_quit(0);
|
|
2053
|
+
}
|
|
2054
|
+
}
|
|
2055
|
+
Event::UserEvent(UserEvent::ThemeChanged) => {
|
|
2056
|
+
for (id, win) in &windows.map {
|
|
2057
|
+
let theme = window_theme(&win.window);
|
|
2058
|
+
paint(&win.window, Some(&win.webview), &windows.shell.colors, theme == tao::window::Theme::Dark);
|
|
2059
|
+
push_event(&format!(r#"{{"type":"window","event":"themeChanged","window":{id},"theme":"{}"}}"#, theme_name(theme)));
|
|
2060
|
+
}
|
|
2061
|
+
}
|
|
2062
|
+
Event::UserEvent(UserEvent::CancelTerminate) =>
|
|
2063
|
+
{
|
|
2064
|
+
#[cfg(target_os = "macos")]
|
|
2065
|
+
if TERMINATE_LATER.swap(false, Ordering::AcqRel) {
|
|
2066
|
+
macos::reply_to_terminate(false);
|
|
2067
|
+
}
|
|
2068
|
+
}
|
|
2069
|
+
_ => {}
|
|
2070
|
+
}
|
|
2071
|
+
});
|
|
2072
|
+
}
|
|
2073
|
+
|
|
2074
|
+
// ───────────────────────── macOS ─────────────────────────
|
|
2075
|
+
|
|
2076
|
+
#[cfg(target_os = "macos")]
|
|
2077
|
+
mod macos {
|
|
2078
|
+
use objc2::{
|
|
2079
|
+
msg_send,
|
|
2080
|
+
rc::Retained,
|
|
2081
|
+
runtime::{AnyClass, AnyObject, Imp, Sel},
|
|
2082
|
+
sel, MainThreadMarker,
|
|
2083
|
+
};
|
|
2084
|
+
use objc2_app_kit::{NSApplication, NSApplicationTerminateReply, NSWorkspace};
|
|
2085
|
+
use objc2_foundation::{NSAppleEventDescriptor, NSAppleEventManager, NSString, NSURL};
|
|
2086
|
+
|
|
2087
|
+
pub enum TerminateReply {
|
|
2088
|
+
Now,
|
|
2089
|
+
Cancel,
|
|
2090
|
+
Later,
|
|
2091
|
+
}
|
|
2092
|
+
|
|
2093
|
+
/// keyAEQuitReason ('why?') of the quit Apple event, and the values loginwindow sends for a
|
|
2094
|
+
/// logout, restart or shutdown (AERegistry.h). Cmd+Q comes from the menu (no Apple event); Dock
|
|
2095
|
+
/// Quit and AppleScript `quit` send a quit event without a reason.
|
|
2096
|
+
const QUIT_REASON: u32 = u32::from_be_bytes(*b"why?");
|
|
2097
|
+
const SESSION_END: [&[u8; 4]; 6] = [b"logo", b"rlgo", b"rrst", b"rsdn", b"rest", b"shut"];
|
|
2098
|
+
|
|
2099
|
+
pub fn is_session_end(reason: u32) -> bool {
|
|
2100
|
+
SESSION_END.iter().any(|code| u32::from_be_bytes(**code) == reason)
|
|
2101
|
+
}
|
|
2102
|
+
|
|
2103
|
+
fn quit_reason() -> Option<u32> {
|
|
2104
|
+
let event = NSAppleEventManager::sharedAppleEventManager().currentAppleEvent()?;
|
|
2105
|
+
// AppleEvents.h calls it a parameter; AppKit code in the wild reads it as an attribute. Try both.
|
|
2106
|
+
// msg_send: objc2-foundation gates these two behind objc2-core-services, a crate not in our tree.
|
|
2107
|
+
let attribute: Option<Retained<NSAppleEventDescriptor>> = unsafe { msg_send![&*event, attributeDescriptorForKeyword: QUIT_REASON] };
|
|
2108
|
+
let param = || -> Option<Retained<NSAppleEventDescriptor>> { unsafe { msg_send![&*event, paramDescriptorForKeyword: QUIT_REASON] } };
|
|
2109
|
+
let reason = attribute.or_else(param)?;
|
|
2110
|
+
Some(if reason.enumCodeValue() != 0 { reason.enumCodeValue() } else { reason.typeCodeValue() })
|
|
2111
|
+
}
|
|
2112
|
+
|
|
2113
|
+
extern "C-unwind" fn application_should_terminate(_this: &AnyObject, _sel: Sel, _sender: *mut AnyObject) -> NSApplicationTerminateReply {
|
|
2114
|
+
let session_end = quit_reason().is_some_and(is_session_end);
|
|
2115
|
+
match super::should_terminate(session_end) {
|
|
2116
|
+
TerminateReply::Now => NSApplicationTerminateReply::TerminateNow,
|
|
2117
|
+
TerminateReply::Cancel => NSApplicationTerminateReply::TerminateCancel,
|
|
2118
|
+
TerminateReply::Later => NSApplicationTerminateReply::TerminateLater,
|
|
2119
|
+
}
|
|
2120
|
+
}
|
|
2121
|
+
|
|
2122
|
+
/// TAO's app delegate does not implement applicationShouldTerminate:
|
|
2123
|
+
/// (tao/src/platform_impl/macos/app_delegate.rs), so AppKit would quit without asking the plugin
|
|
2124
|
+
/// host. Add it to TAO's delegate class at runtime, as Electrobun's own delegate implements it
|
|
2125
|
+
/// (electrobun/package/src/native/macos/nativeWrapper.mm:7097-7110).
|
|
2126
|
+
pub fn install_terminate_handler() {
|
|
2127
|
+
let Some(class) = AnyClass::get(c"TaoAppDelegateParent") else {
|
|
2128
|
+
log!("TaoAppDelegateParent not found: quitting skips the plugin host");
|
|
2129
|
+
return;
|
|
2130
|
+
};
|
|
2131
|
+
let imp = application_should_terminate as extern "C-unwind" fn(&AnyObject, Sel, *mut AnyObject) -> NSApplicationTerminateReply;
|
|
2132
|
+
// Safety: the signature matches the type encoding "Q@:@" (NSUInteger return, self, _cmd, sender).
|
|
2133
|
+
let added = unsafe {
|
|
2134
|
+
objc2::ffi::class_addMethod(
|
|
2135
|
+
class as *const AnyClass as *mut AnyClass,
|
|
2136
|
+
sel!(applicationShouldTerminate:),
|
|
2137
|
+
std::mem::transmute::<_, Imp>(imp),
|
|
2138
|
+
c"Q@:@".as_ptr(),
|
|
2139
|
+
)
|
|
2140
|
+
};
|
|
2141
|
+
if !added.as_bool() {
|
|
2142
|
+
log!("TaoAppDelegateParent already implements applicationShouldTerminate:; quitting skips the plugin host");
|
|
2143
|
+
}
|
|
2144
|
+
}
|
|
2145
|
+
|
|
2146
|
+
pub fn reply_to_terminate(yes: bool) {
|
|
2147
|
+
if let Some(mtm) = MainThreadMarker::new() {
|
|
2148
|
+
NSApplication::sharedApplication(mtm).replyToApplicationShouldTerminate(yes);
|
|
2149
|
+
}
|
|
2150
|
+
}
|
|
2151
|
+
|
|
2152
|
+
pub fn is_main_thread() -> bool {
|
|
2153
|
+
MainThreadMarker::new().is_some()
|
|
2154
|
+
}
|
|
2155
|
+
|
|
2156
|
+
pub fn is_dark_mode() -> bool {
|
|
2157
|
+
let Some(mtm) = MainThreadMarker::new() else { return false };
|
|
2158
|
+
let app = NSApplication::sharedApplication(mtm);
|
|
2159
|
+
app.effectiveAppearance().name().to_string().contains("Dark")
|
|
2160
|
+
}
|
|
2161
|
+
|
|
2162
|
+
pub fn open_url(url: &str) {
|
|
2163
|
+
if let Some(u) = NSURL::URLWithString(&NSString::from_str(url)) {
|
|
2164
|
+
NSWorkspace::sharedWorkspace().openURL(&u);
|
|
2165
|
+
}
|
|
2166
|
+
}
|
|
2167
|
+
|
|
2168
|
+
}
|
|
2169
|
+
|
|
2170
|
+
#[cfg(all(test, target_os = "macos"))]
|
|
2171
|
+
mod quit_tests {
|
|
2172
|
+
use super::macos::is_session_end;
|
|
2173
|
+
|
|
2174
|
+
#[test]
|
|
2175
|
+
fn session_end_reasons() {
|
|
2176
|
+
for code in [b"logo", b"rlgo", b"rrst", b"rsdn", b"rest", b"shut"] {
|
|
2177
|
+
assert!(is_session_end(u32::from_be_bytes(*code)));
|
|
2178
|
+
}
|
|
2179
|
+
assert!(!is_session_end(u32::from_be_bytes(*b"quia"))); // kAEQuitAll
|
|
2180
|
+
assert!(!is_session_end(0));
|
|
2181
|
+
}
|
|
2182
|
+
}
|
|
2183
|
+
|
|
2184
|
+
#[cfg(test)]
|
|
2185
|
+
mod asset_path_tests {
|
|
2186
|
+
use super::asset_path;
|
|
2187
|
+
use std::path::Path;
|
|
2188
|
+
|
|
2189
|
+
#[test]
|
|
2190
|
+
fn asset_paths_stay_in_the_app_folder() {
|
|
2191
|
+
let dir = Path::new("app");
|
|
2192
|
+
assert_eq!(asset_path(dir, "img/a b.png"), Some(dir.join("img/a b.png")));
|
|
2193
|
+
for rel in ["/etc/passwd", "../x", "a/../b"] {
|
|
2194
|
+
assert_eq!(asset_path(dir, rel), None, "{rel}");
|
|
2195
|
+
}
|
|
2196
|
+
#[cfg(windows)]
|
|
2197
|
+
for rel in ["C:/Users/u/.ssh/id_rsa", "C:x", r"\\server\share\x"] {
|
|
2198
|
+
assert_eq!(asset_path(dir, rel), None, "{rel}");
|
|
2199
|
+
}
|
|
2200
|
+
}
|
|
2201
|
+
}
|
|
2202
|
+
|
|
2203
|
+
#[cfg(test)]
|
|
2204
|
+
mod range_tests {
|
|
2205
|
+
// The header rules are in the shared vectors (vectors.rs); this checks what reaches the page.
|
|
2206
|
+
#[test]
|
|
2207
|
+
fn ranged_reads_take_only_their_part() {
|
|
2208
|
+
let dir = std::env::temp_dir().join(format!("akan-native-range-{}", std::process::id()));
|
|
2209
|
+
std::fs::create_dir_all(&dir).unwrap();
|
|
2210
|
+
let file = dir.join("big.bin");
|
|
2211
|
+
let data: Vec<u8> = (0..(crate::contract::MAX_RANGE_BYTES * 3)).map(|i| (i % 251) as u8).collect();
|
|
2212
|
+
std::fs::write(&file, &data).unwrap();
|
|
2213
|
+
let r = super::read_file(&file, "video/mp4", super::Served::Asset, Some("bytes=10-")).unwrap();
|
|
2214
|
+
assert_eq!(r.status(), 206);
|
|
2215
|
+
assert_eq!(r.body().as_slice(), &data[10..10 + crate::contract::MAX_RANGE_BYTES]);
|
|
2216
|
+
assert_eq!(r.headers()["content-range"], format!("bytes 10-{}/{}", 9 + crate::contract::MAX_RANGE_BYTES, data.len()));
|
|
2217
|
+
let r = super::read_file(&file, "video/mp4", super::Served::Asset, Some("bytes=5-9")).unwrap();
|
|
2218
|
+
assert_eq!(r.body().as_slice(), &data[5..10]);
|
|
2219
|
+
let r = super::read_file(&file, "video/mp4", super::Served::Asset, None).unwrap();
|
|
2220
|
+
assert_eq!((r.status().as_u16(), r.body().len()), (200, data.len()));
|
|
2221
|
+
assert_eq!(super::read_file(&file, "video/mp4", super::Served::Asset, Some("bytes=999999999-")).unwrap().status(), 416);
|
|
2222
|
+
assert_eq!(super::read_file(&file, "bad\nvalue", super::Served::Asset, None).unwrap().status(), 500);
|
|
2223
|
+
// FileRefs: no sniffing, same-origin only, and sandboxed unless plain media (N1).
|
|
2224
|
+
let r = super::read_file(&file, "text/html", super::Served::FileRef, None).unwrap();
|
|
2225
|
+
assert_eq!(r.headers()["x-content-type-options"], "nosniff");
|
|
2226
|
+
assert_eq!(r.headers()["cross-origin-resource-policy"], "same-origin");
|
|
2227
|
+
assert_eq!(r.headers()["content-security-policy"], "sandbox");
|
|
2228
|
+
let r = super::read_file(&file, "image/png", super::Served::FileRef, None).unwrap();
|
|
2229
|
+
assert!(r.headers().get("content-security-policy").is_none());
|
|
2230
|
+
assert!(super::read_file(&file, "text/html", super::Served::Asset, None).unwrap().headers().get("content-security-policy").is_none());
|
|
2231
|
+
std::fs::remove_dir_all(&dir).unwrap();
|
|
2232
|
+
}
|
|
2233
|
+
}
|
|
2234
|
+
|
|
2235
|
+
#[cfg(test)]
|
|
2236
|
+
mod window_arg_tests {
|
|
2237
|
+
use super::{app_path, json, parse_config, window_arg};
|
|
2238
|
+
|
|
2239
|
+
#[test]
|
|
2240
|
+
fn window_ids() {
|
|
2241
|
+
let arg = |s: &str| window_arg(&json::parse(s).unwrap());
|
|
2242
|
+
assert_eq!(arg(r#"{}"#), Ok(None));
|
|
2243
|
+
assert_eq!(arg(r#"{"window":2}"#), Ok(Some(2)));
|
|
2244
|
+
for bad in [r#"{"window":0}"#, r#"{"window":-1}"#, r#"{"window":1.5}"#, r#"{"window":"2"}"#, r#"{"window":1e12}"#] {
|
|
2245
|
+
assert!(arg(bad).is_err(), "{bad}");
|
|
2246
|
+
}
|
|
2247
|
+
}
|
|
2248
|
+
|
|
2249
|
+
#[test]
|
|
2250
|
+
fn app_paths() {
|
|
2251
|
+
let path = |s: &str| app_path(&json::parse(s).unwrap());
|
|
2252
|
+
assert_eq!(path(r#"{}"#), Ok("/".into()));
|
|
2253
|
+
assert_eq!(path(r#"{"path":"/settings?tab=2#a"}"#), Ok("/settings?tab=2#a".into()));
|
|
2254
|
+
for bad in [r#"{"path":"settings"}"#, r#"{"path":"//evil.com/x"}"#, r#"{"path":"https://example.com"}"#, r#"{"path":"/a\\b"}"#, r#"{"path":"/a\nb"}"#, r#"{"path":3}"#] {
|
|
2255
|
+
assert!(path(bad).is_err(), "{bad}");
|
|
2256
|
+
}
|
|
2257
|
+
}
|
|
2258
|
+
|
|
2259
|
+
#[test]
|
|
2260
|
+
fn start_paths() {
|
|
2261
|
+
let start = |extra: &str| parse_config(&format!(r#"{{"appDir":"/a","initJs":""{extra}}}"#)).map(|c| c.start_path);
|
|
2262
|
+
assert_eq!(start(""), Ok("/".into()));
|
|
2263
|
+
assert_eq!(start(r#","startPath":"/en/home?csr=true""#), Ok("/en/home?csr=true".into()));
|
|
2264
|
+
assert!(start(r#","startPath":"//evil.com/x""#).is_err());
|
|
2265
|
+
}
|
|
2266
|
+
}
|
|
2267
|
+
|
|
2268
|
+
#[cfg(test)]
|
|
2269
|
+
mod drag_drop_tests {
|
|
2270
|
+
use super::*;
|
|
2271
|
+
|
|
2272
|
+
#[test]
|
|
2273
|
+
fn reports_file_drags_only() {
|
|
2274
|
+
let files = std::cell::Cell::new(false);
|
|
2275
|
+
let ev = |e| drag_drop_event(2, &files, e, 1.0);
|
|
2276
|
+
// A text drag: nothing, including its Over and Leave.
|
|
2277
|
+
assert_eq!(ev(DragDropEvent::Enter { paths: vec![], position: (1, 2) }), None);
|
|
2278
|
+
assert_eq!(ev(DragDropEvent::Over { position: (3, 4) }), None);
|
|
2279
|
+
assert_eq!(ev(DragDropEvent::Leave), None);
|
|
2280
|
+
// A file drag.
|
|
2281
|
+
let enter = ev(DragDropEvent::Enter { paths: vec![PathBuf::from("/tmp/a \"b\".txt")], position: (10, 20) }).unwrap();
|
|
2282
|
+
assert_eq!(enter, r#"{"type":"dragDrop","window":2,"event":"enter","paths":["/tmp/a \"b\".txt"],"x":10,"y":20}"#);
|
|
2283
|
+
assert!(json::parse(&enter).is_ok());
|
|
2284
|
+
assert_eq!(ev(DragDropEvent::Over { position: (11, 21) }).unwrap(), r#"{"type":"dragDrop","window":2,"event":"over","x":11,"y":21}"#);
|
|
2285
|
+
let drop = ev(DragDropEvent::Drop { paths: vec![PathBuf::from("/tmp/x")], position: (5, 6) }).unwrap();
|
|
2286
|
+
assert!(drop.contains(r#""event":"drop","paths":["/tmp/x"]"#));
|
|
2287
|
+
// After the drop, a following text drag is quiet again.
|
|
2288
|
+
assert_eq!(ev(DragDropEvent::Over { position: (0, 0) }), None);
|
|
2289
|
+
}
|
|
2290
|
+
|
|
2291
|
+
/// WebView2's physical pixels become CSS pixels (N6): 150 % scaling.
|
|
2292
|
+
#[test]
|
|
2293
|
+
fn positions_are_css_pixels() {
|
|
2294
|
+
let files = std::cell::Cell::new(false);
|
|
2295
|
+
let enter = drag_drop_event(1, &files, DragDropEvent::Enter { paths: vec![PathBuf::from("/a")], position: (150, 301) }, 1.5).unwrap();
|
|
2296
|
+
assert!(enter.ends_with(r#""x":100,"y":200.67}"#), "{enter}");
|
|
2297
|
+
}
|
|
2298
|
+
}
|
|
2299
|
+
|
|
2300
|
+
#[cfg(test)]
|
|
2301
|
+
mod recovery_tests {
|
|
2302
|
+
use super::recovery_wait;
|
|
2303
|
+
use std::time::Duration;
|
|
2304
|
+
|
|
2305
|
+
#[test]
|
|
2306
|
+
fn waits_longer_after_each_end_in_a_row_up_to_a_minute() {
|
|
2307
|
+
let secs: Vec<u64> = (0..10).map(|streak| recovery_wait(streak).map_or(0, |d| d.as_secs())).collect();
|
|
2308
|
+
assert_eq!(secs, [0, 1, 2, 4, 8, 16, 32, 60, 60, 60]);
|
|
2309
|
+
assert_eq!(recovery_wait(u32::MAX), Some(Duration::from_secs(60)));
|
|
2310
|
+
}
|
|
2311
|
+
|
|
2312
|
+
#[test]
|
|
2313
|
+
fn reads_the_recovery_policy_and_refuses_an_unknown_one() {
|
|
2314
|
+
let base = r#""appDir":"/a","initJs":"x""#;
|
|
2315
|
+
assert!(!super::parse_config(&format!("{{{base}}}")).unwrap().recovery_reload);
|
|
2316
|
+
assert!(super::parse_config(&format!(r#"{{{base},"recovery":"reload","fullscreen":true}}"#)).unwrap().recovery_reload);
|
|
2317
|
+
assert!(super::parse_config(&format!(r#"{{{base},"recovery":"always"}}"#)).is_err());
|
|
2318
|
+
assert!(super::parse_config(&format!(r#"{{{base},"screenCapture":"auto"}}"#)).unwrap().screen_capture_auto);
|
|
2319
|
+
assert!(super::parse_config(&format!(r#"{{{base},"screenCapture":"any"}}"#)).is_err());
|
|
2320
|
+
}
|
|
2321
|
+
}
|