Page MenuHomePhorge

D8934.1765089106.diff
No OneTemporary

Size
8 KB
Referenced Files
None
Subscribers
None

D8934.1765089106.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
@@ -1,7 +1,23 @@
// @flow
+const inviteLinkUrlPrefix = 'https://comm.app/invite/';
function inviteLinkUrl(secret: string): string {
- return `https://comm.app/invite/${secret}`;
+ return `${inviteLinkUrlPrefix}${secret}`;
}
-export { inviteLinkUrl };
+const qrCodeLinkUrlPrefix = 'comm://qr-code/';
+function qrCodeLinkUrl(aes256Param: string, ed25519Param: string): string {
+ const keys = {
+ aes256: aes256Param,
+ ed25519: ed25519Param,
+ };
+ const keysString = encodeURIComponent(JSON.stringify(keys));
+ return `${qrCodeLinkUrlPrefix}${keysString}`;
+}
+
+export {
+ inviteLinkUrlPrefix,
+ inviteLinkUrl,
+ qrCodeLinkUrlPrefix,
+ qrCodeLinkUrl,
+};
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/invite-links/invite-links-context-provider.react.js b/native/invite-links/invite-links-context-provider.react.js
--- a/native/invite-links/invite-links-context-provider.react.js
+++ b/native/invite-links/invite-links-context-provider.react.js
@@ -9,6 +9,7 @@
verifyInviteLink,
verifyInviteLinkActionTypes,
} from 'lib/actions/link-actions.js';
+import { inviteLinkUrlPrefix } from 'lib/facts/links.js';
import { isLoggedIn } from 'lib/selectors/user-selectors.js';
import type { SetState } from 'lib/types/hook-types.js';
import {
@@ -78,9 +79,13 @@
const dispatchActionPromise = useDispatchActionPromise();
const validateLink = useServerCall(verifyInviteLink);
const navigation = useNavigation();
+ const isCurrentLinkInviteLink = React.useMemo(
+ () => currentLink?.startsWith(inviteLinkUrlPrefix),
+ [currentLink],
+ );
React.useEffect(() => {
(async () => {
- if (!loggedIn || !currentLink) {
+ if (!loggedIn || !currentLink || !isCurrentLinkInviteLink) {
return;
}
// We're setting this to null so that we ensure that each link click
@@ -107,7 +112,14 @@
},
});
})();
- }, [currentLink, dispatchActionPromise, loggedIn, navigation, validateLink]);
+ }, [
+ currentLink,
+ dispatchActionPromise,
+ loggedIn,
+ isCurrentLinkInviteLink,
+ navigation,
+ validateLink,
+ ]);
const contextValue = React.useMemo(
() => ({
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,50 @@
+// @flow
+
+import { useNavigation } from '@react-navigation/native';
+import * as React from 'react';
+import { Linking } from 'react-native';
+
+import { qrCodeLinkUrlPrefix } 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();
+ const isQRCodeLink = React.useMemo(
+ () => currentLink?.startsWith(qrCodeLinkUrlPrefix),
+ [currentLink],
+ );
+
+ React.useEffect(() => {
+ if (!loggedIn || !currentLink || !isQRCodeLink) {
+ return;
+ }
+
+ setCurrentLink(null);
+
+ navigate(SecondaryDeviceQRCodeScannerRouteName);
+ }, [currentLink, loggedIn, isQRCodeLink, 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
@@ -36,10 +36,14 @@
}, [navigation]);
const onConnect = React.useCallback((barCodeEvent: BarCodeEvent) => {
- const { type, data } = barCodeEvent;
+ const { data } = barCodeEvent;
+ const extractKeysFromURLRegex = /comm:\/\/qr-code\/(.*)/;
+ const keysMatch = data.match(extractKeysFromURLRegex)?.[1] ?? '';
+ 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
Sun, Dec 7, 6:31 AM (12 h, 56 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5842889
Default Alt Text
D8934.1765089106.diff (8 KB)

Event Timeline