Notification token on Windows

This commit is contained in:
Fedor Indutny 2025-02-03 14:30:19 -08:00 committed by GitHub
parent 74acb3a2dd
commit 22d30ec4eb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 142 additions and 122 deletions

View file

@ -2899,14 +2899,13 @@ function handleSignalRoute(route: ParsedSignalRoute) {
value: route.args.encryptedUsername, value: route.args.encryptedUsername,
}); });
} else if (route.key === 'showConversation') { } else if (route.key === 'showConversation') {
mainWindow.webContents.send('show-conversation-via-notification', { mainWindow.webContents.send(
conversationId: route.args.conversationId, 'show-conversation-via-token',
messageId: route.args.messageId, route.args.token
storyId: route.args.storyId, );
});
} else if (route.key === 'startCallLobby') { } else if (route.key === 'startCallLobby') {
mainWindow.webContents.send('start-call-lobby', { mainWindow.webContents.send('start-call-lobby', {
conversationId: route.args.conversationId, token: route.args.token,
}); });
} else if (route.key === 'linkCall') { } else if (route.key === 'linkCall') {
mainWindow.webContents.send('start-call-link', { mainWindow.webContents.send('start-call-link', {

View file

@ -37,10 +37,8 @@ const Image = (props: { id: string; src: string; 'hint-crop': string }) =>
export function renderWindowsToast({ export function renderWindowsToast({
avatarPath, avatarPath,
body, body,
conversationId,
heading, heading,
messageId, token,
storyId,
type, type,
}: WindowsNotificationData): string { }: WindowsNotificationData): string {
// Note: with these templates, the first <text> is one line, bolded // Note: with these templates, the first <text> is one line, bolded
@ -58,13 +56,11 @@ export function renderWindowsToast({
// 2) this also maps to the url-handling in main.ts // 2) this also maps to the url-handling in main.ts
if (type === NotificationType.Message || type === NotificationType.Reaction) { if (type === NotificationType.Message || type === NotificationType.Reaction) {
launch = showConversationRoute.toAppUrl({ launch = showConversationRoute.toAppUrl({
conversationId, token,
messageId: messageId ?? null,
storyId: storyId ?? null,
}); });
} else if (type === NotificationType.IncomingGroupCall) { } else if (type === NotificationType.IncomingGroupCall) {
launch = startCallLobbyRoute.toAppUrl({ launch = startCallLobbyRoute.toAppUrl({
conversationId, token,
}); });
} else if (type === NotificationType.IncomingCall) { } else if (type === NotificationType.IncomingCall) {
launch = showWindowRoute.toAppUrl({}); launch = showWindowRoute.toAppUrl({});

View file

@ -10,6 +10,7 @@ import * as log from './logging/log';
import { explodePromise } from './util/explodePromise'; import { explodePromise } from './util/explodePromise';
import { AccessType, ipcInvoke } from './sql/channels'; import { AccessType, ipcInvoke } from './sql/channels';
import { backupsService } from './services/backups'; import { backupsService } from './services/backups';
import { notificationService } from './services/notifications';
import { AttachmentBackupManager } from './jobs/AttachmentBackupManager'; import { AttachmentBackupManager } from './jobs/AttachmentBackupManager';
import { migrateAllMessages } from './messages/migrateMessageData'; import { migrateAllMessages } from './messages/migrateMessageData';
import { SECOND } from './util/durations'; import { SECOND } from './util/durations';
@ -22,6 +23,7 @@ type ResolveType = (data: unknown) => void;
export type CIType = { export type CIType = {
deviceName: string; deviceName: string;
getConversationId: (address: string | null) => string | null; getConversationId: (address: string | null) => string | null;
createNotificationToken: (address: string) => string | undefined;
getMessagesBySentAt( getMessagesBySentAt(
sentAt: number sentAt: number
): Promise<ReadonlyArray<MessageAttributesType>>; ): Promise<ReadonlyArray<MessageAttributesType>>;
@ -157,6 +159,19 @@ export function getCI({
return window.ConversationController.getConversationId(address); return window.ConversationController.getConversationId(address);
} }
function createNotificationToken(address: string): string | undefined {
const id = window.ConversationController.getConversationId(address);
if (!id) {
return undefined;
}
return notificationService._createToken({
conversationId: id,
messageId: undefined,
storyId: undefined,
});
}
async function openSignalRoute(url: string) { async function openSignalRoute(url: string) {
strictAssert( strictAssert(
isSignalRoute(url), isSignalRoute(url),
@ -201,6 +216,7 @@ export function getCI({
return { return {
deviceName, deviceName,
getConversationId, getConversationId,
createNotificationToken,
getMessagesBySentAt, getMessagesBySentAt,
handleEvent, handleEvent,
setProvisioningURL, setProvisioningURL,

View file

@ -4,6 +4,8 @@
import os from 'os'; import os from 'os';
import { debounce } from 'lodash'; import { debounce } from 'lodash';
import EventEmitter from 'events'; import EventEmitter from 'events';
import { v4 as getGuid } from 'uuid';
import { Sound, SoundType } from '../util/Sound'; import { Sound, SoundType } from '../util/Sound';
import { shouldHideExpiringMessageBody } from '../types/Settings'; import { shouldHideExpiringMessageBody } from '../types/Settings';
import OS from '../util/os/osMain'; import OS from '../util/os/osMain';
@ -36,16 +38,14 @@ type NotificationDataType = Readonly<{
export type NotificationClickData = Readonly<{ export type NotificationClickData = Readonly<{
conversationId: string; conversationId: string;
messageId: string | null; messageId: string | undefined;
storyId: string | null; storyId: string | undefined;
}>; }>;
export type WindowsNotificationData = { export type WindowsNotificationData = {
avatarPath?: string; avatarPath?: string;
body: string; body: string;
conversationId: string;
heading: string; heading: string;
messageId?: string; token: string;
storyId?: string;
type: NotificationType; type: NotificationType;
}; };
export enum NotificationType { export enum NotificationType {
@ -86,6 +86,7 @@ class NotificationService extends EventEmitter {
#lastNotification: null | Notification = null; #lastNotification: null | Notification = null;
#notificationData: null | NotificationDataType = null; #notificationData: null | NotificationDataType = null;
#tokenData: { token: string; data: NotificationClickData } | undefined;
// Testing indicated that trying to create/destroy notifications too quickly // Testing indicated that trying to create/destroy notifications too quickly
// resulted in notifications that stuck around forever, requiring the user // resulted in notifications that stuck around forever, requiring the user
@ -175,16 +176,20 @@ class NotificationService extends EventEmitter {
log.info('NotificationService: showing a notification', sentAt); log.info('NotificationService: showing a notification', sentAt);
if (OS.isWindows()) { if (OS.isWindows()) {
const token = this._createToken({
conversationId,
messageId,
storyId,
});
// Note: showing a windows notification clears all previous notifications first // Note: showing a windows notification clears all previous notifications first
drop( drop(
window.IPC.showWindowsNotification({ window.IPC.showWindowsNotification({
avatarPath: iconPath, avatarPath: iconPath,
body: message, body: message,
conversationId,
heading: title, heading: title,
messageId,
storyId,
type, type,
token,
}) })
); );
} else { } else {
@ -206,8 +211,8 @@ class NotificationService extends EventEmitter {
window.IPC.showWindow(); window.IPC.showWindow();
window.Events.showConversationViaNotification({ window.Events.showConversationViaNotification({
conversationId, conversationId,
messageId: messageId ?? null, messageId,
storyId: storyId ?? null, storyId,
}); });
} else if (type === NotificationType.IncomingGroupCall) { } else if (type === NotificationType.IncomingGroupCall) {
window.IPC.showWindow(); window.IPC.showWindow();
@ -304,6 +309,7 @@ class NotificationService extends EventEmitter {
// adding anythhing new; just one notification at a time. Electron forces it, so // adding anythhing new; just one notification at a time. Electron forces it, so
// we replicate it with our Windows notifications. // we replicate it with our Windows notifications.
if (!notificationData) { if (!notificationData) {
this.#tokenData = undefined;
drop(window.IPC.clearAllWindowsNotifications()); drop(window.IPC.clearAllWindowsNotifications());
} }
} else if (this.#lastNotification) { } else if (this.#lastNotification) {
@ -446,6 +452,32 @@ class NotificationService extends EventEmitter {
); );
} }
/** @internal */
public _createToken(data: NotificationClickData): string {
const token = getGuid();
this.#tokenData = {
token,
data,
};
return token;
}
public resolveToken(token: string): NotificationClickData | undefined {
if (!this.#tokenData) {
log.warn(`NotificationService: no data when looking up ${token}`);
return undefined;
}
if (this.#tokenData.token !== token) {
log.warn(`NotificationService: token mismatch ${token}`);
return undefined;
}
return this.#tokenData.data;
}
public clear(): void { public clear(): void {
log.info( log.info(
'NotificationService: clearing notification and requesting an update' 'NotificationService: clearing notification and requesting an update'

View file

@ -55,18 +55,13 @@ describe('routing', function (this: Mocha.Suite) {
const [friend] = contacts; const [friend] = contacts;
const page = await app.getWindow(); const page = await app.getWindow();
await page.locator('#LeftPane').waitFor(); await page.locator('#LeftPane').waitFor();
const conversationId = await page.evaluate( const token = await page.evaluate(
serviceId => window.SignalCI?.getConversationId(serviceId), serviceId => window.SignalCI?.createNotificationToken(serviceId),
friend.toContact().aci friend.toContact().aci
); );
strictAssert( strictAssert(typeof token === 'string', 'token must be returned');
typeof conversationId === 'string',
'conversationId must exist'
);
const conversationUrl = showConversationRoute.toAppUrl({ const conversationUrl = showConversationRoute.toAppUrl({
conversationId, token,
messageId: null,
storyId: null,
}); });
await app.openSignalRoute(conversationUrl); await app.openSignalRoute(conversationUrl);
const title = page.locator( const title = page.locator(

View file

@ -12,12 +12,12 @@ describe('renderWindowsToast', () => {
avatarPath: 'C:/temp/ab/abcd', avatarPath: 'C:/temp/ab/abcd',
body: 'Hi there!', body: 'Hi there!',
heading: 'Alice', heading: 'Alice',
conversationId: 'conversation5', token: 'token',
type: NotificationType.Message, type: NotificationType.Message,
}); });
const expected = const expected =
'<toast launch="sgnl://show-conversation?conversationId=conversation5" activationType="protocol"><visual><binding template="ToastImageAndText02"><image id="1" src="file:///C:/temp/ab/abcd" hint-crop="circle"></image><text id="1">Alice</text><text id="2">Hi there!</text></binding></visual></toast>'; '<toast launch="sgnl://show-conversation?token=token" activationType="protocol"><visual><binding template="ToastImageAndText02"><image id="1" src="file:///C:/temp/ab/abcd" hint-crop="circle"></image><text id="1">Alice</text><text id="2">Hi there!</text></binding></visual></toast>';
assert.strictEqual(xml, expected); assert.strictEqual(xml, expected);
}); });
@ -26,12 +26,12 @@ describe('renderWindowsToast', () => {
const xml = renderWindowsToast({ const xml = renderWindowsToast({
body: 'Hi there!', body: 'Hi there!',
heading: 'Alice', heading: 'Alice',
conversationId: 'conversation5', token: 'token',
type: NotificationType.Message, type: NotificationType.Message,
}); });
const expected = const expected =
'<toast launch="sgnl://show-conversation?conversationId=conversation5" activationType="protocol"><visual><binding template="ToastText02"><text id="1">Alice</text><text id="2">Hi there!</text></binding></visual></toast>'; '<toast launch="sgnl://show-conversation?token=token" activationType="protocol"><visual><binding template="ToastText02"><text id="1">Alice</text><text id="2">Hi there!</text></binding></visual></toast>';
assert.strictEqual(xml, expected); assert.strictEqual(xml, expected);
}); });
@ -40,14 +40,12 @@ describe('renderWindowsToast', () => {
const xml = renderWindowsToast({ const xml = renderWindowsToast({
body: 'Hi there!', body: 'Hi there!',
heading: 'Alice', heading: 'Alice',
conversationId: 'conversation5', token: 'token',
messageId: 'message6',
storyId: 'story7',
type: NotificationType.Message, type: NotificationType.Message,
}); });
const expected = const expected =
'<toast launch="sgnl://show-conversation?conversationId=conversation5&amp;messageId=message6&amp;storyId=story7" activationType="protocol"><visual><binding template="ToastText02"><text id="1">Alice</text><text id="2">Hi there!</text></binding></visual></toast>'; '<toast launch="sgnl://show-conversation?token=token" activationType="protocol"><visual><binding template="ToastText02"><text id="1">Alice</text><text id="2">Hi there!</text></binding></visual></toast>';
assert.strictEqual(xml, expected); assert.strictEqual(xml, expected);
}); });
@ -56,7 +54,7 @@ describe('renderWindowsToast', () => {
const xml = renderWindowsToast({ const xml = renderWindowsToast({
body: 'Hi there!', body: 'Hi there!',
heading: 'Alice', heading: 'Alice',
conversationId: 'conversation5', token: 'token',
type: NotificationType.IncomingCall, type: NotificationType.IncomingCall,
}); });
@ -70,12 +68,12 @@ describe('renderWindowsToast', () => {
const xml = renderWindowsToast({ const xml = renderWindowsToast({
body: 'Hi there!', body: 'Hi there!',
heading: 'Alice', heading: 'Alice',
conversationId: 'conversation5', token: 'token',
type: NotificationType.IncomingGroupCall, type: NotificationType.IncomingGroupCall,
}); });
const expected = const expected =
'<toast launch="sgnl://start-call-lobby?conversationId=conversation5" activationType="protocol"><visual><binding template="ToastText02"><text id="1">Alice</text><text id="2">Hi there!</text></binding></visual></toast>'; '<toast launch="sgnl://start-call-lobby?token=token" activationType="protocol"><visual><binding template="ToastText02"><text id="1">Alice</text><text id="2">Hi there!</text></binding></visual></toast>';
assert.strictEqual(xml, expected); assert.strictEqual(xml, expected);
}); });
@ -84,7 +82,7 @@ describe('renderWindowsToast', () => {
const xml = renderWindowsToast({ const xml = renderWindowsToast({
body: 'Hi there!', body: 'Hi there!',
heading: 'Alice', heading: 'Alice',
conversationId: 'conversation5', token: 'token',
type: NotificationType.IsPresenting, type: NotificationType.IsPresenting,
}); });

View file

@ -186,37 +186,23 @@ describe('signalRoutes', () => {
it('showConversation', () => { it('showConversation', () => {
const check = createCheck({ isRoute: true, hasWebUrl: false }); const check = createCheck({ isRoute: true, hasWebUrl: false });
const args1 = `conversationId=${foo}`; const args1 = `token=${foo}`;
const args2 = `conversationId=${foo}&messageId=${foo}`;
const args3 = `conversationId=${foo}&messageId=${foo}&storyId=${foo}`;
const result1: ParsedSignalRoute = { const result1: ParsedSignalRoute = {
key: 'showConversation', key: 'showConversation',
args: { conversationId: foo, messageId: null, storyId: null }, args: { token: foo },
};
const result2: ParsedSignalRoute = {
key: 'showConversation',
args: { conversationId: foo, messageId: foo, storyId: null },
};
const result3: ParsedSignalRoute = {
key: 'showConversation',
args: { conversationId: foo, messageId: foo, storyId: foo },
}; };
check(`sgnl://show-conversation/?${args1}`, result1); check(`sgnl://show-conversation/?${args1}`, result1);
check(`sgnl://show-conversation?${args1}`, result1); check(`sgnl://show-conversation?${args1}`, result1);
check(`sgnl://show-conversation/?${args2}`, result2);
check(`sgnl://show-conversation?${args2}`, result2);
check(`sgnl://show-conversation/?${args3}`, result3);
check(`sgnl://show-conversation?${args3}`, result3);
}); });
it('startCallLobby', () => { it('startCallLobby', () => {
const result: ParsedSignalRoute = { const result: ParsedSignalRoute = {
key: 'startCallLobby', key: 'startCallLobby',
args: { conversationId: foo }, args: { token: foo },
}; };
const check = createCheck({ isRoute: true, hasWebUrl: false }); const check = createCheck({ isRoute: true, hasWebUrl: false });
check(`sgnl://start-call-lobby/?conversationId=${foo}`, result); check(`sgnl://start-call-lobby/?token=${foo}`, result);
check(`sgnl://start-call-lobby?conversationId=${foo}`, result); check(`sgnl://start-call-lobby?token=${foo}`, result);
}); });
it('showWindow', () => { it('showWindow', () => {

View file

@ -35,7 +35,10 @@ import * as Registration from './registration';
import { lookupConversationWithoutServiceId } from './lookupConversationWithoutServiceId'; import { lookupConversationWithoutServiceId } from './lookupConversationWithoutServiceId';
import * as log from '../logging/log'; import * as log from '../logging/log';
import { deleteAllMyStories } from './deleteAllMyStories'; import { deleteAllMyStories } from './deleteAllMyStories';
import type { NotificationClickData } from '../services/notifications'; import {
type NotificationClickData,
notificationService,
} from '../services/notifications';
import { StoryViewModeType, StoryViewTargetType } from '../types/Stories'; import { StoryViewModeType, StoryViewTargetType } from '../types/Stories';
import { isValidE164 } from './isValidE164'; import { isValidE164 } from './isValidE164';
import { fromWebSafeBase64 } from './webSafeBase64'; import { fromWebSafeBase64 } from './webSafeBase64';
@ -121,6 +124,7 @@ export type IPCEventsCallbacksType = {
resetDefaultChatColor: () => void; resetDefaultChatColor: () => void;
setMediaPlaybackDisabled: (playbackDisabled: boolean) => void; setMediaPlaybackDisabled: (playbackDisabled: boolean) => void;
showConversationViaNotification: (data: NotificationClickData) => void; showConversationViaNotification: (data: NotificationClickData) => void;
showConversationViaToken: (token: string) => void;
showConversationViaSignalDotMe: ( showConversationViaSignalDotMe: (
kind: string, kind: string,
value: string value: string
@ -129,6 +133,7 @@ export type IPCEventsCallbacksType = {
showGroupViaLink: (value: string) => Promise<void>; showGroupViaLink: (value: string) => Promise<void>;
showReleaseNotes: () => void; showReleaseNotes: () => void;
showStickerPack: (packId: string, key: string) => void; showStickerPack: (packId: string, key: string) => void;
startCallingLobbyViaToken: (token: string) => void;
requestCloseConfirmation: () => Promise<boolean>; requestCloseConfirmation: () => Promise<boolean>;
getIsInCall: () => boolean; getIsInCall: () => boolean;
shutdown: () => Promise<void>; shutdown: () => Promise<void>;
@ -575,23 +580,31 @@ export function createIPCEvents(
messageId, messageId,
storyId, storyId,
}: NotificationClickData) { }: NotificationClickData) {
if (conversationId) { if (!conversationId) {
if (storyId) {
window.reduxActions.stories.viewStory({
storyId,
storyViewMode: StoryViewModeType.Single,
viewTarget: StoryViewTargetType.Replies,
});
} else {
window.reduxActions.conversations.showConversation({
conversationId,
messageId: messageId ?? undefined,
});
}
} else {
window.reduxActions.app.openInbox(); window.reduxActions.app.openInbox();
} else if (storyId) {
window.reduxActions.stories.viewStory({
storyId,
storyViewMode: StoryViewModeType.Single,
viewTarget: StoryViewTargetType.Replies,
});
} else {
window.reduxActions.conversations.showConversation({
conversationId,
messageId: messageId ?? undefined,
});
} }
}, },
showConversationViaToken(token: string) {
const data = notificationService.resolveToken(token);
if (!data) {
window.reduxActions.app.openInbox();
} else {
window.Events.showConversationViaNotification(data);
}
},
async showConversationViaSignalDotMe(kind: string, value: string) { async showConversationViaSignalDotMe(kind: string, value: string) {
if (!Registration.everDone()) { if (!Registration.everDone()) {
log.info( log.info(
@ -638,6 +651,17 @@ export function createIPCEvents(
showUnknownSgnlLinkModal(); showUnknownSgnlLinkModal();
}, },
startCallingLobbyViaToken(token: string) {
const data = notificationService.resolveToken(token);
if (!data) {
return;
}
window.reduxActions?.calling?.startCallingLobby({
conversationId: data.conversationId,
isVideoCall: true,
});
},
requestCloseConfirmation: async (): Promise<boolean> => { requestCloseConfirmation: async (): Promise<boolean> => {
try { try {
await new Promise<void>((resolve, reject) => { await new Promise<void>((resolve, reject) => {

View file

@ -201,7 +201,6 @@ function _route<Key extends string, Args extends object>(
} }
const paramSchema = z.string().min(1); const paramSchema = z.string().min(1);
const optionalParamSchema = paramSchema.nullish().default(null);
/** /**
* signal.me by phone number * signal.me by phone number
@ -452,11 +451,9 @@ export const artAddStickersRoute = _route('artAddStickers', {
* @example * @example
* ```ts * ```ts
* showConversationRoute.toAppUrl({ * showConversationRoute.toAppUrl({
* conversationId: "123", * token: 'abc',
* messageId: "abc",
* storyId: "def",
* }) * })
* // URL { "sgnl://show-conversation?conversationId=123&messageId=abc&storyId=def" } * // URL { "sgnl://show-conversation?token=abc" }
* ``` * ```
*/ */
export const showConversationRoute = _route('showConversation', { export const showConversationRoute = _route('showConversation', {
@ -464,28 +461,16 @@ export const showConversationRoute = _route('showConversation', {
_pattern('sgnl:', 'show-conversation', '{/}?', { search: ':params' }), _pattern('sgnl:', 'show-conversation', '{/}?', { search: ':params' }),
], ],
schema: z.object({ schema: z.object({
conversationId: paramSchema, token: paramSchema,
messageId: optionalParamSchema,
storyId: optionalParamSchema,
}), }),
parse(result) { parse(result) {
const params = new URLSearchParams(result.search.groups.params); const params = new URLSearchParams(result.search.groups.params);
return { return {
conversationId: params.get('conversationId'), token: params.get('token'),
messageId: params.get('messageId'),
storyId: params.get('storyId'),
}; };
}, },
toAppUrl(args) { toAppUrl(args) {
const params = new URLSearchParams({ const params = new URLSearchParams({ token: args.token });
conversationId: args.conversationId,
});
if (args.messageId != null) {
params.set('messageId', args.messageId);
}
if (args.storyId != null) {
params.set('storyId', args.storyId);
}
return new URL(`sgnl://show-conversation?${params.toString()}`); return new URL(`sgnl://show-conversation?${params.toString()}`);
}, },
}); });
@ -495,9 +480,9 @@ export const showConversationRoute = _route('showConversation', {
* @example * @example
* ```ts * ```ts
* startCallLobbyRoute.toAppUrl({ * startCallLobbyRoute.toAppUrl({
* conversationId: "123", * token: "123",
* }) * })
* // URL { "sgnl://start-call-lobby?conversationId=123" } * // URL { "sgnl://start-call-lobby?token=123" }
* ``` * ```
*/ */
export const startCallLobbyRoute = _route('startCallLobby', { export const startCallLobbyRoute = _route('startCallLobby', {
@ -505,18 +490,16 @@ export const startCallLobbyRoute = _route('startCallLobby', {
_pattern('sgnl:', 'start-call-lobby', '{/}?', { search: ':params' }), _pattern('sgnl:', 'start-call-lobby', '{/}?', { search: ':params' }),
], ],
schema: z.object({ schema: z.object({
conversationId: paramSchema, token: paramSchema,
}), }),
parse(result) { parse(result) {
const params = new URLSearchParams(result.search.groups.params); const params = new URLSearchParams(result.search.groups.params);
return { return {
conversationId: params.get('conversationId'), token: params.get('token'),
}; };
}, },
toAppUrl(args) { toAppUrl(args) {
const params = new URLSearchParams({ const params = new URLSearchParams({ token: args.token });
conversationId: args.conversationId,
});
return new URL(`sgnl://start-call-lobby?${params.toString()}`); return new URL(`sgnl://start-call-lobby?${params.toString()}`);
}, },
}); });

View file

@ -18,10 +18,7 @@ import * as Errors from '../../types/errors';
import { strictAssert } from '../../util/assert'; import { strictAssert } from '../../util/assert';
import { drop } from '../../util/drop'; import { drop } from '../../util/drop';
import { DataReader } from '../../sql/Client'; import { DataReader } from '../../sql/Client';
import type { import type { WindowsNotificationData } from '../../services/notifications';
NotificationClickData,
WindowsNotificationData,
} from '../../services/notifications';
import { AggregatedStats } from '../../textsecure/WebsocketResources'; import { AggregatedStats } from '../../textsecure/WebsocketResources';
import { UNAUTHENTICATED_CHANNEL_NAME } from '../../textsecure/SocketManager'; import { UNAUTHENTICATED_CHANNEL_NAME } from '../../textsecure/SocketManager';
@ -340,12 +337,9 @@ ipc.on('show-group-via-link', (_event, info) => {
drop(window.Events.showGroupViaLink?.(info.value)); drop(window.Events.showGroupViaLink?.(info.value));
}); });
ipc.on('start-call-lobby', (_event, { conversationId }) => { ipc.on('start-call-lobby', (_event, info) => {
window.IPC.showWindow(); window.IPC.showWindow();
window.reduxActions?.calling?.startCallingLobby({ window.Events.startCallingLobbyViaToken(info.token);
conversationId,
isVideoCall: true,
});
}); });
ipc.on('start-call-link', (_event, { key }) => { ipc.on('start-call-link', (_event, { key }) => {
@ -362,15 +356,12 @@ ipc.on('cancel-presenting', () => {
window.reduxActions?.calling?.cancelPresenting(); window.reduxActions?.calling?.cancelPresenting();
}); });
ipc.on( ipc.on('show-conversation-via-token', (_event, token: string) => {
'show-conversation-via-notification', const { showConversationViaToken } = window.Events;
(_event, data: NotificationClickData) => { if (showConversationViaToken) {
const { showConversationViaNotification } = window.Events; void showConversationViaToken(token);
if (showConversationViaNotification) {
void showConversationViaNotification(data);
}
} }
); });
ipc.on('show-conversation-via-signal.me', (_event, info) => { ipc.on('show-conversation-via-signal.me', (_event, info) => {
const { kind, value } = info; const { kind, value } = info;
strictAssert(typeof kind === 'string', 'Got an invalid kind over IPC'); strictAssert(typeof kind === 'string', 'Got an invalid kind over IPC');