// Copyright 2022 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only import React from 'react'; import { renderToStaticMarkup } from 'react-dom/server'; import type { WindowsNotificationData } from '../ts/services/notifications'; import { NotificationType } from '../ts/services/notifications'; import { missingCaseError } from '../ts/util/missingCaseError'; function pathToUri(path: string) { return `file:///${encodeURI(path.replace(/\\/g, '/'))}`; } const Toast = (props: { launch: string; // Note: though React doesn't like it, Windows seems to require that this be camelcase activationType: string; children: React.ReactNode; }) => React.createElement('toast', props); const Visual = (props: { children: React.ReactNode }) => React.createElement('visual', props); const Binding = (props: { template: string; children: React.ReactNode }) => React.createElement('binding', props); const Text = (props: { id: string; children: React.ReactNode }) => React.createElement('text', props); const Image = (props: { id: string; src: string; 'hint-crop': string }) => React.createElement('image', props); export function renderWindowsToast({ avatarPath, body, conversationId, heading, messageId, storyId, type, }: WindowsNotificationData): string { // Note: with these templates, the first is one line, bolded // https://learn.microsoft.com/en-us/previous-versions/windows/apps/hh761494(v=win.10)?redirectedfrom=MSDN#toastimageandtext02 // https://learn.microsoft.com/en-us/previous-versions/windows/apps/hh761494(v=win.10)?redirectedfrom=MSDN#toasttext02 const image = avatarPath ? ( ) : null; const template = avatarPath ? 'ToastImageAndText02' : 'ToastText02'; let launch: URL; // Note: // 1) this maps to the notify() function in services/notifications.ts // 2) this also maps to the url-handling in main.ts if (type === NotificationType.Message || type === NotificationType.Reaction) { launch = new URL('sgnl://show-conversation'); launch.searchParams.set('conversationId', conversationId); if (messageId) { launch.searchParams.set('messageId', messageId); } if (storyId) { launch.searchParams.set('storyId', storyId); } } else if (type === NotificationType.IncomingGroupCall) { launch = new URL(`sgnl://start-call-lobby`); launch.searchParams.set('conversationId', conversationId); } else if (type === NotificationType.IncomingCall) { launch = new URL('sgnl://show-window'); } else if (type === NotificationType.IsPresenting) { launch = new URL('sgnl://set-is-presenting'); } else { throw missingCaseError(type); } return renderToStaticMarkup( {image} {heading} {body} ); }