Is it possible to conditionally open sidebar depending on var in storage.sync

I have a variable named tabMode that can take the value ‘openSidebar’ amongst others. It is stored in the options object in storage.sync. I’d like the sidebar to only open if the value ‘openSidebar’ is assigned to tabMode. Unfortunately, I keep getting an error:

Uncaught (in promise) Error: sidebarAction.open may only be called from a user input handler

Here is the latest code that I tried: (which fails)

async function f(info, tab) {
    const options = await getOptions();
    handleMenuClick(info, tab, options);
}

function addClickListener() {
    if (!menuClickListenerAdded) {
        browser.menus.onClicked.addListener(f);
        menuClickListenerAdded = true;
    }
}

function removeClickListener() {
    if (menuClickListenerAdded) {
        browser.menus.onClicked.removeListener(f);
        menuClickListenerAdded = false;
    }
}

async function handleMenuClick(info, tab, options) {
    const id = (info.menuItemId.startsWith('cs-')) ? info.menuItemId.replace('cs-', '') : info.menuItemId;
    const ignoreIds = ['download-video', 'reverse-image-search', 'google-lens', 'options', 'multitab', 'match', 'ai-search'];

    if (logToConsole) console.log('Clicked on ' + id);

    if (options.tabMode === 'openSidebar' && !ignoreIds.includes(id)) {
        if (logToConsole) console.log('Opening the sidebar.');
        await browser.sidebarAction.open();
        await browser.sidebarAction.setPanel({ panel: '' });
    } else {
        if (logToConsole) console.log('Not opening the sidebar.');
    }

    await processSearch(info, tab);
}

Not right now, but eventually it will probably be possible:

2 Likes

I think that this feature would nicely improve UX. Thank you for letting me know.

Yep yep, this affects all browsers. As noted in 1398833#c19, “Next step is to raise this topic in the WECG to align and specify the desired behavior.” We (the WECG) kicked around some ideas at TPAC 2024, but we still need a proposal on how best to address this.

I hope it won’t take too long, because users aren’t happy and I don’t know what to do:

I wouldn’t hold my breath :upside_down_face:.

But there are some “bad” workarounds available, at least for Firefox.

  1. you can use “localStorage” API - which is synchronous, so you can read and write it anytime and you won’t loose the “user-action flag” (I don’t know how to call it…).
    However, it’s kind of “deprecated” (in MV3) and it stores everything as string, so not great.

  2. since your background script is persistent, you could “simply” keep copy of your “options” in a global variable (available for sync. read operations).
    This can be done pretty simply:

    1. create async function that loads the “options” from storage to a global variable.
    2. call this function each time storage changes (the browser.storage.local.onChanged.addListener handler)
    3. call that function also on browser start (to populate it initially)
    4. when you need sync. access to options, access it through the global variable

This second option is actually what I’ve been using all along since 2017 :slight_smile: for all my addons for “options”.

1 Like

Thanks, Juraj. Your second suggestion sounds good to me. Will give it a try. I always thought that the way things were designed was supposed to make our lives easier. I’ve witnessed that it’s not always so!

1 Like