Fix #2236: unrevert changes to state synchronisation

Revert "Revert "Merge pull request #2137 from tridactyl/state_no_onchanged""

This reverts commit 4497ec3442.
This commit is contained in:
Oliver Blanthorn 2020-04-16 22:31:38 +01:00
parent fe80381c77
commit ac33cbd88c
No known key found for this signature in database
GPG key ID: 2BB8C36BB504BFF3
2 changed files with 29 additions and 9 deletions

View file

@ -11,6 +11,7 @@ export type TabMessageType =
| "finding_content"
| "commandline_cmd"
| "commandline_frame"
| "state"
| "lock"
export type NonTabMessageType =
@ -152,7 +153,10 @@ export async function messageAllTabs(
try {
responses.push(await messageTab(tab.id, type, command, args))
} catch (e) {
logger.error(e)
// Skip errors caused by tabs we aren't running on
if (e.message != "Could not establish connection. Receiving end does not exist.") {
logger.error(e)
}
}
}
return responses

View file

@ -14,7 +14,9 @@
If this turns out to be expensive there are improvements available.
*/
import * as locks from "@src/lib/locks"
import Logger from "@src/lib/logging"
import * as messaging from "@src/lib/messaging"
const logger = new Logger("state")
class State {
@ -54,19 +56,33 @@ const state = (new Proxy(overlay, {
}
},
/** Persist sets to storage immediately */
/** Persist sets to storage "immediately" */
set(target, property, value) {
logger.debug("State changed!", property, value)
target[property] = value
browser.storage.local.set({ state: target } as any)
locks.withlock("state", async () => {
logger.debug("State changed!", property, value)
target[property] = value
browser.storage.local.set({ state: target } as any)
// Wait for reply from each script to say that they have updated their own state
await Promise.all([
// dispatch message to all content state.ts's
messaging.messageAllTabs("state", "stateUpdate", [{state: target}]),
// Ideally this V would use Farnoy's typed messages but
// I haven't had time to get my head around them
browser.runtime.sendMessage({type: "state", command: "stateUpdate", args: [{state: target}]}),
])
})
return true
},
}))
browser.storage.onChanged.addListener((changes, areaname) => {
if (areaname === "local" && "state" in changes) {
Object.assign(overlay, changes.state.newValue)
}
// Keep instances of state.ts synchronised with each other
messaging.addListener("state", (message, sender, sendResponse) => {
if (message.command !== "stateUpdate") throw("Unsupported message to state, type " + message.command)
Object.assign(overlay, message.args[0].state)
sendResponse(true)
})
export { state as default }