@@ -28,10 +28,12 @@ export const COPY_LINK_SELECTORS = [
2828 * The webapp migrated from #channelHeaderDropdownButton to Menu.Button
2929 * with an aria-label like "off-topic channel menu".
3030 */
31- export async function openChannelHeaderMenu ( win : ServerView ) : Promise < void > {
32- await win . waitForSelector ( CHANNEL_HEADER_MENU_TRIGGER , { state : 'visible' , timeout : 15_000 } ) ;
31+ export async function openChannelHeaderMenu ( win : ServerView , timeout = 20_000 ) : Promise < void > {
32+ const menuTimeout = Math . min ( Math . max ( Math . floor ( timeout * 0.25 ) , 500 ) , 5_000 ) ;
33+ const triggerTimeout = Math . max ( timeout - menuTimeout , 500 ) ;
34+ await win . waitForSelector ( CHANNEL_HEADER_MENU_TRIGGER , { state : 'visible' , timeout : triggerTimeout } ) ;
3335 await win . click ( CHANNEL_HEADER_MENU_TRIGGER ) ;
34- await win . waitForSelector ( '#channelHeaderDropdownMenu, .a11y__popup' , { timeout : 5_000 } ) ;
36+ await win . waitForSelector ( '#channelHeaderDropdownMenu, .a11y__popup' , { timeout : menuTimeout } ) ;
3537}
3638
3739const SIDEBAR_CHANNEL_MENU_BUTTON = ( channelItemSelector : string ) => [
@@ -117,34 +119,59 @@ export async function clickCopyLinkInMenu(win: ServerView): Promise<void> {
117119 * helper only toggles the preference — callers wait for bookmark items later.
118120 */
119121export async function enableBookmarksBar ( win : ServerView ) : Promise < void > {
120- const alreadyVisible = await win . runInRenderer ( `
122+ const isBookmarksBarVisible = async ( ) : Promise < boolean > => win . runInRenderer ( `
121123 const container = document.querySelector('[data-testid="channel-bookmarks-container"]');
122124 if (!container) {
123125 return false;
124126 }
125127 const rect = container.getBoundingClientRect();
126128 return rect.width > 0 && rect.height > 0;
127129 ` ) ;
128- if ( alreadyVisible ) {
130+
131+ if ( await isBookmarksBarVisible ( ) ) {
129132 return ;
130133 }
131134
132- await openChannelHeaderMenu ( win ) ;
133- const toggled = await win . runInRenderer ( `
134- const items = Array.from(document.querySelectorAll(
135- '[role="menuitem"], .MenuItem, [id^="channel-menu-"]',
136- ));
137- const barItem = items.find((item) => /bookmarks bar/i.test((item.textContent || '').trim()));
138- if (!barItem) {
139- return false;
135+ const deadline = Date . now ( ) + 15_000 ;
136+ while ( Date . now ( ) < deadline ) {
137+ const remaining = Math . max ( deadline - Date . now ( ) , 1_000 ) ;
138+ await openChannelHeaderMenu ( win , remaining ) ;
139+
140+ const toggleResult = await win . runInRenderer ( `
141+ const submenuTrigger = document.querySelector('[id^="channel-menu-"][id$="-bookmarks"]');
142+ if (submenuTrigger instanceof HTMLElement) {
143+ submenuTrigger.dispatchEvent(new MouseEvent('mouseenter', {bubbles: true}));
144+ submenuTrigger.dispatchEvent(new MouseEvent('mouseover', {bubbles: true}));
145+ }
146+
147+ const items = Array.from(document.querySelectorAll(
148+ '[role="menuitem"], .MenuItem, [id^="channel-menu-"]',
149+ ));
150+ const barItem = items.find((item) => {
151+ const text = (item.textContent || '').trim();
152+ return /bookmarks bar/i.test(text) && !/add a link|add bookmark|attach file/i.test(text);
153+ });
154+ if (!barItem) {
155+ // Modern webapp: bookmarks live under the Bookmarks submenu and the bar
156+ // autoshows once a bookmark exists — no separate Show/Hide toggle.
157+ return submenuTrigger ? 'submenu-only' : 'missing';
158+ }
159+ const label = (barItem.textContent || '').trim().toLowerCase();
160+ const checked = barItem.getAttribute('aria-checked');
161+ if (label.includes('hide') || checked === 'true') {
162+ return 'enabled';
163+ }
164+ barItem.click();
165+ return 'clicked';
166+ ` , true ) ;
167+ await win . keyboard . press ( 'Escape' ) . catch ( ( ) => undefined ) ;
168+ if ( toggleResult === 'enabled' || toggleResult === 'clicked' || toggleResult === 'submenu-only' ) {
169+ return ;
140170 }
141- barItem.click();
142- return true;
143- ` , true ) ;
144- if ( ! toggled ) {
145- throw new Error ( 'Bookmarks Bar menu item not found in channel header menu' ) ;
171+ await new Promise ( ( resolve ) => setTimeout ( resolve , 300 ) ) ;
146172 }
147- await win . keyboard . press ( 'Escape' ) ;
173+
174+ throw new Error ( 'Bookmarks Bar menu item not found in channel header menu' ) ;
148175}
149176
150177export const TEAM_SIDEBAR_BUTTON = [
0 commit comments