Files
MyGoNavi/internal/nativewindow/runtime_script.go
Syngnat fa9d21be8b feat(native-window): 支持标签页拖出为原生独立窗口
- 支持 SQL、数据和结果标签拖出到跨显示器原生窗口
- 通过受认证 loopback bridge 复用主进程后端与状态
- 支持子窗口继续拆窗、聚焦、关闭、还原与异常退出恢复
- 补充多窗口协议、状态同步和跨平台回归测试
2026-07-16 20:25:08 +08:00

111 lines
3.3 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;
},
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 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' && control && typeof control.Close === 'function') {
control.Close();
} else if (command.action === 'focus' && control && typeof control.Focus === 'function') {
control.Focus();
}
});
}, -1);
}
})();`
}