diff --git a/sticker-creator/window/phase3-sticker-functions.ts b/sticker-creator/window/phase3-sticker-functions.ts index fb3fbae53..111f5d66b 100644 --- a/sticker-creator/window/phase3-sticker-functions.ts +++ b/sticker-creator/window/phase3-sticker-functions.ts @@ -165,6 +165,7 @@ window.encryptAndUpload = async ( username, password, useWebSocket: false, + hasStoriesDisabled: true, }); const manifestProto = new Proto.StickerPack(); diff --git a/ts/background.ts b/ts/background.ts index 178a9926c..1cba57be3 100644 --- a/ts/background.ts +++ b/ts/background.ts @@ -221,9 +221,10 @@ export async function startApp(): Promise { let routineProfileRefresher: RoutineProfileRefresher | undefined; window.storage.onready(() => { - server = window.WebAPI.connect( - window.textsecure.storage.user.getWebAPICredentials() - ); + server = window.WebAPI.connect({ + ...window.textsecure.storage.user.getWebAPICredentials(), + hasStoriesDisabled: window.storage.get('hasStoriesDisabled', false), + }); window.textsecure.server = server; initializeAllJobQueues({ @@ -1722,9 +1723,7 @@ export async function startApp(): Promise { } log.info('reconnectToWebSocket starting...'); - await server.onOffline(); - await server.onOnline(); - log.info('reconnectToWebSocket complete.'); + await server.reconnect(); }); }; diff --git a/ts/services/storageRecordOps.ts b/ts/services/storageRecordOps.ts index 2de936804..f3f89026c 100644 --- a/ts/services/storageRecordOps.ts +++ b/ts/services/storageRecordOps.ts @@ -1256,7 +1256,11 @@ export async function mergeAccountRecord( window.storage.put('displayBadgesOnProfile', Boolean(displayBadgesOnProfile)); window.storage.put('keepMutedChatsArchived', Boolean(keepMutedChatsArchived)); window.storage.put('hasSetMyStoriesPrivacy', Boolean(hasSetMyStoriesPrivacy)); - window.storage.put('hasStoriesDisabled', Boolean(storiesDisabled)); + { + const hasStoriesDisabled = Boolean(storiesDisabled); + window.storage.put('hasStoriesDisabled', hasStoriesDisabled); + window.textsecure.server?.onHasStoriesDisabledChange(hasStoriesDisabled); + } const ourID = window.ConversationController.getOurConversationId(); diff --git a/ts/textsecure/SocketManager.ts b/ts/textsecure/SocketManager.ts index fb0fbfbd1..f3ff4e189 100644 --- a/ts/textsecure/SocketManager.ts +++ b/ts/textsecure/SocketManager.ts @@ -37,6 +37,7 @@ export type SocketManagerOptions = Readonly<{ certificateAuthority: string; version: string; proxyUrl?: string; + hasStoriesDisabled: boolean; }>; // This class manages two websocket resources: @@ -76,12 +77,16 @@ export class SocketManager extends EventListener { private isOffline = false; + private hasStoriesDisabled: boolean; + constructor(private readonly options: SocketManagerOptions) { super(); if (options.proxyUrl) { this.proxyAgent = new ProxyAgent(options.proxyUrl); } + + this.hasStoriesDisabled = options.hasStoriesDisabled; } public getStatus(): SocketStatus { @@ -124,7 +129,10 @@ export class SocketManager extends EventListener { this.credentials = credentials; - log.info('SocketManager: connecting authenticated socket'); + log.info( + 'SocketManager: connecting authenticated socket ' + + `(hasStoriesDisabled=${this.hasStoriesDisabled})` + ); this.setStatus(SocketStatus.CONNECTING); @@ -138,6 +146,9 @@ export class SocketManager extends EventListener { this.queueOrHandleRequest(req); }, }, + extraHeaders: { + 'X-Signal-Receive-Stories': String(!this.hasStoriesDisabled), + }, }); // Cancel previous connect attempt or close socket @@ -348,6 +359,25 @@ export class SocketManager extends EventListener { this.requestHandlers.delete(handler); } + public async onHasStoriesDisabledChange(newValue: boolean): Promise { + if (this.hasStoriesDisabled === newValue) { + return; + } + + this.hasStoriesDisabled = newValue; + log.info( + `SocketManager: reconnecting after setting hasStoriesDisabled=${newValue}` + ); + await this.reconnect(); + } + + public async reconnect(): Promise { + log.info('SocketManager.reconnect: starting...'); + this.onOffline(); + await this.onOnline(); + log.info('SocketManager.reconnect: complete.'); + } + // Force keep-alive checks on WebSocketResources public async check(): Promise { if (this.isOffline) { @@ -374,7 +404,7 @@ export class SocketManager extends EventListener { // Puts SocketManager into "offline" state and gracefully disconnects both // unauthenticated and authenticated resources. - public async onOffline(): Promise { + public onOffline(): void { log.info('SocketManager.onOffline'); this.isOffline = true; @@ -471,11 +501,13 @@ export class SocketManager extends EventListener { path, resourceOptions, query = {}, + extraHeaders = {}, }: { name: string; path: string; resourceOptions: WebSocketResourceOptions; query?: Record; + extraHeaders?: Record; }): AbortableProcess { const queryWithDefaults = { agent: 'OWD', @@ -492,6 +524,8 @@ export class SocketManager extends EventListener { version: this.options.version, proxyAgent: this.proxyAgent, + extraHeaders, + createResource(socket: WebSocket): WebSocketResource { return new WebSocketResource(socket, resourceOptions); }, diff --git a/ts/textsecure/WebAPI.ts b/ts/textsecure/WebAPI.ts index 597c227e5..2bf668600 100644 --- a/ts/textsecure/WebAPI.ts +++ b/ts/textsecure/WebAPI.ts @@ -612,6 +612,7 @@ type AjaxOptionsType = { export type WebAPIConnectOptionsType = WebAPICredentials & { useWebSocket?: boolean; + hasStoriesDisabled: boolean; }; export type WebAPIConnectType = { @@ -962,9 +963,11 @@ export type WebAPIType = { getSocketStatus: () => SocketStatus; registerRequestHandler: (handler: IRequestHandler) => void; unregisterRequestHandler: (handler: IRequestHandler) => void; + onHasStoriesDisabledChange: (newValue: boolean) => void; checkSockets: () => void; onOnline: () => Promise; - onOffline: () => Promise; + onOffline: () => void; + reconnect: () => Promise; }; export type SignedPreKeyType = { @@ -1074,6 +1077,7 @@ export function initialize({ username: initialUsername, password: initialPassword, useWebSocket = true, + hasStoriesDisabled, }: WebAPIConnectOptionsType) { let username = initialUsername; let password = initialPassword; @@ -1088,6 +1092,7 @@ export function initialize({ certificateAuthority, version, proxyUrl, + hasStoriesDisabled, }); socketManager.on('statusChange', () => { @@ -1228,8 +1233,10 @@ export function initialize({ checkSockets, onOnline, onOffline, + reconnect, registerRequestHandler, unregisterRequestHandler, + onHasStoriesDisabledChange, authenticate, logout, cdsLookup, @@ -1430,8 +1437,12 @@ export function initialize({ await socketManager.onOnline(); } - async function onOffline(): Promise { - await socketManager.onOffline(); + function onOffline(): void { + socketManager.onOffline(); + } + + async function reconnect(): Promise { + await socketManager.reconnect(); } function registerRequestHandler(handler: IRequestHandler): void { @@ -1442,6 +1453,10 @@ export function initialize({ socketManager.unregisterRequestHandler(handler); } + function onHasStoriesDisabledChange(newValue: boolean): void { + socketManager.onHasStoriesDisabledChange(newValue); + } + async function getConfig() { type ResType = { config: Array<{ name: string; enabled: boolean; value: string | null }>; diff --git a/ts/util/createIPCEvents.tsx b/ts/util/createIPCEvents.tsx index c138e6ebe..309ad9b3c 100644 --- a/ts/util/createIPCEvents.tsx +++ b/ts/util/createIPCEvents.tsx @@ -184,6 +184,7 @@ export function createIPCEvents( await window.storage.put('hasStoriesDisabled', value); const account = window.ConversationController.getOurConversationOrThrow(); account.captureChange('hasStoriesDisabled'); + window.textsecure.server?.onHasStoriesDisabledChange(value); }, getPreferredAudioInputDevice: () =>