mirror of
https://github.com/Syngnat/GoNavi.git
synced 2026-06-22 06:23:43 +08:00
✨ feat(sidebar): 增强 v2 侧栏搜索持久筛选
- 新增 v2 侧栏搜索模式配置,支持新版命令搜索和旧版侧栏筛选切换 - 命令搜索面板增加同步筛选开关和重置筛选按钮 - 侧栏顶部支持展示并清空已同步筛选词 - 补充 appearance 持久化字段清洗和回归测试
This commit is contained in:
@@ -4197,6 +4197,23 @@ function App() {
|
||||
新版 UI 仍在 Beta,部分屏幕样式可能与旧版有差异,遇到问题可随时切回。
|
||||
</div>
|
||||
)}
|
||||
{appearance.uiVersion === 'v2' && (
|
||||
<div style={{ marginTop: 14 }}>
|
||||
<div style={{ marginBottom: 8, fontWeight: 500 }}>新版左侧搜索模式</div>
|
||||
<Segmented
|
||||
block
|
||||
options={[
|
||||
{ label: '新版命令搜索', value: 'command' },
|
||||
{ label: '旧版侧栏筛选', value: 'filter' },
|
||||
]}
|
||||
value={appearance.v2SidebarSearchMode ?? 'command'}
|
||||
onChange={(value) => setAppearance({ v2SidebarSearchMode: value as 'command' | 'filter' })}
|
||||
/>
|
||||
<div style={{ ...utilityMutedTextStyle, marginTop: 8 }}>
|
||||
新版命令搜索适合跳转连接、表和动作,可在面板中开启同步开关持续过滤左侧树;旧版侧栏筛选会直接显示输入框并持久保留筛选内容。
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div style={utilityPanelStyle}>
|
||||
<div style={{ marginBottom: 10, fontWeight: 600 }}>主题模式</div>
|
||||
|
||||
@@ -30,6 +30,9 @@ describe('UI version switch placement', () => {
|
||||
expect(appSource).toContain("onClick={() => setAppearance({ uiVersion: item.key as 'legacy' | 'v2' })}");
|
||||
expect(appSource).toContain('新版 UI 仍在 Beta');
|
||||
expect(appSource).toContain('Windows、macOS 与 Linux 均可切换');
|
||||
expect(appSource).toContain('新版左侧搜索模式');
|
||||
expect(appSource).toContain("value={appearance.v2SidebarSearchMode ?? 'command'}");
|
||||
expect(appSource).toContain("setAppearance({ v2SidebarSearchMode: value as 'command' | 'filter' })");
|
||||
});
|
||||
|
||||
it('uses the card-style v2 switch from the redesign instead of the segmented pill', () => {
|
||||
@@ -42,6 +45,7 @@ describe('UI version switch placement', () => {
|
||||
expect(uiVersionBlock).toContain("label: '旧版 UI'");
|
||||
expect(uiVersionBlock).toContain("label: '新版 UI'");
|
||||
expect(uiVersionBlock).toContain('CheckOutlined');
|
||||
expect(uiVersionBlock).not.toContain('<Segmented');
|
||||
expect(uiVersionBlock).toContain('新版左侧搜索模式');
|
||||
expect(uiVersionBlock).toContain('<Segmented');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -439,7 +439,10 @@ describe('Sidebar locate toolbar', () => {
|
||||
expect(markup).toContain('gn-v2-object-explorer');
|
||||
expect(markup).toContain('gn-v2-active-connection-header');
|
||||
expect(markup).toContain('gn-v2-explorer-search');
|
||||
expect(markup).toContain('data-v2-sidebar-search-mode="command"');
|
||||
expect(markup).toContain('gn-v2-explorer-command-trigger');
|
||||
expect(markup).toContain('gn-v2-explorer-filter-action');
|
||||
expect(markup).toContain('重置侧栏筛选');
|
||||
expect(markup).toContain('搜索表、连接、动作... 或问 AI');
|
||||
expect(markup).toContain('gn-v2-search-shortcut');
|
||||
expect(markup).toContain('<kbd>⌘</kbd>');
|
||||
@@ -453,6 +456,11 @@ describe('Sidebar locate toolbar', () => {
|
||||
expect(markup).toContain('函数');
|
||||
expect(markup).toContain('aria-pressed="true"');
|
||||
expect(source).toContain("const [v2ExplorerFilter, setV2ExplorerFilter] = useState<V2ExplorerFilter>('all');");
|
||||
expect(source).toContain("const v2SidebarSearchMode = appearance.v2SidebarSearchMode ?? 'command';");
|
||||
expect(source).toContain('const v2CommandSearchPersistentFilterEnabled = appearance.v2CommandSearchPersistentFilterEnabled === true;');
|
||||
expect(source).toContain('handleV2CommandSearchValueChange(event.target.value)');
|
||||
expect(source).toContain('toggleV2CommandSearchPersistentFilter');
|
||||
expect(source).toContain('gn-v2-command-filter-switch');
|
||||
expect(source).toContain('onClick={() => setV2ExplorerFilter(item.key)}');
|
||||
expect(source).toContain('treeData={isV2Ui ? v2VisibleTreeData : displayTreeData}');
|
||||
expect(markup).toContain('gn-v2-sidebar-log-footer');
|
||||
@@ -496,6 +504,18 @@ describe('Sidebar locate toolbar', () => {
|
||||
expect(contextMenuFunction).not.toContain('setActiveContext');
|
||||
});
|
||||
|
||||
it('can render the v2 sidebar with legacy persistent filter input', () => {
|
||||
mocks.state.appearance.v2SidebarSearchMode = 'filter';
|
||||
mocks.state.appearance.v2SidebarPersistedFilter = 'fs_org';
|
||||
|
||||
const markup = renderToStaticMarkup(<Sidebar uiVersion="v2" />);
|
||||
|
||||
expect(markup).toContain('data-v2-sidebar-search-mode="filter"');
|
||||
expect(markup).toContain('筛选左侧表、连接、对象...');
|
||||
expect(markup).toContain('value="fs_org"');
|
||||
expect(markup).toContain('重置侧栏筛选');
|
||||
});
|
||||
|
||||
it('renders the v2 search shortcut from the user shortcut settings', () => {
|
||||
mocks.state.shortcutOptions = cloneShortcutOptions(DEFAULT_SHORTCUT_OPTIONS);
|
||||
mocks.state.shortcutOptions.focusSidebarSearch.mac = { combo: 'Meta+F', enabled: true };
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { useEffect, useState, useMemo, useRef, useCallback, useDeferredValue } from 'react';
|
||||
import { createPortal } from 'react-dom';
|
||||
import { Tree, message, Dropdown, MenuProps, Input, Button, Modal, Form, Badge, Checkbox, Space, Select, Popover, Tooltip, Progress } from 'antd';
|
||||
import { Tree, message, Dropdown, MenuProps, Input, Button, Modal, Form, Badge, Checkbox, Space, Select, Popover, Tooltip, Progress, Switch } from 'antd';
|
||||
import {
|
||||
DatabaseOutlined,
|
||||
TableOutlined,
|
||||
@@ -954,6 +954,7 @@ const Sidebar: React.FC<{
|
||||
const addSqlLog = useStore(state => state.addSqlLog);
|
||||
const sqlLogs = useStore(state => state.sqlLogs) || [];
|
||||
const shortcutOptions = useStore(state => state.shortcutOptions);
|
||||
const setAppearance = useStore(state => state.setAppearance);
|
||||
const setAIPanelVisible = useStore(state => state.setAIPanelVisible);
|
||||
const addAIContext = useStore(state => state.addAIContext);
|
||||
const darkMode = theme === 'dark';
|
||||
@@ -966,6 +967,7 @@ const Sidebar: React.FC<{
|
||||
const focusSidebarSearchShortcutTokens = focusSidebarSearchShortcut === '-'
|
||||
? []
|
||||
: focusSidebarSearchShortcut.match(/Ctrl|Alt|Shift|Esc|Space|[⌘⌃⌥⇧↵↑↓←→]|[^+]/g) ?? [];
|
||||
const isV2Ui = (uiVersion ?? appearance.uiVersion) === 'v2';
|
||||
const [treeData, setTreeData] = useState<TreeNode[]>([]);
|
||||
const activeTab = useMemo(() => tabs.find(tab => tab.id === activeTabId) || null, [tabs, activeTabId]);
|
||||
const activeTabLocateRequest = useMemo(() => normalizeSidebarLocateObjectRequestFromTab(activeTab), [activeTab]);
|
||||
@@ -1021,7 +1023,11 @@ const Sidebar: React.FC<{
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
const [searchValue, setSearchValue] = useState('');
|
||||
const v2SidebarSearchMode = appearance.v2SidebarSearchMode ?? 'command';
|
||||
const v2UseLegacySidebarFilter = isV2Ui && v2SidebarSearchMode === 'filter';
|
||||
const v2CommandSearchPersistentFilterEnabled = appearance.v2CommandSearchPersistentFilterEnabled === true;
|
||||
const v2PersistedSidebarFilter = appearance.v2SidebarPersistedFilter ?? '';
|
||||
const [searchValue, setSearchValue] = useState(v2PersistedSidebarFilter);
|
||||
const deferredSearchValue = useDeferredValue(searchValue);
|
||||
const [searchScopes, setSearchScopes] = useState<SearchScope[]>(['smart']);
|
||||
const [v2ExplorerFilter, setV2ExplorerFilter] = useState<V2ExplorerFilter>('all');
|
||||
@@ -1093,6 +1099,49 @@ const Sidebar: React.FC<{
|
||||
setV2CommandSearchValue('');
|
||||
setV2CommandActiveIndex(0);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
setSearchValue(v2PersistedSidebarFilter);
|
||||
}, [v2PersistedSidebarFilter]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!v2UseLegacySidebarFilter) {
|
||||
return;
|
||||
}
|
||||
const nextFilter = searchValue.trim();
|
||||
if (nextFilter !== v2PersistedSidebarFilter) {
|
||||
setAppearance({ v2SidebarPersistedFilter: nextFilter });
|
||||
}
|
||||
}, [searchValue, setAppearance, v2PersistedSidebarFilter, v2UseLegacySidebarFilter]);
|
||||
|
||||
const handleV2CommandSearchValueChange = useCallback((value: string) => {
|
||||
setV2CommandSearchValue(value);
|
||||
if (!v2CommandSearchPersistentFilterEnabled) {
|
||||
return;
|
||||
}
|
||||
const nextFilter = value.trim();
|
||||
setSearchValue(nextFilter);
|
||||
setAppearance({ v2SidebarPersistedFilter: nextFilter });
|
||||
}, [setAppearance, v2CommandSearchPersistentFilterEnabled]);
|
||||
|
||||
const toggleV2CommandSearchPersistentFilter = useCallback((enabled: boolean) => {
|
||||
const nextFilter = enabled ? v2CommandSearchValue.trim() : '';
|
||||
setSearchValue(nextFilter);
|
||||
setAppearance({
|
||||
v2CommandSearchPersistentFilterEnabled: enabled,
|
||||
v2SidebarPersistedFilter: nextFilter,
|
||||
});
|
||||
message.success(enabled ? '已开启左侧筛选同步' : '已关闭左侧筛选同步');
|
||||
}, [setAppearance, v2CommandSearchValue]);
|
||||
|
||||
const resetV2SidebarFilter = useCallback(() => {
|
||||
setSearchValue('');
|
||||
setAppearance({
|
||||
v2CommandSearchPersistentFilterEnabled: false,
|
||||
v2SidebarPersistedFilter: '',
|
||||
});
|
||||
message.success('已重置侧栏筛选');
|
||||
}, [setAppearance]);
|
||||
|
||||
// Virtual Scroll State
|
||||
const [treeHeight, setTreeHeight] = useState(500);
|
||||
@@ -1121,7 +1170,7 @@ const Sidebar: React.FC<{
|
||||
|
||||
useEffect(() => {
|
||||
const handleFocusSidebarSearch = () => {
|
||||
if ((uiVersion ?? appearance.uiVersion) === 'v2') {
|
||||
if (isV2Ui && !v2UseLegacySidebarFilter) {
|
||||
openV2CommandSearch();
|
||||
return;
|
||||
}
|
||||
@@ -1136,7 +1185,7 @@ const Sidebar: React.FC<{
|
||||
return () => {
|
||||
window.removeEventListener('gonavi:focus-sidebar-search', handleFocusSidebarSearch as EventListener);
|
||||
};
|
||||
}, [appearance.uiVersion, openV2CommandSearch, uiVersion]);
|
||||
}, [isV2Ui, openV2CommandSearch, v2UseLegacySidebarFilter]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isV2CommandSearchOpen) return;
|
||||
@@ -3110,8 +3159,6 @@ const Sidebar: React.FC<{
|
||||
});
|
||||
};
|
||||
|
||||
const isV2Ui = (uiVersion ?? appearance.uiVersion) === 'v2';
|
||||
|
||||
const onSelect = (keys: React.Key[], info: any) => {
|
||||
if (isV2Ui && info?.node?.type === 'v2-table-section') {
|
||||
return;
|
||||
@@ -6792,15 +6839,15 @@ const Sidebar: React.FC<{
|
||||
setV2CommandActiveIndex((prev) => Math.max(prev - 1, 0));
|
||||
return;
|
||||
}
|
||||
if (event.key === 'Enter') {
|
||||
event.preventDefault();
|
||||
if (v2CommandSearchAiMode && !v2CommandSearchQuery.aiPrompt) {
|
||||
message.warning('请输入要问 AI 的问题');
|
||||
return;
|
||||
}
|
||||
runCommandSearchItem(commandSearchFlatItems[v2CommandActiveIndex]);
|
||||
return;
|
||||
}
|
||||
if (event.key === 'Enter') {
|
||||
event.preventDefault();
|
||||
if (v2CommandSearchAiMode && !v2CommandSearchQuery.aiPrompt) {
|
||||
message.warning('请输入要问 AI 的问题');
|
||||
return;
|
||||
}
|
||||
runCommandSearchItem(commandSearchFlatItems[v2CommandActiveIndex]);
|
||||
return;
|
||||
}
|
||||
if (event.key === 'Escape') {
|
||||
event.preventDefault();
|
||||
closeV2CommandSearch();
|
||||
@@ -6855,10 +6902,29 @@ const Sidebar: React.FC<{
|
||||
ref={commandSearchInputRef}
|
||||
variant="borderless"
|
||||
value={v2CommandSearchValue}
|
||||
onChange={(event) => setV2CommandSearchValue(event.target.value)}
|
||||
onChange={(event) => handleV2CommandSearchValueChange(event.target.value)}
|
||||
onKeyDown={handleV2CommandSearchKeyDown}
|
||||
placeholder="搜索表、连接、动作... 或问 AI"
|
||||
/>
|
||||
<Tooltip title="同步输入内容到左侧筛选">
|
||||
<span className="gn-v2-command-filter-switch" aria-label="同步到左侧筛选">
|
||||
<Switch
|
||||
size="small"
|
||||
checked={v2CommandSearchPersistentFilterEnabled}
|
||||
onChange={toggleV2CommandSearchPersistentFilter}
|
||||
/>
|
||||
</span>
|
||||
</Tooltip>
|
||||
<Tooltip title={v2PersistedSidebarFilter ? '重置侧栏筛选' : '没有已同步的侧栏筛选'}>
|
||||
<Button
|
||||
size="small"
|
||||
type="text"
|
||||
icon={<ReloadOutlined />}
|
||||
aria-label="重置侧栏筛选"
|
||||
disabled={!v2PersistedSidebarFilter}
|
||||
onClick={resetV2SidebarFilter}
|
||||
/>
|
||||
</Tooltip>
|
||||
<kbd>esc</kbd>
|
||||
</div>
|
||||
<div className="gn-v2-command-list">
|
||||
@@ -8489,26 +8555,62 @@ const Sidebar: React.FC<{
|
||||
</div>
|
||||
)}
|
||||
<div className={isV2Ui ? 'gn-v2-explorer-search' : undefined} style={{ padding: '8px 14px', borderBottom: `1px solid ${darkMode ? 'rgba(255,255,255,0.06)' : 'rgba(0,0,0,0.04)'}` }}>
|
||||
{isV2Ui ? (
|
||||
<button
|
||||
type="button"
|
||||
className="gn-v2-explorer-command-trigger"
|
||||
onClick={() => {
|
||||
openV2CommandSearch();
|
||||
onFocusCommandSearch?.();
|
||||
}}
|
||||
aria-label="搜索表、连接、动作"
|
||||
>
|
||||
<SearchOutlined />
|
||||
<span>搜索表、连接、动作... 或问 AI</span>
|
||||
{focusSidebarSearchShortcutTokens.length > 0 ? (
|
||||
<span className="gn-v2-search-shortcut" aria-hidden="true">
|
||||
{focusSidebarSearchShortcutTokens.map((token, index) => (
|
||||
<kbd key={`${token}-${index}`}>{token}</kbd>
|
||||
))}
|
||||
</span>
|
||||
) : null}
|
||||
</button>
|
||||
{isV2Ui && !v2UseLegacySidebarFilter ? (
|
||||
<div className="gn-v2-explorer-command-row" data-v2-sidebar-search-mode="command">
|
||||
<button
|
||||
type="button"
|
||||
className="gn-v2-explorer-command-trigger"
|
||||
onClick={() => {
|
||||
openV2CommandSearch();
|
||||
onFocusCommandSearch?.();
|
||||
}}
|
||||
aria-label="搜索表、连接、动作"
|
||||
>
|
||||
<SearchOutlined />
|
||||
<span>{v2PersistedSidebarFilter || '搜索表、连接、动作... 或问 AI'}</span>
|
||||
{focusSidebarSearchShortcutTokens.length > 0 ? (
|
||||
<span className="gn-v2-search-shortcut" aria-hidden="true">
|
||||
{focusSidebarSearchShortcutTokens.map((token, index) => (
|
||||
<kbd key={`${token}-${index}`}>{token}</kbd>
|
||||
))}
|
||||
</span>
|
||||
) : null}
|
||||
</button>
|
||||
<Tooltip title={v2PersistedSidebarFilter ? '重置侧栏筛选' : '没有已同步的侧栏筛选'}>
|
||||
<button
|
||||
type="button"
|
||||
className="gn-v2-explorer-filter-action"
|
||||
aria-label="重置侧栏筛选"
|
||||
disabled={!v2PersistedSidebarFilter}
|
||||
onClick={resetV2SidebarFilter}
|
||||
>
|
||||
<ReloadOutlined />
|
||||
</button>
|
||||
</Tooltip>
|
||||
</div>
|
||||
) : isV2Ui ? (
|
||||
<div className="gn-v2-explorer-legacy-filter-row" data-v2-sidebar-search-mode="filter">
|
||||
<Input
|
||||
{...noAutoCapInputProps}
|
||||
ref={searchInputRef}
|
||||
value={searchValue}
|
||||
placeholder="筛选左侧表、连接、对象..."
|
||||
onChange={onSearch}
|
||||
size="small"
|
||||
prefix={<SearchOutlined />}
|
||||
/>
|
||||
<Tooltip title={searchValue ? '重置侧栏筛选' : '没有筛选内容'}>
|
||||
<button
|
||||
type="button"
|
||||
className="gn-v2-explorer-filter-action"
|
||||
aria-label="重置侧栏筛选"
|
||||
disabled={!searchValue}
|
||||
onClick={resetV2SidebarFilter}
|
||||
>
|
||||
<ReloadOutlined />
|
||||
</button>
|
||||
</Tooltip>
|
||||
</div>
|
||||
) : (
|
||||
<Input
|
||||
{...noAutoCapInputProps}
|
||||
|
||||
@@ -69,6 +69,9 @@ describe('store appearance persistence', () => {
|
||||
expect(appearance.opacity).toBe(0.75);
|
||||
expect(appearance.blur).toBe(6);
|
||||
expect(appearance.useNativeMacWindowControls).toBe(true);
|
||||
expect(appearance.v2SidebarSearchMode).toBe('command');
|
||||
expect(appearance.v2CommandSearchPersistentFilterEnabled).toBe(false);
|
||||
expect(appearance.v2SidebarPersistedFilter).toBe('');
|
||||
expect(appearance.showDataTableVerticalBorders).toBe(false);
|
||||
expect(appearance.dataTableDensity).toBe('comfortable');
|
||||
expect(appearance.dataTableFontSize).toBeNull();
|
||||
@@ -124,6 +127,30 @@ describe('store appearance persistence', () => {
|
||||
expect(appearance.customMonoFontFamily).toBeNull();
|
||||
});
|
||||
|
||||
it('persists v2 sidebar search preferences and sanitizes filter text', async () => {
|
||||
const { useStore } = await importStore();
|
||||
|
||||
useStore.getState().setAppearance({
|
||||
v2SidebarSearchMode: 'filter',
|
||||
v2CommandSearchPersistentFilterEnabled: true,
|
||||
v2SidebarPersistedFilter: ` ${'orders'.repeat(40)} `,
|
||||
});
|
||||
|
||||
const persisted = JSON.parse(storage.getItem('lite-db-storage') || '{}');
|
||||
expect(persisted.state.appearance.v2SidebarSearchMode).toBe('filter');
|
||||
expect(persisted.state.appearance.v2CommandSearchPersistentFilterEnabled).toBe(true);
|
||||
expect(persisted.state.appearance.v2SidebarPersistedFilter).toHaveLength(120);
|
||||
expect(persisted.state.appearance.v2SidebarPersistedFilter.startsWith('orders')).toBe(true);
|
||||
|
||||
vi.resetModules();
|
||||
const reloaded = await importStore();
|
||||
const appearance = reloaded.useStore.getState().appearance;
|
||||
|
||||
expect(appearance.v2SidebarSearchMode).toBe('filter');
|
||||
expect(appearance.v2CommandSearchPersistentFilterEnabled).toBe(true);
|
||||
expect(appearance.v2SidebarPersistedFilter).toHaveLength(120);
|
||||
});
|
||||
|
||||
it('persists tab display appearance settings and sanitizes invalid elements', async () => {
|
||||
const { useStore } = await importStore();
|
||||
|
||||
|
||||
@@ -59,6 +59,9 @@ export interface AppearanceSettings extends DataGridDisplaySettings {
|
||||
opacity: number;
|
||||
blur: number;
|
||||
useNativeMacWindowControls: boolean;
|
||||
v2SidebarSearchMode: "command" | "filter";
|
||||
v2CommandSearchPersistentFilterEnabled: boolean;
|
||||
v2SidebarPersistedFilter: string;
|
||||
customUIFontFamily: string | null;
|
||||
customMonoFontFamily: string | null;
|
||||
tabDisplay: TabDisplaySettings;
|
||||
@@ -70,6 +73,9 @@ export const DEFAULT_APPEARANCE: AppearanceSettings = {
|
||||
opacity: 1.0,
|
||||
blur: 0,
|
||||
useNativeMacWindowControls: false,
|
||||
v2SidebarSearchMode: "command",
|
||||
v2CommandSearchPersistentFilterEnabled: false,
|
||||
v2SidebarPersistedFilter: "",
|
||||
customUIFontFamily: null,
|
||||
customMonoFontFamily: null,
|
||||
tabDisplay: DEFAULT_TAB_DISPLAY_SETTINGS,
|
||||
@@ -84,6 +90,20 @@ const MAX_FONT_SIZE = 20;
|
||||
const DEFAULT_STARTUP_FULLSCREEN = false;
|
||||
const LEGACY_DEFAULT_OPACITY = 0.95;
|
||||
const OPACITY_EPSILON = 1e-6;
|
||||
const MAX_SIDEBAR_PERSISTED_FILTER_LENGTH = 120;
|
||||
|
||||
const sanitizeV2SidebarSearchMode = (
|
||||
value: unknown,
|
||||
): AppearanceSettings["v2SidebarSearchMode"] => {
|
||||
return value === "filter" ? "filter" : DEFAULT_APPEARANCE.v2SidebarSearchMode;
|
||||
};
|
||||
|
||||
const sanitizeV2SidebarPersistedFilter = (value: unknown): string => {
|
||||
if (typeof value !== "string") {
|
||||
return DEFAULT_APPEARANCE.v2SidebarPersistedFilter;
|
||||
}
|
||||
return value.trim().slice(0, MAX_SIDEBAR_PERSISTED_FILTER_LENGTH);
|
||||
};
|
||||
const MAX_URI_LENGTH = 4096;
|
||||
const MAX_HOST_ENTRY_LENGTH = 512;
|
||||
const MAX_HOST_ENTRIES = 64;
|
||||
@@ -1637,6 +1657,16 @@ const sanitizeAppearance = (
|
||||
typeof appearance.useNativeMacWindowControls === "boolean"
|
||||
? appearance.useNativeMacWindowControls
|
||||
: DEFAULT_APPEARANCE.useNativeMacWindowControls,
|
||||
v2SidebarSearchMode: sanitizeV2SidebarSearchMode(
|
||||
appearance.v2SidebarSearchMode,
|
||||
),
|
||||
v2CommandSearchPersistentFilterEnabled:
|
||||
typeof appearance.v2CommandSearchPersistentFilterEnabled === "boolean"
|
||||
? appearance.v2CommandSearchPersistentFilterEnabled
|
||||
: DEFAULT_APPEARANCE.v2CommandSearchPersistentFilterEnabled,
|
||||
v2SidebarPersistedFilter: sanitizeV2SidebarPersistedFilter(
|
||||
appearance.v2SidebarPersistedFilter,
|
||||
),
|
||||
customUIFontFamily: sanitizeFontFamilyInput(appearance.customUIFontFamily),
|
||||
customMonoFontFamily: sanitizeFontFamilyInput(appearance.customMonoFontFamily),
|
||||
tabDisplay: sanitizeTabDisplaySettings(appearance.tabDisplay),
|
||||
|
||||
@@ -1831,8 +1831,22 @@ body[data-ui-version="v2"] .gn-v2-explorer-search {
|
||||
border-bottom: none !important;
|
||||
}
|
||||
|
||||
body[data-ui-version="v2"] .gn-v2-explorer-command-row,
|
||||
body[data-ui-version="v2"] .gn-v2-explorer-legacy-filter-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
body[data-ui-version="v2"] .gn-v2-explorer-legacy-filter-row .ant-input-affix-wrapper {
|
||||
flex: 1 1 auto;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
body[data-ui-version="v2"] .gn-v2-explorer-command-trigger {
|
||||
width: 100%;
|
||||
flex: 1 1 auto;
|
||||
min-width: 0;
|
||||
height: 30px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -1862,6 +1876,31 @@ body[data-ui-version="v2"] .gn-v2-explorer-command-trigger > span:nth-child(2) {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
body[data-ui-version="v2"] .gn-v2-explorer-filter-action {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
flex: 0 0 30px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: 0.5px solid var(--gn-br-2);
|
||||
border-radius: 7px;
|
||||
background: var(--gn-bg-input);
|
||||
color: var(--gn-fg-4);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
body[data-ui-version="v2"] .gn-v2-explorer-filter-action:hover:not(:disabled) {
|
||||
border-color: var(--gn-accent);
|
||||
background: var(--gn-bg-hover);
|
||||
color: var(--gn-fg-2);
|
||||
}
|
||||
|
||||
body[data-ui-version="v2"] .gn-v2-explorer-filter-action:disabled {
|
||||
opacity: 0.42;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
body[data-ui-version="v2"] .gn-v2-command-backdrop {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
@@ -1918,6 +1957,38 @@ body[data-ui-version="v2"] .gn-v2-command-searchbar > .anticon {
|
||||
color: var(--gn-fg-4);
|
||||
}
|
||||
|
||||
body[data-ui-version="v2"] .gn-v2-command-filter-switch {
|
||||
height: 30px;
|
||||
flex: 0 0 auto;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
body[data-ui-version="v2"] .gn-v2-command-searchbar .ant-switch {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
body[data-ui-version="v2"] .gn-v2-command-searchbar .ant-btn {
|
||||
width: 30px !important;
|
||||
height: 30px !important;
|
||||
flex: 0 0 30px;
|
||||
display: inline-flex !important;
|
||||
align-items: center !important;
|
||||
justify-content: center !important;
|
||||
border-radius: 8px !important;
|
||||
color: var(--gn-fg-4) !important;
|
||||
}
|
||||
|
||||
body[data-ui-version="v2"] .gn-v2-command-searchbar .ant-btn:hover:not(:disabled) {
|
||||
background: var(--gn-bg-hover) !important;
|
||||
color: var(--gn-fg-2) !important;
|
||||
}
|
||||
|
||||
body[data-ui-version="v2"] .gn-v2-command-searchbar .ant-btn:disabled {
|
||||
color: var(--gn-fg-5) !important;
|
||||
}
|
||||
|
||||
body[data-ui-version="v2"] .gn-v2-command-searchbar > kbd,
|
||||
body[data-ui-version="v2"] .gn-v2-command-footer kbd,
|
||||
body[data-ui-version="v2"] .gn-v2-command-row kbd {
|
||||
|
||||
Reference in New Issue
Block a user