diff --git a/src/client/Client.tsx b/src/client/Client.tsx index e67bd71..2adc0a5 100644 --- a/src/client/Client.tsx +++ b/src/client/Client.tsx @@ -25,6 +25,7 @@ export interface IAuth { } export interface ClientState { + emailState: string | null; inFlight: { emailContents: Set<string>; emailStubs: Set<string>; @@ -33,7 +34,9 @@ export interface ClientState { mailboxes: { trash: IMailbox; } | null; + mailboxState: string | null; session: ISession | null; + threadState: string | null; } class Account implements IAccount { @@ -69,13 +72,16 @@ export default class Client { callbacks: Array<Callback> = []; jclient: jmapclient.Client | null = null; state: ClientState = { + emailState: null, inFlight: { emailContents: new Set(), emailStubs: new Set(), mailboxes: new Set(), }, mailboxes: null, + mailboxState: null, session: null, + threadState: null, }; // Get the currently active account @@ -247,8 +253,10 @@ export default class Client { receivedAt: e.receivedAt, subject: e.subject, }; - this._triggerChange(msg + e.id); }); + this._triggerChange(msg); + //this.state.session.state = response.sessionState; + this.state.emailState = response.state; }) .catch((x) => { console.error("Failed to get email stub", emailId, x); @@ -337,13 +345,57 @@ export default class Client { c(); }); } + _onChangedEmail(accountId: string, state: string) { + console.log("Email changed", state); + if (this.jclient === null) return; + if (this.state.session === null) return; + const account = this.account(accountId); + if (account === null) return; + if (this.state.emailState === null) return; + const args = { + accountId: accountId, + sinceState: this.state.emailState, + }; + this.jclient.email_changes(args).then((r) => { + console.log("Handle email changes ", r); + }); + } + _onChangedMailbox(accountId: string, state: string) { + console.log("Mailbox changed", state); + if (this.jclient === null) return; + if (this.state.session === null) return; + const account = this.account(accountId); + if (account === null) return; + if (this.state.mailboxState === null) return; + const args = { + accountId: accountId, + sinceState: this.state.session.state, + }; + this.jclient.mailbox_changes(args).then((r) => { + console.log("Handle mailbox changes ", r); + }); + } + _onChangedThread(accountId: string, state: string) { + console.log("Thread changed", state); + if (this.jclient === null) return; + if (this.state.session === null) return; + const account = this.account(accountId); + if (account === null) return; + if (this.state.threadState === null) return; + const args = { + accountId: accountId, + sinceState: this.state.session.state, + }; + this.jclient.thread_changes(args).then((r) => { + console.log("Handle thread changes ", r); + }); + } _onSession() { - console.log("Session received"); - // For the type checker if (!this.jclient) return; const session = this.jclient.getSession(); + console.log("Session received: ", session); // Subscribe to server-pushed events if (session.eventSourceUrl) { this._subscribeToEventSource(session.eventSourceUrl); @@ -373,7 +425,28 @@ export default class Client { this.jclient.subscribeToEvents( eventSourceUrl, (type: string, message: PushMessage) => { - console.log("Got an event!", type, message); + if (type === "ping") { + return; + } + if (type === "state") { + console.log("Got an event!", type, message); + const stateChange = message as jmaptypes.IStateChange; + for (const [accountId, changes] of Object.entries( + stateChange.changed, + )) { + for (const [changeType, state] of Object.entries(changes)) { + if (changeType === "Email") { + this._onChangedEmail(accountId, state); + } else if (changeType === "Mailbox") { + this._onChangedMailbox(accountId, state); + } else if (changeType === "Thread") { + this._onChangedThread(accountId, state); + } + } + } + } else { + console.log("Not sure what to do with event", type); + } }, ); } diff --git a/src/client/jmap-client-ts b/src/client/jmap-client-ts index 160a66c..ee2af71 160000 --- a/src/client/jmap-client-ts +++ b/src/client/jmap-client-ts @@ -1 +1 @@ -Subproject commit 160a66caf7f385b18e25f224a64f75f213997bb2 +Subproject commit ee2af71a8e764c1a8153a7dcd71f4085f970243f