I’ve got my app up to what I would call a “twitchy alpha”, and I am looking at dealing with a minor annoyance.
A user can edit or create custom tags for a context menu, but they do not show up on that context menu until the extension is reloaded (currently doing this though the whole about:debugging thing).
Obviously, once it gets released on AMO, I could just tell the users that the modifications to custom tags require a restart, but that is a bit of a PITA.
Is there a function that can be called to regenerate the custom tags when the user hits save on new/modified tags?
Well I suppose there is one easy way - create function that builds all context menu items and when user changes something, just remove all menus and recreate them again using your function.
Does it make sense to pull the menu creation code out of my context menu script, and make it a library that I would load when the extension is first loaded (contextmenu.js) when the user changes the active menus (options.js) and when the user changes the custom menus (custom_tags.js), or should I just copy and paste into all three scripts?
I would implement it in the background script and then control it by sending messages to your background script.
You can have it in the separate file - your background script can load multiple scripts just like any other page.
The thing is that the script to delete and regenerate the menus will run three times:
At startup. (Runs in the background script ./context_menu.js now)
When changing the active menus on the ./settings/options.html page.
When editing custom tags on the ./settings/custom+tags.html page. (I keep them separate because I prefer the interface that way)
My ./context_menu.js already generates the menu upon extension loading and reloading.
So, could I simply put a menus.removeAll() before the menu generation code of my ./context_menu.js file, and then call it when the save button is pushed on the other pages? (Message passing reruns ./context_menu.js)
But you could decouple it completely by using existing events.
For example, when user clicks save button, you store the config to the browser storage, right?
I would just register browser.storage.onChanged.addListener listener in your context menu builder module and let it rebuild it. That way, you don’t care who and where changed it, it will rebuild when saved settings changes.
The former invoked the function, and the latter did nothing, but this probably has something to do with my profound lack of knowledge in JavaScript.
For example, I know that the => used in your code above, is some sort of Java idiom, and I have actually used it in some (open source licensed) code that I’ve borrowed, but I do not quite know what it does.
The two snippets above were what I tried, and the former worked, and the latter did not.
These event listeners are for two completely different storages. The first one is for window.localStorage and window.sessionStorage and the second one is for browser.storage.local, browser.storage.managed and browser.storage.sync.
Regarding the storages - for your add-on data you may want to use browser.storage.local and not window.localStorage.
The window.localStorage is synchronous and it may get cleared:
Although this API is similar to Window.localStorage it is recommended that you don’t use Window.localStorage in extension code. Firefox will clear data stored by extensions using the localStorage API in various scenarios where users clear their browsing history and data for privacy reasons, while data saved using the storage.local API will be correctly persisted in these scenarios.
does not until I manually reaload the extension through the about:debugging page.
In the options page, saving the updated data looks like this:
function saveMenus () {
console.log(JSON.stringify(activeMenus));
for (i = 0; i < Object.keys(activeMenus).length; i++) {
let crntMenu = Object.keys(activeMenus)[i]; //steps through object names
let crntCheck = crntMenu+"CHK"; //steps through check box names
let checkVal = document.getElementById(crntCheck).checked; //gives boolean value of check box
activeMenus[crntMenu] = checkVal; //gotta use this notation because I am using a variable for the name.
}
localStorage.setItem('activeMenus',JSON.stringify(activeMenus)); //store default in local menu
console.log("Menu Settings Saved");
}
It appears the listener picks up when listening to the window, but not for the browser.
That seems like a thing that should never work. browser only has the webextension APIs, So the browser.storage.* APIs. No DOM API like localStorage or addEventListener
Important: localStorage and browser.storage.local are two very different things.
So, I’m trying to square the circle on the statement earlier in this discussion that window.localStorage should not be used, and that browser.storage.* will not work.
It appears that you are saying to me that to save locally stored data, I should probably use browser.localStorage.setItem(); as opposed to localStorage.setItem(); , and user browser.localStorage.getItem(); as well, correct?