+ {pending.joined ? (
+ <>
+
{m.wants(pending.joined.name)}
+
{spaced(pending.joined.code)}
+
{m.compare(spaced(pending.joined.code))}
+
+
+
+
+ >
+ ) : (
+ <>
+ {started &&
}
+
{m.scan}
+
{m.expires(clock(left))}
+
+ >
+ )}
+ {problem && (
+
+ {problem}
+
+ )}
+
+ );
+}
diff --git a/app/src/features/account/MobilePhones.tsx b/app/src/features/account/MobilePhones.tsx
new file mode 100644
index 00000000..423a7967
--- /dev/null
+++ b/app/src/features/account/MobilePhones.tsx
@@ -0,0 +1,32 @@
+// Settings, "Backup", the phone block (spec 28.7): connect a phone by showing
+// a code for it to scan, compare the two codes, and cut a phone off.
+
+import { Smartphone } from "lucide-react";
+import { useT } from "../../i18n";
+import { MobileSignedIn } from "./MobileSignedIn";
+import { Section } from "./settingsParts";
+import { useCloud } from "./useCloud";
+import { useMobile } from "./useMobile";
+
+export function MobilePhones() {
+ const m = useT().account.mobile;
+ const { status: cloud } = useCloud();
+ const { status, refresh } = useMobile();
+ // No cloud set up, nothing to connect a phone to.
+ if (!cloud?.url) {
+ return null;
+ }
+ return (
+