mirror of
https://github.com/Syngnat/GoNavi.git
synced 2026-08-11 01:03:51 +08:00
- 支持全部工作台标签与 AI 对话在多显示器中原生独立展示 - 修复拖拽指针捕获,恢复关闭、右键菜单和跨窗口释放识别 - 拆分子窗启动入口并按需加载语言与工作台内容 - 内容与 Monaco 完成可见绘制后再提交迁移,消除白屏和加载闪烁 - 加固结果编辑、宿主同步及关闭、超时和焦点竞态
122 lines
3.6 KiB
Go
122 lines
3.6 KiB
Go
package nativewindow
|
|
|
|
func detachedRuntimeBridgeScript() string {
|
|
return `(function () {
|
|
if (typeof window === 'undefined') return;
|
|
|
|
var existingGo = window.go || {};
|
|
var nativeNamespace = existingGo.nativewindow || {};
|
|
var bridge = nativeNamespace.Bridge;
|
|
var control = nativeNamespace.Control;
|
|
if (
|
|
!bridge
|
|
|| typeof bridge.Invoke !== 'function'
|
|
|| typeof bridge.WindowID !== 'function'
|
|
|| typeof bridge.OpenWindow !== 'function'
|
|
|| typeof bridge.FocusWindow !== 'function'
|
|
|| typeof bridge.CloseWindow !== 'function'
|
|
|| typeof bridge.CloseOwnedWindows !== 'function'
|
|
) {
|
|
console.error('[GoNavi Detached] native bridge is unavailable');
|
|
return;
|
|
}
|
|
|
|
var invoke = function (namespace, receiver, method, args) {
|
|
return bridge.Invoke(namespace, receiver, method, Array.isArray(args) ? args : []);
|
|
};
|
|
var buildServiceProxy = function (namespace, receiver) {
|
|
return new Proxy({}, {
|
|
get: function (_target, property) {
|
|
if (typeof property !== 'string') return undefined;
|
|
return function () {
|
|
return invoke(namespace, receiver, property, Array.prototype.slice.call(arguments));
|
|
};
|
|
}
|
|
});
|
|
};
|
|
var parentWindowManager = {
|
|
Open: function (request) {
|
|
return bridge.OpenWindow(request || {});
|
|
},
|
|
Focus: function (id) {
|
|
return bridge.FocusWindow(String(id || ''));
|
|
},
|
|
Close: function (id) {
|
|
return bridge.CloseWindow(String(id || ''));
|
|
},
|
|
CloseAll: function () {
|
|
return bridge.CloseOwnedWindows();
|
|
}
|
|
};
|
|
nativeNamespace = {
|
|
...nativeNamespace,
|
|
Manager: parentWindowManager
|
|
};
|
|
|
|
window.go = {
|
|
...existingGo,
|
|
nativewindow: nativeNamespace,
|
|
app: {
|
|
...(existingGo.app || {}),
|
|
App: buildServiceProxy('app', 'App')
|
|
},
|
|
aiservice: {
|
|
...(existingGo.aiservice || {}),
|
|
Service: buildServiceProxy('aiservice', 'Service')
|
|
}
|
|
};
|
|
|
|
var detached = {
|
|
active: true,
|
|
bootstrap: null,
|
|
bootstrapPromise: null,
|
|
loadBootstrap: function () {
|
|
if (!detached.bootstrapPromise) {
|
|
detached.bootstrapPromise = bridge.Bootstrap().then(function (payload) {
|
|
detached.bootstrap = payload;
|
|
return payload;
|
|
});
|
|
}
|
|
return detached.bootstrapPromise;
|
|
},
|
|
present: function () {
|
|
if (!control || typeof control.Present !== 'function') {
|
|
return Promise.reject(new Error('native window present control is unavailable'));
|
|
}
|
|
return control.Present();
|
|
},
|
|
action: function (action, payload) {
|
|
return bridge.Action(String(action || ''), payload || {});
|
|
}
|
|
};
|
|
window.__GONAVI_DETACHED__ = detached;
|
|
window.__GONAVI_DETACHED_RUNTIME__ = {
|
|
buildType: 'desktop-detached',
|
|
capabilities: { nativeWindow: true, sharedBackend: true }
|
|
};
|
|
|
|
var detachedWindowIDPromise = Promise.resolve(bridge.WindowID()).then(function (windowID) {
|
|
return String(windowID || '');
|
|
});
|
|
var requestGracefulClose = function (reason) {
|
|
window.dispatchEvent(new CustomEvent('` + GracefulCloseRequestEventName + `', {
|
|
detail: { reason: String(reason || '') }
|
|
}));
|
|
};
|
|
|
|
var runtime = window.runtime || {};
|
|
if (typeof runtime.EventsOnMultiple === 'function') {
|
|
runtime.EventsOnMultiple('` + CommandEventName + `', function (command) {
|
|
detachedWindowIDPromise.then(function (windowID) {
|
|
if (!command || String(command.id || '') !== windowID) return;
|
|
if (command.action === 'close') {
|
|
requestGracefulClose(command.reason);
|
|
} else if (command.action === 'focus' && control && typeof control.Focus === 'function') {
|
|
control.Focus();
|
|
}
|
|
});
|
|
}, -1);
|
|
}
|
|
})();`
|
|
}
|