diff --git a/wework/src-tauri/tauri.conf.json b/wework/src-tauri/tauri.conf.json index dfa33a78731..ca46bed73ca 100644 --- a/wework/src-tauri/tauri.conf.json +++ b/wework/src-tauri/tauri.conf.json @@ -37,9 +37,7 @@ "enable": true, "scope": { "requireLiteralLeadingDot": false, - "allow": [ - "**/*" - ] + "allow": ["**/*"] } } } @@ -55,13 +53,8 @@ "icons/icon.icns", "icons/icon.ico" ], - "externalBin": [ - "binaries/wegent-executor" - ], - "resources": [ - "binaries/codex/**/*", - "bundled-hooks/**/*" - ], + "externalBin": ["binaries/wegent-executor"], + "resources": ["binaries/codex/**/*", "bundled-hooks/**/*"], "android": { "debugApplicationIdSuffix": ".debug" } diff --git a/wework/src/components/chat/ChatInput.test.tsx b/wework/src/components/chat/ChatInput.test.tsx index 150deeeb198..d824311cc31 100644 --- a/wework/src/components/chat/ChatInput.test.tsx +++ b/wework/src/components/chat/ChatInput.test.tsx @@ -2274,7 +2274,7 @@ describe('ChatInput', () => { expect(menu.queryByText('计划模式')).not.toBeInTheDocument() }) - test('nests models by family while keeping controls from the selected GPT model', async () => { + test('lists models by family in the second-level menu while keeping selected controls', async () => { const gptModel: UnifiedModel = { name: 'overseas-gpt-5.5', type: 'user', @@ -2319,13 +2319,8 @@ describe('ChatInput', () => { await userEvent.click(screen.getByTestId('model-selector-button')) await userEvent.hover(screen.getByTestId('model-control-menu-model')) - expect(screen.getByTestId('model-family-claude')).toBeInTheDocument() - expect(screen.getByTestId('model-family-gpt')).toBeInTheDocument() - expect(screen.queryByTestId('model-option-claude-opus')).not.toBeInTheDocument() - - await userEvent.hover(screen.getByTestId('model-family-gpt')) + expect(screen.getByTestId('model-option-claude-opus')).toBeInTheDocument() expect(screen.getByTestId('model-option-overseas-gpt-5.5')).toBeInTheDocument() - expect(screen.queryByTestId('model-option-claude-opus')).not.toBeInTheDocument() await userEvent.hover(screen.getByTestId('model-control-menu-reasoning')) expect(screen.getByTestId('model-control-reasoning-high')).toBeInTheDocument() expect(screen.queryByTestId('model-control-reasoning-auto')).not.toBeInTheDocument() diff --git a/wework/src/components/chat/composer/ModelSelector.test.tsx b/wework/src/components/chat/composer/ModelSelector.test.tsx index ee43029c59c..ef2ccd96b85 100644 --- a/wework/src/components/chat/composer/ModelSelector.test.tsx +++ b/wework/src/components/chat/composer/ModelSelector.test.tsx @@ -172,7 +172,7 @@ describe('ModelSelector desktop layout', () => { expect(screen.queryByTestId('model-family-codex-official')).not.toBeInTheDocument() }) - test('shows family entries before model options when there are multiple families', async () => { + test('shows models from every family in the second-level menu', async () => { createShellElement({ hidden: true }) render( @@ -189,92 +189,11 @@ describe('ModelSelector desktop layout', () => { fireEvent.click(screen.getByTestId('model-selector-button')) fireEvent.mouseEnter(await screen.findByTestId('model-control-menu-model')) - expect(await screen.findByTestId('model-family-codex-official')).toHaveTextContent('我的CodeX') - expect(screen.getByTestId('model-family-claude')).toBeInTheDocument() - expect(screen.getByTestId('model-selector-submenu')).not.toHaveClass('min-h-48') - expect(screen.queryByTestId(`model-option-${SAMPLE_MODEL.name}`)).not.toBeInTheDocument() - - fireEvent.mouseEnter(screen.getByTestId('model-family-claude')) - - const familySubmenu = await screen.findByTestId('model-selector-family-submenu') - expect(familySubmenu).toHaveTextContent('Claude') - expect(familySubmenu).not.toHaveClass('min-h-48') + const submenu = await screen.findByTestId('model-selector-submenu') + expect(submenu).toHaveTextContent('我的CodeX') + expect(submenu).toHaveTextContent('Claude') expect(screen.getByTestId(`model-option-${SECOND_FAMILY_MODEL.name}`)).toBeInTheDocument() - expect(screen.queryByTestId(`model-option-${SAMPLE_MODEL.name}`)).not.toBeInTheDocument() - }) - - test('keeps the family model submenu above the viewport bottom', async () => { - createShellElement({ hidden: true }) - const originalGetBoundingClientRect = HTMLElement.prototype.getBoundingClientRect - const originalScrollHeight = Object.getOwnPropertyDescriptor( - HTMLElement.prototype, - 'scrollHeight' - ) - HTMLElement.prototype.getBoundingClientRect = function getBoundingClientRect() { - if (this.getAttribute('data-testid') === 'model-selector-menu') { - return { - top: 600, - left: 600, - right: 856, - bottom: 856, - width: 256, - height: 256, - x: 600, - y: 600, - toJSON: () => {}, - } as DOMRect - } - if (this.getAttribute('data-testid') === 'model-selector-family-submenu') { - return { - top: 800, - left: 888, - right: 1176, - bottom: 1040, - width: 288, - height: 240, - x: 888, - y: 800, - toJSON: () => {}, - } as DOMRect - } - return originalGetBoundingClientRect.call(this) - } - Object.defineProperty(HTMLElement.prototype, 'scrollHeight', { - configurable: true, - get() { - return this.getAttribute('data-testid') === 'model-selector-family-submenu' ? 240 : 0 - }, - }) - - try { - render( - - ) - - fireEvent.click(screen.getByTestId('model-selector-button')) - fireEvent.mouseEnter(await screen.findByTestId('model-control-menu-model')) - fireEvent.mouseEnter(await screen.findByTestId('model-family-claude')) - - const familySubmenu = await screen.findByTestId('model-selector-family-submenu') - const wrapper = screen.getByTestId('model-selector-menu').parentElement - await waitFor(() => { - expect( - parseInt(wrapper!.style.top, 10) + parseInt(familySubmenu.style.top, 10) + 240 - ).toBeLessThanOrEqual(WINDOW_INNER_HEIGHT - 16) - }) - } finally { - HTMLElement.prototype.getBoundingClientRect = originalGetBoundingClientRect - if (originalScrollHeight) { - Object.defineProperty(HTMLElement.prototype, 'scrollHeight', originalScrollHeight) - } - } + expect(screen.getByTestId(`model-option-${SAMPLE_MODEL.name}`)).toBeInTheDocument() }) test('caps the trigger width when maxClosedWidth is provided', () => { diff --git a/wework/src/components/chat/composer/ModelSelector.tsx b/wework/src/components/chat/composer/ModelSelector.tsx index 9caa1da51de..f0b25396d17 100644 --- a/wework/src/components/chat/composer/ModelSelector.tsx +++ b/wework/src/components/chat/composer/ModelSelector.tsx @@ -95,7 +95,6 @@ export function ModelSelector({ const desktopMenuWrapperRef = useRef(null) const menuPanelRef = useRef(null) const submenuPanelRef = useRef(null) - const familySubmenuPanelRef = useRef(null) const mobileMenuRef = useRef(null) const mobileCloseButtonRef = useRef(null) const modelButtonRef = useRef(null) @@ -113,9 +112,6 @@ export function ModelSelector({ const [activeDesktopSubmenu, setActiveDesktopSubmenu] = useState( null ) - const [activeDesktopFamilyId, setActiveDesktopFamilyId] = useState(null) - const [desktopFamilyOffset, setDesktopFamilyOffset] = useState(0) - const [desktopFamilyTop, setDesktopFamilyTop] = useState(0) const [advancedOpen, setAdvancedOpen] = useState(readModelSelectorPowerViewPreference) const [powerSliderInteracting, setPowerSliderInteracting] = useState(false) const modelSelectorShortcut = useConfiguredKeybinding(TOGGLE_MODEL_SELECTOR_COMMAND) @@ -140,7 +136,6 @@ export function ModelSelector({ setOpen(false) setMobileQuery('') setActiveDesktopSubmenu(null) - setActiveDesktopFamilyId(null) setPowerSliderInteracting(false) }, [setActiveDesktopSubmenu, setMobileQuery, setOpen, setPowerSliderInteracting]) const handleSelectModelOption = useCallback( @@ -277,11 +272,9 @@ export function ModelSelector({ ) const activateModels = useCallback(() => { setActiveDesktopSubmenu({ type: 'models' }) - setActiveDesktopFamilyId(null) - }, [setActiveDesktopSubmenu, setActiveDesktopFamilyId]) + }, [setActiveDesktopSubmenu]) const clearDesktopSubmenu = useCallback(() => { setActiveDesktopSubmenu({ type: 'none' }) - setActiveDesktopFamilyId(null) }, [setActiveDesktopSubmenu]) const activateMobileFamily = useCallback( (familyId: string) => { @@ -395,39 +388,6 @@ export function ModelSelector({ activeDesktopSubmenu?.type === 'control' ? desktopControls.find(control => control.id === activeDesktopSubmenu.id) : undefined - const activeDesktopFamily = activeDesktopFamilyId - ? familyGroups.find(group => group.config.id === activeDesktopFamilyId) - : undefined - const desktopFamilySubmenuWidth = SUBMENU_WIDTH - const desktopFamilySubmenuLeft = (() => { - const modelSubmenuWidth = submenuWidth ?? SUBMENU_WIDTH - if (submenuLeft < 0) { - return submenuLeft - desktopFamilySubmenuWidth - } - - const rightSideLeft = submenuLeft + modelSubmenuWidth - const rightSideEdge = desktopMenuLeft + rightSideLeft + desktopFamilySubmenuWidth - return rightSideEdge <= getDesktopViewportRightBoundary() - VIEWPORT_MARGIN - ? rightSideLeft - : -desktopFamilySubmenuWidth - })() - - useLayoutEffect(() => { - if (!open || isMobile || !activeDesktopFamily) return - - const familySubmenu = familySubmenuPanelRef.current - if (!familySubmenu) return - - const submenuHeight = Math.min( - familySubmenu.scrollHeight || familySubmenu.getBoundingClientRect().height, - SUBMENU_MAX_HEIGHT, - Math.max(0, window.innerHeight - SUBMENU_VIEWPORT_VERTICAL_GAP) - ) - const preferredTop = submenuOffset + desktopFamilyOffset - const minTop = DESKTOP_MENU_VIEWPORT_TOP - desktopMenuTop - const maxTop = window.innerHeight - VIEWPORT_MARGIN - submenuHeight - desktopMenuTop - setDesktopFamilyTop(Math.round(Math.max(minTop, Math.min(preferredTop, maxTop)))) - }, [activeDesktopFamily, desktopFamilyOffset, desktopMenuTop, isMobile, open, submenuOffset]) useLayoutEffect(() => { if (!open || isMobile) return @@ -1030,7 +990,7 @@ export function ModelSelector({ data-enter-animation="submenu" style={{ top: submenuOffset, left: submenuLeft, width: submenuWidth }} className={cn( - 'absolute max-h-[min(28rem,calc(100vh-8rem))] w-72 overflow-y-auto rounded-2xl border border-border bg-background p-2 shadow-[0_16px_44px_rgba(0,0,0,0.16)]', + 'absolute max-h-[min(28rem,calc(100vh-8rem))] min-h-48 w-72 overflow-y-auto rounded-2xl border border-border bg-background p-2 shadow-[0_16px_44px_rgba(0,0,0,0.16)]', styles.submenu )} > @@ -1040,59 +1000,14 @@ export function ModelSelector({
{familyGroups.length <= 1 ? renderDesktopModelOptions(desktopModels) - : familyGroups.map(group => { - const active = activeDesktopFamilyId === group.config.id - return ( - - ) - })} -
- - ) : null} - {activeDesktopSubmenu?.type === 'models' && activeDesktopFamily ? ( -
-
- {activeDesktopFamily.config.label} -
-
- {renderDesktopModelOptions(activeDesktopFamily.models)} + : familyGroups.map(group => ( +
+
+ {group.config.label} +
+ {renderDesktopModelOptions(group.models)} +
+ ))}
) : null}