diff --git a/keyserver/src/keyserver.js b/keyserver/src/keyserver.js --- a/keyserver/src/keyserver.js +++ b/keyserver/src/keyserver.js @@ -112,7 +112,7 @@ console.log( '\nOpen the Comm app on your phone and scan the QR code below, or copy and paste this URL:\n', ); - const url = qrCodeLinkURL(aes256Key, ed25519Key); + const url = qrCodeLinkURL(aes256Key, ed25519Key, 'KEYSERVER'); console.log(url, '\n'); console.log('How to find the scanner:\n'); console.log('Go to \x1b[1mProfile\x1b[0m'); diff --git a/lib/facts/links.js b/lib/facts/links.js --- a/lib/facts/links.js +++ b/lib/facts/links.js @@ -1,7 +1,10 @@ // @flow +import { identityDeviceTypes } from '../types/identity-service-types.js'; import { isDev } from '../utils/dev-utils.js'; +type DeviceType = $Keys; + /* Invite Links */ function inviteLinkURL(secret: string): string { if (isDev) { @@ -11,13 +14,18 @@ } /* QR Code */ -function qrCodeLinkURL(aes256Param: string, ed25519Param: string): string { +function qrCodeLinkURL( + aes256Param: string, + ed25519Param: string, + deviceType: DeviceType, +): string { + const deviceTypeLower = deviceType.toLowerCase(); const keys = { aes256: aes256Param, ed25519: ed25519Param, }; const keysString = encodeURIComponent(JSON.stringify(keys)); - return `comm://qr-code/${keysString}`; + return `comm://qr-code/${deviceTypeLower}/${keysString}`; } /* Deep Link Utils */ @@ -33,13 +41,13 @@ }; type ParsedQRCodeData = { +type: 'qr-code', - +data: { +keys: string }, + +data: { +keys: string, +deviceType?: string }, }; export type ParsedDeepLinkData = ParsedInviteLinkData | ParsedQRCodeData | null; function parseDataFromDeepLink(url: string): ParsedDeepLinkData { const inviteLinkSecretRegex = /invite\/(\S+)$/; - const qrCodeKeysRegex = /qr-code\/(\S+)$/; + const qrCodeKeysRegex = /qr-code\/(?:([^/]+)\/)?(\S+)$/; const inviteLinkSecretMatch = inviteLinkSecretRegex.exec(url); if (inviteLinkSecretMatch) { @@ -51,9 +59,10 @@ const qrCodeKeysMatch = qrCodeKeysRegex.exec(url); if (qrCodeKeysMatch) { + const [, deviceType, keys] = qrCodeKeysMatch; return { type: 'qr-code', - data: { keys: qrCodeKeysMatch[1] }, + data: { keys, ...(deviceType ? { deviceType } : {}) }, }; } diff --git a/native/qr-code/qr-code-screen.react.js b/native/qr-code/qr-code-screen.react.js --- a/native/qr-code/qr-code-screen.react.js +++ b/native/qr-code/qr-code-screen.react.js @@ -1,7 +1,7 @@ // @flow import * as React from 'react'; -import { View, Text } from 'react-native'; +import { View, Text, Platform } from 'react-native'; import QRCode from 'react-native-qrcode-svg'; import { useQRAuthContext } from 'lib/components/qr-auth-provider.react.js'; @@ -24,10 +24,14 @@ void generateQRCode(); }, [generateQRCode]); - const qrCodeURL = React.useMemo( - () => (qrData ? qrCodeLinkURL(qrData.aesKey, qrData.deviceID) : undefined), - [qrData], - ); + const qrCodeURL = React.useMemo(() => { + if (!qrData) { + return undefined; + } + + const deviceType = Platform.OS === 'android' ? 'ANDROID' : 'IOS'; + return qrCodeLinkURL(qrData.aesKey, qrData.deviceID, deviceType); + }, [qrData]); const styles = useStyles(unboundStyles); return ( diff --git a/web/account/qr-code-login.react.js b/web/account/qr-code-login.react.js --- a/web/account/qr-code-login.react.js +++ b/web/account/qr-code-login.react.js @@ -5,20 +5,45 @@ import { useQRAuthContext } from 'lib/components/qr-auth-provider.react.js'; import { qrCodeLinkURL } from 'lib/facts/links.js'; +import { getConfig } from 'lib/utils/config.js'; import css from './qr-code-login.css'; function QRCodeLogin(): React.Node { const { qrData, generateQRCode } = useQRAuthContext(); + const platform = getConfig().platformDetails.platform; React.useEffect(() => { void generateQRCode(); }, [generateQRCode]); - const qrCodeURL = React.useMemo( - () => (qrData ? qrCodeLinkURL(qrData.aesKey, qrData.deviceID) : undefined), - [qrData], - ); + const qrCodeURL = React.useMemo(() => { + if (!qrData) { + return undefined; + } + + let webPlatform; + switch (platform) { + case 'web': + webPlatform = 'WEB'; + break; + case 'macos': + webPlatform = 'MAC_OS'; + break; + case 'windows': + webPlatform = 'WINDOWS'; + break; + default: + webPlatform = undefined; + break; + } + + if (!webPlatform) { + return undefined; + } + + return qrCodeLinkURL(qrData.aesKey, qrData.deviceID, webPlatform); + }, [platform, qrData]); return (