Page MenuHomePhabricator

D8934.diff
No OneTemporary

D8934.diff

diff --git a/keyserver/.well-known/apple-app-site-association b/keyserver/.well-known/apple-app-site-association
--- a/keyserver/.well-known/apple-app-site-association
+++ b/keyserver/.well-known/apple-app-site-association
@@ -10,12 +10,15 @@
"components": [
{
"/": "/invite/*"
+ },
+ {
+ "/": "/qr-code/*"
}
]
},
{
"appID": "H98Y8MH53M.app.comm",
- "paths": [ "/invite/*" ]
+ "paths": [ "/invite/*", "/qr-code/*" ]
}
]
}
diff --git a/lib/facts/links.js b/lib/facts/links.js
--- a/lib/facts/links.js
+++ b/lib/facts/links.js
@@ -4,4 +4,19 @@
return `https://comm.app/invite/${secret}`;
}
-export { inviteLinkUrl };
+function qrCodeLinkUrl(aes256Param: string, ed25519Param: string): string {
+ const keys = {
+ aes256: aes256Param,
+ ed25519: ed25519Param,
+ };
+ const keysString = encodeURIComponent(JSON.stringify(keys));
+ return `comm://qr-code/${keysString}`;
+}
+
+function parseKeysFromQRCodeURL(url: string): ?string {
+ const urlRegex = /qr-code\/(\S+)$/;
+ const match = urlRegex.exec(url);
+ return match?.[1];
+}
+
+export { inviteLinkUrl, qrCodeLinkUrl, parseKeysFromQRCodeURL };
diff --git a/native/android/app/src/main/AndroidManifest.xml b/native/android/app/src/main/AndroidManifest.xml
--- a/native/android/app/src/main/AndroidManifest.xml
+++ b/native/android/app/src/main/AndroidManifest.xml
@@ -68,6 +68,11 @@
android:host="comm.app"
android:pathPrefix="/invite"
/>
+ <data
+ android:scheme="https"
+ android:host="comm.app"
+ android:pathPrefix="/qr-code"
+ />
</intent-filter>
</activity>
<activity
diff --git a/native/navigation/navigation-handler.react.js b/native/navigation/navigation-handler.react.js
--- a/native/navigation/navigation-handler.react.js
+++ b/native/navigation/navigation-handler.react.js
@@ -11,6 +11,7 @@
import { useIsAppLoggedIn } from './nav-selectors.js';
import { NavContext, type NavAction } from './navigation-context.js';
import PolicyAcknowledgmentHandler from './policy-acknowledgment-handler.react.js';
+import QRCodeLinkHandler from './qr-code-link-handler.react.js';
import ThreadScreenTracker from './thread-screen-tracker.react.js';
import DevTools from '../redux/dev-tools.react.js';
import { useSelector } from '../redux/redux-utils.js';
@@ -43,6 +44,7 @@
<ThreadScreenTracker />
<ModalPruner navContext={navContext} />
<PolicyAcknowledgmentHandler />
+ <QRCodeLinkHandler />
{devTools}
</>
);
diff --git a/native/navigation/qr-code-link-handler.react.js b/native/navigation/qr-code-link-handler.react.js
new file mode 100644
--- /dev/null
+++ b/native/navigation/qr-code-link-handler.react.js
@@ -0,0 +1,51 @@
+// @flow
+
+import { useNavigation } from '@react-navigation/native';
+import * as React from 'react';
+import { Linking } from 'react-native';
+
+import { parseKeysFromQRCodeURL } from 'lib/facts/links.js';
+import { isLoggedIn } from 'lib/selectors/user-selectors.js';
+
+import { SecondaryDeviceQRCodeScannerRouteName } from './route-names.js';
+import { useSelector } from '../redux/redux-utils.js';
+
+function QRCodeLinkHandler(): null {
+ const [currentLink, setCurrentLink] = React.useState(null);
+
+ React.useEffect(() => {
+ const subscription = Linking.addEventListener('url', ({ url }) =>
+ setCurrentLink(url),
+ );
+ (async () => {
+ const initialURL = await Linking.getInitialURL();
+ if (initialURL) {
+ setCurrentLink(initialURL);
+ }
+ })();
+
+ return () => subscription.remove();
+ }, []);
+
+ const loggedIn = useSelector(isLoggedIn);
+ const { navigate } = useNavigation();
+
+ React.useEffect(() => {
+ if (!loggedIn || !currentLink) {
+ return;
+ }
+
+ setCurrentLink(null);
+
+ const keys = parseKeysFromQRCodeURL(currentLink);
+ if (!keys) {
+ return;
+ }
+
+ navigate(SecondaryDeviceQRCodeScannerRouteName);
+ }, [currentLink, loggedIn, navigate]);
+
+ return null;
+}
+
+export default QRCodeLinkHandler;
diff --git a/native/profile/secondary-device-qr-code-scanner.react.js b/native/profile/secondary-device-qr-code-scanner.react.js
--- a/native/profile/secondary-device-qr-code-scanner.react.js
+++ b/native/profile/secondary-device-qr-code-scanner.react.js
@@ -5,6 +5,8 @@
import * as React from 'react';
import { View } from 'react-native';
+import { parseKeysFromQRCodeURL } from 'lib/facts/links.js';
+
import { useStyles } from '../themes/colors.js';
import Alert from '../utils/alert.js';
@@ -36,10 +38,23 @@
}, [navigation]);
const onConnect = React.useCallback((barCodeEvent: BarCodeEvent) => {
- const { type, data } = barCodeEvent;
+ const { data } = barCodeEvent;
+ const keysMatch = parseKeysFromQRCodeURL(data);
+
+ if (!keysMatch) {
+ Alert.alert(
+ 'Scan failed',
+ 'QR code does not contain a valid pair of keys.',
+ [{ text: 'OK' }],
+ );
+ return;
+ }
+
+ const keys = JSON.parse(decodeURIComponent(keysMatch));
+
Alert.alert(
'Scan successful',
- `Bar code with type ${type} and data ${data} has been scanned!`,
+ `QR code contains the following keys: ${JSON.stringify(keys)}`,
[{ text: 'OK' }],
);
}, []);
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
@@ -4,6 +4,8 @@
import { View, Text } from 'react-native';
import QRCode from 'react-native-qrcode-svg';
+import { qrCodeLinkUrl } from 'lib/facts/links.js';
+
import type { QRCodeSignInNavigationProp } from './qr-code-sign-in-navigator.react.js';
import type { NavigationRoute } from '../navigation/route-names.js';
import { useStyles } from '../themes/colors.js';
@@ -13,6 +15,8 @@
+route: NavigationRoute<'QRCodeScreen'>,
};
+const qrCodeValue = qrCodeLinkUrl('random_aes256_key', 'device_ed25519_key');
+
// eslint-disable-next-line no-unused-vars
function QRCodeScreen(props: QRCodeScreenProps): React.Node {
const styles = useStyles(unboundStyles);
@@ -22,7 +26,7 @@
<Text style={styles.headingSubtext}>
Open the Comm app on your phone and scan the QR code below
</Text>
- <QRCode value="https://www.google.com" size={200} />
+ <QRCode value={qrCodeValue} size={200} />
<View style={styles.instructionsBox}>
<Text style={styles.instructionsTitle}>How to find the scanner:</Text>
<Text style={styles.instructionsStep}>
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
@@ -3,8 +3,12 @@
import { QRCodeSVG } from 'qrcode.react';
import * as React from 'react';
+import { qrCodeLinkUrl } from 'lib/facts/links.js';
+
import css from './qr-code-login.css';
+const qrCodeValue = qrCodeLinkUrl('random_aes256_key', 'device_ed25519_key');
+
function QrCodeLogin(): React.Node {
return (
<div className={css.qrContainer}>
@@ -12,12 +16,7 @@
<div className={css.scanInstructions}>
Open the Comm app on your phone and scan the QR code below
</div>
- <QRCodeSVG
- value="https://comm.app/"
- size={300}
- marginSize={4}
- level="L"
- />
+ <QRCodeSVG value={qrCodeValue} size={300} marginSize={4} level="L" />
<div className={css.instructionsContainer}>
<div className={css.instructionsTitle}>How to find the scanner:</div>
<div className={css.instructionsStep}>

File Metadata

Mime Type
text/plain
Expires
Mon, Dec 23, 8:15 AM (18 h, 18 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2694104
Default Alt Text
D8934.diff (7 KB)

Event Timeline