perf(renderer): 整体优化响应速度 — rAF 合并编辑器刷新/自动保存缓存/粒子引擎空闲自停
同时: 不透明窗口 + 精简主题(8到2)、TabBar 简化、图谱宽松布局、MoreActions 层级修复
This commit is contained in:
@@ -299,22 +299,15 @@ test('Graph: 控件+模式切换可用', async () => {
|
||||
await a.app.close();
|
||||
});
|
||||
|
||||
// === TabBar pin/close ===
|
||||
test('TabBar: 固定+关闭可用', async () => {
|
||||
// === TabBar close ===
|
||||
test('TabBar: 关闭标签可用(pin 点已移除)', async () => {
|
||||
const a = await launch(nodePath.join(os.tmpdir(), 'hn-tab-' + Date.now()));
|
||||
const { v } = await setupVault(a, [{ name: 'Tab1', body: 't1' }, { name: 'Tab2', body: 't2' }]);
|
||||
await a.page.getByTestId('filetree').getByText('Tab1').click();
|
||||
await a.page.waitForTimeout(300);
|
||||
await a.page.getByTestId('filetree').getByText('Tab2').click();
|
||||
await a.page.waitForTimeout(300);
|
||||
// 固定 Tab1(pin 按钮是 span[title="固定"]●)
|
||||
const tab1 = a.page.getByTestId('tabbar').locator('div').filter({ hasText: 'Tab1' }).first();
|
||||
await tab1.locator('span[title="固定"]').click();
|
||||
await a.page.waitForTimeout(300);
|
||||
// 取消固定
|
||||
await tab1.locator('span[title="取消固定"]').click();
|
||||
await a.page.waitForTimeout(300);
|
||||
// 关闭 Tab2(close 按钮是 span 文本 x)
|
||||
// 关闭 Tab2(close 按钮是 span 文本 x;pin 点按钮已按 UI 需求移除)
|
||||
const tab2 = a.page.getByTestId('tabbar').locator('div').filter({ hasText: 'Tab2' }).first();
|
||||
await tab2.locator('span').filter({ hasText: 'x' }).click();
|
||||
await a.page.waitForTimeout(300);
|
||||
@@ -354,4 +347,4 @@ test('OutlinePanel: 切换文档后大纲自动更新', async () => {
|
||||
await expect(a.page.locator('.outline-item', { hasText: 'Title B' })).toBeVisible({ timeout: 5000 });
|
||||
await expect(a.page.locator('.outline-item', { hasText: 'Deep B' })).toBeVisible({ timeout: 5000 });
|
||||
await a.app.close();
|
||||
});
|
||||
});
|
||||
@@ -60,18 +60,19 @@ test('思维导图+知识图谱渲染验证(含可见性)', async () => {
|
||||
const rects = svg.querySelectorAll('rect').length;
|
||||
const texts = svg.querySelectorAll('text').length;
|
||||
const lines = svg.querySelectorAll('line').length;
|
||||
const linkPaths = svg.querySelectorAll('path').length;
|
||||
// Check a node card is visible within the svg
|
||||
const visibleCard = Array.from(svg.querySelectorAll('rect')).some((r) => {
|
||||
const b = r.getBoundingClientRect();
|
||||
return b.width > 0 && b.height > 0;
|
||||
});
|
||||
return { found: true, w: rect.width, h: rect.height, rects, texts, lines, visibleCard };
|
||||
return { found: true, w: rect.width, h: rect.height, rects, texts, lines, linkPaths, visibleCard };
|
||||
});
|
||||
console.log('Knowledge graph:', JSON.stringify(graph));
|
||||
expect(graph.found).toBe(true);
|
||||
expect(graph.h).toBeGreaterThan(100);
|
||||
expect(graph.rects).toBeGreaterThanOrEqual(5);
|
||||
expect(graph.lines).toBeGreaterThanOrEqual(1);
|
||||
expect(graph.rects).toBeGreaterThanOrEqual(3); // 2 卡 rect + 1 背景 rect(demo 卡片无左侧色条)
|
||||
expect(graph.linkPaths).toBeGreaterThanOrEqual(1); // 曲线连线为 path
|
||||
expect(graph.visibleCard).toBe(true);
|
||||
|
||||
await app.close();
|
||||
|
||||
@@ -38,7 +38,8 @@ test('知识图谱:卡片+连线(消费 IPC.graph)', async () => {
|
||||
await a.page.getByTitle('切换 编辑器/图谱').click();
|
||||
await a.page.getByRole('button', { name: '知识图谱' }).click();
|
||||
// 限定在知识图谱画布内统计卡片 rect(标题栏等 UI 图标也是 svg,不能全页统计)
|
||||
await expect(a.page.locator('[data-testid="graph-canvas"] rect')).toHaveCount(5, { timeout: 10000 });
|
||||
// 2 张卡片(2 卡 rect)+ 1 背景 rect = 3(demo 卡片无左侧色条)
|
||||
await expect(a.page.locator('[data-testid="graph-canvas"] rect')).toHaveCount(3, { timeout: 10000 });
|
||||
await a.app.close();
|
||||
});
|
||||
|
||||
|
||||
@@ -6,8 +6,8 @@ import os from 'node:os';
|
||||
|
||||
const MAIN_JS = nodePath.join(process.cwd(), 'dist-electron/main/index.js');
|
||||
|
||||
// 透明主题真透明:bgPrimary=transparent 时根背景必须是 alpha=0(配合主进程 transparent:true + backgroundColor:#00000000 + backgroundMaterial:'none' 即可透出下层软件)
|
||||
test('透明主题:根背景 alpha=0(真透明,可见下层软件)', async () => {
|
||||
// UI 重新设计:窗口不透明(transparent:false + backgroundColor 空间底色),根背景应为不透明的 L0 空间色
|
||||
test('窗口不透明:根背景为 L0 空间底色(alpha=1,非透明)', async () => {
|
||||
const tmp = await fs.mkdtemp(nodePath.join(os.tmpdir(), 'hn-tr-'));
|
||||
const ud = nodePath.join(tmp, 'ud'); const v = nodePath.join(tmp, 'v');
|
||||
await fs.mkdir(ud, { recursive: true }); await fs.mkdir(v, { recursive: true });
|
||||
@@ -15,15 +15,7 @@ test('透明主题:根背景 alpha=0(真透明,可见下层软件)', asy
|
||||
const page = await app.firstWindow();
|
||||
await page.waitForLoadState('domcontentloaded');
|
||||
await page.evaluate(({ root }) => (globalThis as any).dsh.invoke('vault:switch', { root }), { root: v });
|
||||
// 应用透明主题的 CSS 变量(bgPrimary='transparent'),并移除背景图遮罩
|
||||
await page.evaluate(() => {
|
||||
const el = document.documentElement;
|
||||
el.style.setProperty('--bg-primary', 'transparent');
|
||||
el.style.setProperty('--bg-secondary', 'rgba(20,20,28,0.5)');
|
||||
el.style.setProperty('--text-primary', '#ddd');
|
||||
document.querySelectorAll('div[style*="background-image"]').forEach((n: any) => n.remove());
|
||||
});
|
||||
await page.waitForTimeout(400);
|
||||
await page.waitForTimeout(500);
|
||||
const rootBg = await page.evaluate(() => {
|
||||
const root = document.querySelector('#root > div') as HTMLElement;
|
||||
if (!root) return null;
|
||||
@@ -31,7 +23,15 @@ test('透明主题:根背景 alpha=0(真透明,可见下层软件)', asy
|
||||
});
|
||||
console.log('ROOT_BG', rootBg);
|
||||
expect(rootBg).not.toBeNull();
|
||||
// 透明背景应为 alpha=0(rgba(0,0,0,0) 或 transparent)
|
||||
expect(rootBg).toMatch(/rgba\(0, 0, 0, 0\)|transparent/i);
|
||||
// 窗口不透明:根背景为不透明空间底色(alpha=1,非 rgba(...,0) / transparent)
|
||||
const m = rootBg!.match(/rgba\(([\d.]+),\s*([\d.]+),\s*([\d.]+),\s*([\d.]+)\)|^rgb\(([\d.]+),\s*([\d.]+),\s*([\d.]+)\)$/);
|
||||
expect(m).not.toBeNull();
|
||||
// 不透明:要么是 rgb(...)(隐式 alpha=1),要么 rgba alpha=1
|
||||
if (rootBg!.startsWith('rgba')) {
|
||||
const alpha = parseFloat(m![4]);
|
||||
expect(alpha).toBe(1);
|
||||
} else {
|
||||
expect(rootBg!.startsWith('rgb(')).toBe(true);
|
||||
}
|
||||
await app.close();
|
||||
});
|
||||
Reference in New Issue
Block a user