Skip to content

Commit

Permalink
feat(vue3): add state.watch API
Browse files Browse the repository at this point in the history
  • Loading branch information
bourdaisj committed Nov 8, 2024
1 parent a1aa3b6 commit 49abf0d
Showing 1 changed file with 56 additions and 0 deletions.
56 changes: 56 additions & 0 deletions vue3-app/src/core/trame/state.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,44 @@ import { decorate, registerDecorator } from "./decorators";
// ----------------------------------------------------------------------------
// State helper
// ----------------------------------------------------------------------------
export class WatcherManager {
constructor() {
this.nextId = 1;
this.listeners = {};
}

watch(dependencies, callback) {
const key = `${this.nextId++}`;
this.listeners[key] = {
key,
dependencies,
callback,
};
const unsubscribe = () => delete this.listeners[key];
return unsubscribe;
}

notifyWatchers(changedKeys, fullState) {
const watchers = Object.values(this.listeners);
const keys = new Set(changedKeys);

for (let i = 0; i < watchers.length; i++) {
const { dependencies, callback } = watchers[i];
if (keys.intersection(new Set(dependencies)).size) {
const args = dependencies.map((v) => fullState[v]);
try {
callback(...args);
} catch (e) {
console.error(`Watcher error with dependencies: ${dependencies}`, e);
}
}
}
}

getWatchers() {
return Object.values(this.listeners);
}
}

export class SharedState {
constructor(client) {
Expand All @@ -15,6 +53,7 @@ export class SharedState {
this.mtime = 0;
this.listeners = [];
this.ready = false;
this._watchers = new WatcherManager();

// bind decorator helper
this.registerDecorator = registerDecorator;
Expand Down Expand Up @@ -77,6 +116,14 @@ export class SharedState {
)
);

this.subscriptions.push(
this.addListener(({ type, keys }) => {
if (type === "dirty-state") {
this._watchers.notifyWatchers(keys, this.state);
}
})
);

// Keep it so we can call it on disconnect
this._updateFromServer = updateFromServer;
}
Expand Down Expand Up @@ -125,6 +172,15 @@ export class SharedState {
return this.state[key];
}

watch(keys, fn) {
const unsubscribe = this._watchers.watch(keys, fn);

// Call it right away with available values
fn(...keys.map((v) => this.state[v]));

return unsubscribe;
}

async set(key, value) {
// Prevent triggering change when same value is set
if (this.state[key] === value) {
Expand Down

0 comments on commit 49abf0d

Please sign in to comment.