1
0
Fork 0
mirror of https://github.com/FrankerFaceZ/FrankerFaceZ.git synced 2025-08-10 08:10:52 +00:00

Fix setting sync using BroadcastChannel, since localStorage events are unreliable. Thanks Chrome. :D

This commit is contained in:
SirStendec 2018-03-21 16:51:10 -04:00
parent 8ce07a5603
commit 2e5c99c727
3 changed files with 57 additions and 2 deletions

View file

@ -1,3 +1,8 @@
<div class="list-header">4.0.0-beta1.6<span>@d2469b218214357ed0c0</span> <time datetime="2018-03-21">(2018-03-21)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Fixed: Settings are now properly and immediately synchronized across all open windows.</li>
</ul>
<div class="list-header">4.0.0-beta1.6<span>@e81b570ec2664e4cd19c</span> <time datetime="2018-03-19">(2018-03-19)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Fixed: Following Directory features not working correctly.</li>

View file

@ -115,10 +115,13 @@ export default class SettingsManager extends Module {
if ( key === 'profiles' )
return this.loadProfiles();
if ( ! key.startsWith('p:') )
return;
// If we're still here, it means an individual setting was changed.
// Look up the profile it belongs to and emit a changed event from
// that profile, thus notifying any contexts or UI instances.
key = key.substr(2);
const idx = key.indexOf(':');
if ( idx === -1 )
return;

View file

@ -75,8 +75,15 @@ export class LocalStorageProvider extends SettingsProvider {
this.ready = true;
this._boundHandleStorage = this.handleStorage.bind(this);
window.addEventListener('storage', this._boundHandleStorage);
if ( window.BroadcastChannel ) {
const bc = this._broadcaster = new BroadcastChannel('ffz-settings');
bc.addEventListener('message',
this._boundHandleMessage = this.handleMessage.bind(this));
} else {
window.addEventListener('storage',
this._boundHandleStorage = this.handleStorage.bind(this));
}
}
destroy() {
@ -87,6 +94,12 @@ export class LocalStorageProvider extends SettingsProvider {
disable() {
this.disabled = true;
if ( this._broadcaster ) {
this._broadcaster.removeEventListener('message', this._boundHandleMessage);
this._broadcaster.close();
this._boundHandleMessage = this._broadcaster = null;
}
if ( this._boundHandleStorage ) {
window.removeEventListener('storage', this._boundHandleStorage);
this._boundHandleStorage = null;
@ -94,6 +107,37 @@ export class LocalStorageProvider extends SettingsProvider {
}
broadcast(msg) {
if ( this._broadcaster )
this._broadcaster.postMessage(msg);
}
handleMessage(event) {
if ( this.disabled || ! event.isTrusted || ! event.data )
return;
this.manager.log.debug('storage broadcast event', event.data);
const {type, key} = event.data;
if ( type === 'set' ) {
const val = JSON.parse(localStorage.getItem(this.prefix + key));
this._cached.set(key, val);
this.emit('changed', key, val, false);
} else if ( type === 'delete' ) {
this._cached.delete(key);
this.emit('changed', key, undefined, true);
} else if ( type === 'clear' ) {
const old_keys = Array.from(this._cached.keys());
this._cached.clear();
for(const key of old_keys)
this.emit('changed', key, undefined, true);
}
}
handleStorage(event) {
if ( this.disabled )
return;
@ -129,11 +173,13 @@ export class LocalStorageProvider extends SettingsProvider {
set(key, value) {
this._cached.set(key, value);
localStorage.setItem(this.prefix + key, JSON.stringify(value));
this.broadcast({type: 'set', key});
}
delete(key) {
this._cached.delete(key);
localStorage.removeItem(this.prefix + key);
this.broadcast({type: 'delete', key});
}
has(key) {
@ -149,6 +195,7 @@ export class LocalStorageProvider extends SettingsProvider {
localStorage.removeItem(this.prefix + key);
this._cached.clear();
this.broadcast({type: 'clear'});
}
entries() {