mirror of
https://github.com/Youzini-afk/ST-Bionic-Memory-Ecology.git
synced 2026-05-15 22:30:38 +08:00
perf: reduce graph panel refresh churn during streaming
This commit is contained in:
186
tests/panel-graph-refresh.mjs
Normal file
186
tests/panel-graph-refresh.mjs
Normal file
@@ -0,0 +1,186 @@
|
|||||||
|
import assert from "node:assert/strict";
|
||||||
|
|
||||||
|
import {
|
||||||
|
buildVisibleGraphRefreshToken,
|
||||||
|
resolveVisibleGraphWorkspaceMode,
|
||||||
|
} from "../ui/panel-graph-refresh-utils.js";
|
||||||
|
|
||||||
|
assert.equal(
|
||||||
|
resolveVisibleGraphWorkspaceMode({
|
||||||
|
overlayActive: false,
|
||||||
|
isMobile: false,
|
||||||
|
currentTabId: "dashboard",
|
||||||
|
currentGraphView: "graph",
|
||||||
|
}),
|
||||||
|
"hidden",
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.equal(
|
||||||
|
resolveVisibleGraphWorkspaceMode({
|
||||||
|
overlayActive: true,
|
||||||
|
isMobile: false,
|
||||||
|
currentTabId: "config",
|
||||||
|
currentGraphView: "graph",
|
||||||
|
}),
|
||||||
|
"hidden",
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.equal(
|
||||||
|
resolveVisibleGraphWorkspaceMode({
|
||||||
|
overlayActive: true,
|
||||||
|
isMobile: false,
|
||||||
|
currentTabId: "dashboard",
|
||||||
|
currentGraphView: "graph",
|
||||||
|
}),
|
||||||
|
"desktop:graph",
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.equal(
|
||||||
|
resolveVisibleGraphWorkspaceMode({
|
||||||
|
overlayActive: true,
|
||||||
|
isMobile: false,
|
||||||
|
currentTabId: "memory",
|
||||||
|
currentGraphView: "cognition",
|
||||||
|
}),
|
||||||
|
"desktop:cognition",
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.equal(
|
||||||
|
resolveVisibleGraphWorkspaceMode({
|
||||||
|
overlayActive: true,
|
||||||
|
isMobile: false,
|
||||||
|
currentTabId: "actions",
|
||||||
|
currentGraphView: "summary",
|
||||||
|
}),
|
||||||
|
"desktop:summary",
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.equal(
|
||||||
|
resolveVisibleGraphWorkspaceMode({
|
||||||
|
overlayActive: true,
|
||||||
|
isMobile: true,
|
||||||
|
currentTabId: "dashboard",
|
||||||
|
currentMobileGraphView: "graph",
|
||||||
|
}),
|
||||||
|
"hidden",
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.equal(
|
||||||
|
resolveVisibleGraphWorkspaceMode({
|
||||||
|
overlayActive: true,
|
||||||
|
isMobile: true,
|
||||||
|
currentTabId: "graph",
|
||||||
|
currentMobileGraphView: "graph",
|
||||||
|
}),
|
||||||
|
"mobile:graph",
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.equal(
|
||||||
|
resolveVisibleGraphWorkspaceMode({
|
||||||
|
overlayActive: true,
|
||||||
|
isMobile: true,
|
||||||
|
currentTabId: "graph",
|
||||||
|
currentMobileGraphView: "cognition",
|
||||||
|
}),
|
||||||
|
"mobile:cognition",
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.equal(
|
||||||
|
resolveVisibleGraphWorkspaceMode({
|
||||||
|
overlayActive: true,
|
||||||
|
isMobile: true,
|
||||||
|
currentTabId: "graph",
|
||||||
|
currentMobileGraphView: "summary",
|
||||||
|
}),
|
||||||
|
"mobile:summary",
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.equal(
|
||||||
|
buildVisibleGraphRefreshToken({
|
||||||
|
visibleMode: "hidden",
|
||||||
|
chatId: "chat-main",
|
||||||
|
loadState: "loaded",
|
||||||
|
revision: 12,
|
||||||
|
nodeCount: 40,
|
||||||
|
edgeCount: 55,
|
||||||
|
lastProcessedSeq: 9,
|
||||||
|
}),
|
||||||
|
"hidden",
|
||||||
|
);
|
||||||
|
|
||||||
|
const baseToken = buildVisibleGraphRefreshToken({
|
||||||
|
visibleMode: "desktop:graph",
|
||||||
|
chatId: "chat-main",
|
||||||
|
loadState: "loaded",
|
||||||
|
revision: 12,
|
||||||
|
nodeCount: 40,
|
||||||
|
edgeCount: 55,
|
||||||
|
lastProcessedSeq: 9,
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(
|
||||||
|
baseToken,
|
||||||
|
buildVisibleGraphRefreshToken({
|
||||||
|
visibleMode: "desktop:graph",
|
||||||
|
chatId: "chat-main",
|
||||||
|
loadState: "loaded",
|
||||||
|
revision: 12,
|
||||||
|
nodeCount: 40,
|
||||||
|
edgeCount: 55,
|
||||||
|
lastProcessedSeq: 9,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.notEqual(
|
||||||
|
baseToken,
|
||||||
|
buildVisibleGraphRefreshToken({
|
||||||
|
visibleMode: "desktop:graph",
|
||||||
|
chatId: "chat-main",
|
||||||
|
loadState: "loaded",
|
||||||
|
revision: 13,
|
||||||
|
nodeCount: 40,
|
||||||
|
edgeCount: 55,
|
||||||
|
lastProcessedSeq: 9,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.notEqual(
|
||||||
|
baseToken,
|
||||||
|
buildVisibleGraphRefreshToken({
|
||||||
|
visibleMode: "desktop:cognition",
|
||||||
|
chatId: "chat-main",
|
||||||
|
loadState: "loaded",
|
||||||
|
revision: 12,
|
||||||
|
nodeCount: 40,
|
||||||
|
edgeCount: 55,
|
||||||
|
lastProcessedSeq: 9,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.notEqual(
|
||||||
|
baseToken,
|
||||||
|
buildVisibleGraphRefreshToken({
|
||||||
|
visibleMode: "desktop:graph",
|
||||||
|
chatId: "chat-side",
|
||||||
|
loadState: "loaded",
|
||||||
|
revision: 12,
|
||||||
|
nodeCount: 40,
|
||||||
|
edgeCount: 55,
|
||||||
|
lastProcessedSeq: 9,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.notEqual(
|
||||||
|
baseToken,
|
||||||
|
buildVisibleGraphRefreshToken({
|
||||||
|
visibleMode: "desktop:graph",
|
||||||
|
chatId: "chat-main",
|
||||||
|
loadState: "loaded",
|
||||||
|
revision: 12,
|
||||||
|
nodeCount: 41,
|
||||||
|
edgeCount: 55,
|
||||||
|
lastProcessedSeq: 9,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log("panel-graph-refresh tests passed");
|
||||||
59
ui/panel-graph-refresh-utils.js
Normal file
59
ui/panel-graph-refresh-utils.js
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
export function resolveVisibleGraphWorkspaceMode({
|
||||||
|
overlayActive = false,
|
||||||
|
isMobile = false,
|
||||||
|
currentTabId = "dashboard",
|
||||||
|
currentGraphView = "graph",
|
||||||
|
currentMobileGraphView = "graph",
|
||||||
|
} = {}) {
|
||||||
|
if (!overlayActive) return "hidden";
|
||||||
|
if (isMobile) {
|
||||||
|
if (currentTabId !== "graph") return "hidden";
|
||||||
|
const mobileView = String(currentMobileGraphView || "graph").trim() || "graph";
|
||||||
|
return mobileView === "cognition"
|
||||||
|
? "mobile:cognition"
|
||||||
|
: mobileView === "summary"
|
||||||
|
? "mobile:summary"
|
||||||
|
: "mobile:graph";
|
||||||
|
}
|
||||||
|
if (currentTabId === "config") return "hidden";
|
||||||
|
const desktopView = String(currentGraphView || "graph").trim() || "graph";
|
||||||
|
return desktopView === "cognition"
|
||||||
|
? "desktop:cognition"
|
||||||
|
: desktopView === "summary"
|
||||||
|
? "desktop:summary"
|
||||||
|
: "desktop:graph";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function buildVisibleGraphRefreshToken({
|
||||||
|
visibleMode = "hidden",
|
||||||
|
chatId = "",
|
||||||
|
loadState = "",
|
||||||
|
revision = 0,
|
||||||
|
nodeCount = -1,
|
||||||
|
edgeCount = -1,
|
||||||
|
lastProcessedSeq = -1,
|
||||||
|
} = {}) {
|
||||||
|
const normalizedMode = String(visibleMode || "hidden").trim() || "hidden";
|
||||||
|
if (normalizedMode === "hidden") return "hidden";
|
||||||
|
const normalizedRevision = Number.isFinite(Number(revision))
|
||||||
|
? Math.trunc(Number(revision))
|
||||||
|
: 0;
|
||||||
|
const normalizedNodeCount = Number.isFinite(Number(nodeCount))
|
||||||
|
? Math.trunc(Number(nodeCount))
|
||||||
|
: -1;
|
||||||
|
const normalizedEdgeCount = Number.isFinite(Number(edgeCount))
|
||||||
|
? Math.trunc(Number(edgeCount))
|
||||||
|
: -1;
|
||||||
|
const normalizedLastProcessedSeq = Number.isFinite(Number(lastProcessedSeq))
|
||||||
|
? Math.trunc(Number(lastProcessedSeq))
|
||||||
|
: -1;
|
||||||
|
return [
|
||||||
|
normalizedMode,
|
||||||
|
String(chatId || "").trim(),
|
||||||
|
String(loadState || "").trim() || "unknown",
|
||||||
|
normalizedRevision,
|
||||||
|
normalizedNodeCount,
|
||||||
|
normalizedEdgeCount,
|
||||||
|
normalizedLastProcessedSeq,
|
||||||
|
].join("|");
|
||||||
|
}
|
||||||
190
ui/panel.js
190
ui/panel.js
@@ -1,6 +1,10 @@
|
|||||||
// ST-BME: 操控面板交互逻辑
|
// ST-BME: 操控面板交互逻辑
|
||||||
|
|
||||||
import { GraphRenderer } from "./graph-renderer.js";
|
import { GraphRenderer } from "./graph-renderer.js";
|
||||||
|
import {
|
||||||
|
buildVisibleGraphRefreshToken,
|
||||||
|
resolveVisibleGraphWorkspaceMode,
|
||||||
|
} from "./panel-graph-refresh-utils.js";
|
||||||
import { getNodeDisplayName } from "../graph/node-labels.js";
|
import { getNodeDisplayName } from "../graph/node-labels.js";
|
||||||
import {
|
import {
|
||||||
buildRegionLine,
|
buildRegionLine,
|
||||||
@@ -335,6 +339,12 @@ let fetchedBackendEmbeddingModels = [];
|
|||||||
let fetchedDirectEmbeddingModels = [];
|
let fetchedDirectEmbeddingModels = [];
|
||||||
let viewportSyncBound = false;
|
let viewportSyncBound = false;
|
||||||
let popupRuntimePromise = null;
|
let popupRuntimePromise = null;
|
||||||
|
const GRAPH_LIVE_REFRESH_THROTTLE_MS = 240;
|
||||||
|
let pendingVisibleGraphRefreshTimer = null;
|
||||||
|
let pendingVisibleGraphRefreshToken = "";
|
||||||
|
let pendingVisibleGraphRefreshForce = false;
|
||||||
|
let lastVisibleGraphRefreshToken = "";
|
||||||
|
let lastVisibleGraphRefreshAt = 0;
|
||||||
|
|
||||||
// 由 index.js 注入的引用
|
// 由 index.js 注入的引用
|
||||||
let _getGraph = null;
|
let _getGraph = null;
|
||||||
@@ -684,6 +694,143 @@ function bindViewportSync() {
|
|||||||
window.visualViewport?.addEventListener("scroll", update);
|
window.visualViewport?.addEventListener("scroll", update);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function _getVisibleGraphWorkspaceMode() {
|
||||||
|
return resolveVisibleGraphWorkspaceMode({
|
||||||
|
overlayActive: overlayEl?.classList.contains("active") === true,
|
||||||
|
isMobile: _isMobile(),
|
||||||
|
currentTabId,
|
||||||
|
currentGraphView,
|
||||||
|
currentMobileGraphView,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function _getCurrentGraphRefreshToken() {
|
||||||
|
const graph = _getGraph?.();
|
||||||
|
const persistence = _getGraphPersistenceSnapshot();
|
||||||
|
return buildVisibleGraphRefreshToken({
|
||||||
|
visibleMode: _getVisibleGraphWorkspaceMode(),
|
||||||
|
chatId: persistence?.chatId,
|
||||||
|
loadState: persistence?.loadState,
|
||||||
|
revision:
|
||||||
|
persistence?.revision ??
|
||||||
|
persistence?.lastAcceptedRevision ??
|
||||||
|
persistence?.lastSyncedRevision ??
|
||||||
|
0,
|
||||||
|
nodeCount: Array.isArray(graph?.nodes) ? graph.nodes.length : -1,
|
||||||
|
edgeCount: Array.isArray(graph?.edges) ? graph.edges.length : -1,
|
||||||
|
lastProcessedSeq: graph?.historyState?.lastProcessedAssistantFloor ?? -1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function _clearScheduledVisibleGraphRefresh() {
|
||||||
|
if (pendingVisibleGraphRefreshTimer) {
|
||||||
|
clearTimeout(pendingVisibleGraphRefreshTimer);
|
||||||
|
pendingVisibleGraphRefreshTimer = null;
|
||||||
|
}
|
||||||
|
pendingVisibleGraphRefreshToken = "";
|
||||||
|
pendingVisibleGraphRefreshForce = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function _refreshVisibleGraphWorkspace({ force = false } = {}) {
|
||||||
|
const visibleMode = _getVisibleGraphWorkspaceMode();
|
||||||
|
if (visibleMode === "hidden") {
|
||||||
|
return { refreshed: false, reason: "hidden" };
|
||||||
|
}
|
||||||
|
|
||||||
|
const graph = _getGraph?.();
|
||||||
|
const nextToken = _getCurrentGraphRefreshToken();
|
||||||
|
if (!force && nextToken === lastVisibleGraphRefreshToken) {
|
||||||
|
return { refreshed: false, reason: "unchanged", token: nextToken };
|
||||||
|
}
|
||||||
|
|
||||||
|
const hints = { userPovAliases: _hostUserPovAliasHintsForGraph() };
|
||||||
|
if (visibleMode === "desktop:graph") {
|
||||||
|
if (graph && graphRenderer) {
|
||||||
|
graphRenderer.loadGraph(graph, hints);
|
||||||
|
}
|
||||||
|
} else if (visibleMode === "desktop:cognition") {
|
||||||
|
_refreshCognitionWorkspace();
|
||||||
|
} else if (visibleMode === "desktop:summary") {
|
||||||
|
_refreshSummaryWorkspace();
|
||||||
|
} else if (visibleMode === "mobile:graph") {
|
||||||
|
if (graph && mobileGraphRenderer) {
|
||||||
|
mobileGraphRenderer.loadGraph(graph, hints);
|
||||||
|
}
|
||||||
|
_buildMobileLegend();
|
||||||
|
} else if (visibleMode === "mobile:cognition") {
|
||||||
|
_refreshMobileCognitionFull();
|
||||||
|
} else if (visibleMode === "mobile:summary") {
|
||||||
|
_refreshMobileSummaryFull();
|
||||||
|
}
|
||||||
|
|
||||||
|
lastVisibleGraphRefreshToken = nextToken;
|
||||||
|
lastVisibleGraphRefreshAt = Date.now();
|
||||||
|
return {
|
||||||
|
refreshed: true,
|
||||||
|
reason: force ? "forced" : "changed",
|
||||||
|
token: nextToken,
|
||||||
|
visibleMode,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function _flushScheduledVisibleGraphRefresh() {
|
||||||
|
const shouldForce = pendingVisibleGraphRefreshForce === true;
|
||||||
|
_clearScheduledVisibleGraphRefresh();
|
||||||
|
return _refreshVisibleGraphWorkspace({ force: shouldForce });
|
||||||
|
}
|
||||||
|
|
||||||
|
function _scheduleVisibleGraphWorkspaceRefresh({ force = false } = {}) {
|
||||||
|
const nextToken = _getCurrentGraphRefreshToken();
|
||||||
|
if (nextToken === "hidden") {
|
||||||
|
_clearScheduledVisibleGraphRefresh();
|
||||||
|
return { scheduled: false, reason: "hidden" };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (force) {
|
||||||
|
_clearScheduledVisibleGraphRefresh();
|
||||||
|
return _refreshVisibleGraphWorkspace({ force: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nextToken === lastVisibleGraphRefreshToken) {
|
||||||
|
return { scheduled: false, reason: "unchanged", token: nextToken };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
pendingVisibleGraphRefreshTimer &&
|
||||||
|
pendingVisibleGraphRefreshToken === nextToken &&
|
||||||
|
pendingVisibleGraphRefreshForce !== true
|
||||||
|
) {
|
||||||
|
return { scheduled: true, reason: "pending", token: nextToken };
|
||||||
|
}
|
||||||
|
|
||||||
|
const delay = Math.max(
|
||||||
|
0,
|
||||||
|
GRAPH_LIVE_REFRESH_THROTTLE_MS - (Date.now() - lastVisibleGraphRefreshAt),
|
||||||
|
);
|
||||||
|
pendingVisibleGraphRefreshToken = nextToken;
|
||||||
|
pendingVisibleGraphRefreshForce = false;
|
||||||
|
|
||||||
|
if (pendingVisibleGraphRefreshTimer) {
|
||||||
|
clearTimeout(pendingVisibleGraphRefreshTimer);
|
||||||
|
pendingVisibleGraphRefreshTimer = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (delay <= 0) {
|
||||||
|
return _flushScheduledVisibleGraphRefresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
pendingVisibleGraphRefreshTimer = setTimeout(() => {
|
||||||
|
_flushScheduledVisibleGraphRefresh();
|
||||||
|
}, delay);
|
||||||
|
|
||||||
|
return {
|
||||||
|
scheduled: true,
|
||||||
|
reason: "throttled",
|
||||||
|
token: nextToken,
|
||||||
|
delay,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 初始化面板(由 index.js 调用一次)
|
* 初始化面板(由 index.js 调用一次)
|
||||||
*/
|
*/
|
||||||
@@ -981,7 +1128,6 @@ export function openPanel() {
|
|||||||
panelEl?.querySelector(".bme-tab-btn.active")?.dataset.tab || currentTabId;
|
panelEl?.querySelector(".bme-tab-btn.active")?.dataset.tab || currentTabId;
|
||||||
_switchTab(activeTabId);
|
_switchTab(activeTabId);
|
||||||
_refreshRuntimeStatus();
|
_refreshRuntimeStatus();
|
||||||
_refreshGraph();
|
|
||||||
_buildLegend();
|
_buildLegend();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -991,6 +1137,8 @@ export function openPanel() {
|
|||||||
export function closePanel() {
|
export function closePanel() {
|
||||||
if (!overlayEl) return;
|
if (!overlayEl) return;
|
||||||
overlayEl.classList.remove("active");
|
overlayEl.classList.remove("active");
|
||||||
|
_clearScheduledVisibleGraphRefresh();
|
||||||
|
lastVisibleGraphRefreshToken = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1032,7 +1180,7 @@ export function refreshLiveState() {
|
|||||||
_refreshMessageTraceWorkspace();
|
_refreshMessageTraceWorkspace();
|
||||||
}
|
}
|
||||||
|
|
||||||
_refreshGraph();
|
_scheduleVisibleGraphWorkspaceRefresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==================== Tab 切换 ====================
|
// ==================== Tab 切换 ====================
|
||||||
@@ -1047,6 +1195,7 @@ function _bindTabs() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function _switchTab(tabId) {
|
function _switchTab(tabId) {
|
||||||
|
const previousVisibleGraphMode = _getVisibleGraphWorkspaceMode();
|
||||||
let next = tabId || "dashboard";
|
let next = tabId || "dashboard";
|
||||||
// 「图谱」仅移动端底部 Tab 可用;桌面端图谱在右侧主工作区,侧栏不设该 Tab
|
// 「图谱」仅移动端底部 Tab 可用;桌面端图谱在右侧主工作区,侧栏不设该 Tab
|
||||||
if (!_isMobile() && next === "graph") {
|
if (!_isMobile() && next === "graph") {
|
||||||
@@ -1078,11 +1227,17 @@ function _switchTab(tabId) {
|
|||||||
_refreshConfigTab();
|
_refreshConfigTab();
|
||||||
break;
|
break;
|
||||||
case "graph":
|
case "graph":
|
||||||
_refreshMobileGraphTab();
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const nextVisibleGraphMode = _getVisibleGraphWorkspaceMode();
|
||||||
|
if (nextVisibleGraphMode !== previousVisibleGraphMode) {
|
||||||
|
_scheduleVisibleGraphWorkspaceRefresh({ force: true });
|
||||||
|
} else {
|
||||||
|
_scheduleVisibleGraphWorkspaceRefresh();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function _getPlannerApi() {
|
function _getPlannerApi() {
|
||||||
@@ -1161,8 +1316,7 @@ function _switchGraphView(view) {
|
|||||||
if (cogWorkspace) cogWorkspace.style.display = isCognition ? "" : "none";
|
if (cogWorkspace) cogWorkspace.style.display = isCognition ? "" : "none";
|
||||||
if (summaryWorkspace) summaryWorkspace.style.display = isSummary ? "" : "none";
|
if (summaryWorkspace) summaryWorkspace.style.display = isSummary ? "" : "none";
|
||||||
|
|
||||||
if (isCognition) _refreshCognitionWorkspace();
|
_refreshGraph({ force: true });
|
||||||
if (isSummary) _refreshSummaryWorkspace();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==================== 移动端图谱 Tab ====================
|
// ==================== 移动端图谱 Tab ====================
|
||||||
@@ -1187,14 +1341,7 @@ function _switchMobileGraphSubView(view) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function _refreshMobileGraphTab() {
|
function _refreshMobileGraphTab() {
|
||||||
if (currentMobileGraphView === "graph") {
|
_refreshGraph({ force: true });
|
||||||
_refreshGraph();
|
|
||||||
_buildMobileLegend();
|
|
||||||
} else if (currentMobileGraphView === "cognition") {
|
|
||||||
_refreshMobileCognitionFull();
|
|
||||||
} else if (currentMobileGraphView === "summary") {
|
|
||||||
_refreshMobileSummaryFull();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function _buildMobileLegend() {
|
function _buildMobileLegend() {
|
||||||
@@ -2990,20 +3137,8 @@ function _hostUserPovAliasHintsForGraph() {
|
|||||||
return getHostUserAliasHints();
|
return getHostUserAliasHints();
|
||||||
}
|
}
|
||||||
|
|
||||||
function _refreshGraph() {
|
function _refreshGraph(options = {}) {
|
||||||
const graph = _getGraph?.();
|
return _refreshVisibleGraphWorkspace({ force: options.force !== false });
|
||||||
if (!graph) return;
|
|
||||||
const hints = { userPovAliases: _hostUserPovAliasHintsForGraph() };
|
|
||||||
graphRenderer?.loadGraph(graph, hints);
|
|
||||||
mobileGraphRenderer?.loadGraph(graph, hints);
|
|
||||||
if (currentGraphView === "cognition") {
|
|
||||||
_refreshCognitionWorkspace();
|
|
||||||
} else if (currentGraphView === "summary") {
|
|
||||||
_refreshSummaryWorkspace();
|
|
||||||
}
|
|
||||||
if (currentTabId === "graph") {
|
|
||||||
_refreshMobileGraphTab();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function _buildLegend() {
|
function _buildLegend() {
|
||||||
@@ -9591,6 +9726,7 @@ function _setText(id, text) {
|
|||||||
|
|
||||||
function _getGraphPersistenceSnapshot() {
|
function _getGraphPersistenceSnapshot() {
|
||||||
return _getGraphPersistenceState?.() || {
|
return _getGraphPersistenceState?.() || {
|
||||||
|
revision: 0,
|
||||||
loadState: "no-chat",
|
loadState: "no-chat",
|
||||||
reason: "",
|
reason: "",
|
||||||
writesBlocked: true,
|
writesBlocked: true,
|
||||||
|
|||||||
Reference in New Issue
Block a user