Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 68 additions & 23 deletions src/Client.js
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,26 @@ class Client extends EventEmitter {
},
);

/**
* Maps WhatsApp's resolved connection screen onto the public client
* events. QR and ERROR are intentionally absent: they keep their own
* code paths and emit nothing here.
* @event Client#ready
* @event Client#loading_screen
*/
const EMIT_BY_SCREEN = {
CONNECTED: () => [Events.READY],
LOADING: (percent) => [
Events.LOADING_SCREEN,
percent,
'WhatsApp',
],
DISCONNECTED: (percent) => [
Events.LOADING_SCREEN,
percent,
'WhatsApp',
],
};
await exposeFunctionIfAbsent(
this.pupPage,
'onAppStateHasSyncedEvent',
Expand Down Expand Up @@ -357,24 +377,60 @@ class Client extends EventEmitter {
this.interface = new InterfaceController(this);

await this.attachEventListeners();

// Connection lifecycle: subscribe to WhatsApp's own
// Stream model (the same signals its loading screen
// renders from) now that ClientInfo exists, then fire
// once for the current state. Backbone only fires on
// real changes, so there is no init race, no backstop
// and no manual de-dup.
await this.pupPage.evaluate(() => {
const {
Stream,
StreamMode: M,
StreamInfo: I,
} = window.require('WAWebStreamModel');
const resolveScreen = () => {
switch (Stream.mode) {
case M.MAIN:
return Stream.displayInfo === I.NORMAL
? 'CONNECTED'
: 'LOADING';
case M.QR:
return 'QR';
case M.OFFLINE:
return 'DISCONNECTED';
case M.SYNCING:
return 'LOADING';
default:
return 'ERROR';
}
};
let lastScreen = null;
const notify = () => {
const screen = resolveScreen();
if (screen === lastScreen) return;
lastScreen = screen;
window.onConnectionStateEvent(
screen,
window
.require('WAWebOfflineHandler')
.OfflineMessageHandler.getOfflineDeliveryProgress(),
);
};
Stream.on('change:mode change:displayInfo', notify);
notify();
});
}
/**
* Emitted when the client has initialized and is ready to receive messages.
* @event Client#ready
*/
this.emit(Events.READY);
this.authStrategy.afterAuthReady();
},
);
let lastPercent = null;
await exposeFunctionIfAbsent(
this.pupPage,
'onOfflineProgressUpdateEvent',
async (percent) => {
if (lastPercent !== percent) {
lastPercent = percent;
this.emit(Events.LOADING_SCREEN, percent, 'WhatsApp'); // Message is hardcoded as "WhatsApp" for now
}
'onConnectionStateEvent',
(screen, percent) => {
const args = EMIT_BY_SCREEN[screen]?.(percent);
if (args) this.emit(...args);
},
);
await exposeFunctionIfAbsent(
Expand Down Expand Up @@ -406,17 +462,6 @@ class Client extends EventEmitter {
window.onAppStateHasSyncedEvent();
},
],
[
Cmd,
'offline_progress_update_from_bridge',
() => {
window.onOfflineProgressUpdateEvent(
window
.require('WAWebOfflineHandler')
.OfflineMessageHandler.getOfflineDeliveryProgress(),
);
},
],
[
Cmd,
'logout',
Expand Down
Loading