Skip to content

Commit 784bed0

Browse files
authored
Merge pull request #223 from httpsphl/feat/mobile-chats
feat(mobile): chats on the phone, PIN lock and release 0.14.0
2 parents 9dc848d + c445e43 commit 784bed0

69 files changed

Lines changed: 5270 additions & 343 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎Cargo.lock‎

Lines changed: 6 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎Cargo.toml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ members = ["crates/botloft-core", "crates/botloft-store", "crates/botloft-cloud"
44
default-members = ["crates/botloft-core", "crates/botloft-store", "crates/botloft-cloud", "crates/botloftd"]
55

66
[workspace.package]
7-
version = "0.13.0"
7+
version = "0.14.0"
88
edition = "2024"
99
license = "FSL-1.1-ALv2"
1010
repository = "https://github.com/httpsphl/botloft"

‎app/package.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "botloft-app",
33
"private": true,
4-
"version": "0.13.0",
4+
"version": "0.14.0",
55
"license": "FSL-1.1-ALv2",
66
"type": "module",
77
"packageManager": "pnpm@12.4.1",

‎app/src/features/account/AccountArea.tsx‎

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import { useApp, useHost } from "../../store/context";
1818
import { POPOVER, POPOVER_ITEM } from "../../ui/surface";
1919
import { attempt } from "../../ui/toast";
2020
import { useDismiss } from "../../ui/useDismiss";
21-
import { SettingsDialog } from "./SettingsDialog";
2221
import { UsageDialog } from "./UsageDialog";
2322

2423
const RELEASES = "https://github.com/httpsphl/botloft/releases";
@@ -35,7 +34,8 @@ export function AccountArea() {
3534
const account = useApp((state) => state.system?.account ?? null);
3635
const signedOut = useApp((state) => state.system?.claudeSignedIn === false);
3736
const [open, setOpen] = useState(false);
38-
const [dialog, setDialog] = useState<"usage" | "settings" | null>(null);
37+
const [dialog, setDialog] = useState<"usage" | null>(null);
38+
const openPage = useApp((state) => state.openPage);
3939
const root = useRef<HTMLDivElement>(null);
4040

4141
useDismiss(
@@ -48,7 +48,11 @@ export function AccountArea() {
4848
const detail = describe(account?.claude ?? null, signedOut, a);
4949
const show = (which: "usage" | "settings") => {
5050
setOpen(false);
51-
setDialog(which);
51+
if (which === "settings") {
52+
openPage("settings");
53+
} else {
54+
setDialog(which);
55+
}
5256
};
5357

5458
return (
@@ -79,7 +83,6 @@ export function AccountArea() {
7983
</span>
8084
</button>
8185
{dialog === "usage" && <UsageDialog onClose={() => setDialog(null)} />}
82-
{dialog === "settings" && <SettingsDialog onClose={() => setDialog(null)} />}
8386
</div>
8487
);
8588
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Settings, "Account and phone": the account that keeps the copies and
2+
// connects the phone (spec 27.6), and the phones connected to it (spec 28.7).
3+
4+
import { useT } from "../../i18n";
5+
import { CloudAccount } from "./CloudAccount";
6+
import { MobilePhones } from "./MobilePhones";
7+
import { Section } from "./settingsParts";
8+
9+
export function AccountSettings() {
10+
const cloud = useT().account.cloud;
11+
return (
12+
<>
13+
<Section title={cloud.title}>
14+
<CloudAccount />
15+
</Section>
16+
<MobilePhones />
17+
</>
18+
);
19+
}

‎app/src/features/account/BackupSettings.tsx‎

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,17 @@ import { Button } from "../../ui/Button";
1212
import { Callout } from "../../ui/Callout";
1313
import { BackupRestore } from "./BackupRestore";
1414
import { backupError } from "./backupError";
15-
import { CloudAccount } from "./CloudAccount";
16-
import { MobilePhones } from "./MobilePhones";
15+
import { CloudBackup } from "./CloudBackup";
1716
import { PassphraseFields, usePassphrase } from "./PassphraseFields";
1817
import { Section } from "./settingsParts";
1918

2019
type Outcome = { saved: string } | { notSaved: true } | { failed: string } | null;
2120

22-
export function BackupSettings() {
21+
export function BackupSettings({ goToAccount }: { goToAccount(): void }) {
2322
const b = useT().account.backup;
24-
const cloud = useT().account.cloud;
2523
return (
2624
<>
27-
<Section title={cloud.title}>
28-
<CloudAccount />
29-
</Section>
30-
<MobilePhones />
25+
<CloudBackup goToAccount={goToAccount} />
3126
<Section title={b.exportTitle}>
3227
<p className="text-ink-soft text-sm leading-relaxed">{b.exportIntro}</p>
3328
<ExportCopy />
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Settings, "Backup": the copies in the cloud (spec 27): send one, keep them
2+
// up to date by themselves, bring one back. They need the account, which
3+
// is in "Account and phone".
4+
5+
import { useState } from "react";
6+
import { useT } from "../../i18n";
7+
import { Button } from "../../ui/Button";
8+
import { CloudAuto } from "./CloudAuto";
9+
import { CloudCopies } from "./CloudCopies";
10+
import { CloudUpload } from "./CloudUpload";
11+
import { Section } from "./settingsParts";
12+
import { useCloud } from "./useCloud";
13+
14+
export function CloudBackup({ goToAccount }: { goToAccount(): void }) {
15+
const s = useT().account.settings;
16+
const { status, refresh } = useCloud();
17+
const [version, setVersion] = useState(0);
18+
// No cloud set up in this Botloft: the Account page says so.
19+
if (!status?.url) {
20+
return null;
21+
}
22+
return (
23+
<Section title={s.copiesTitle}>
24+
{status.signedIn ? (
25+
<>
26+
<CloudUpload
27+
onSent={() => {
28+
setVersion((current) => current + 1);
29+
void refresh();
30+
}}
31+
/>
32+
<CloudAuto />
33+
<CloudCopies version={version} onChanged={refresh} />
34+
</>
35+
) : (
36+
<>
37+
<p className="text-ink-soft text-sm">{s.backupNeedsAccount}</p>
38+
<Button className="self-start" onClick={goToAccount}>
39+
{s.goToAccount}
40+
</Button>
41+
</>
42+
)}
43+
</Section>
44+
);
45+
}

‎app/src/features/account/CloudSignedIn.tsx‎

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// The account when this computer is in (spec 27.6): who, how much is used,
2-
// the copies, and the way out.
2+
// and the way out. The copies are in Backup (CloudBackup.tsx).
33

44
import { useState } from "react";
55
import { useT } from "../../i18n";
@@ -10,9 +10,6 @@ import { Button } from "../../ui/Button";
1010
import { Callout } from "../../ui/Callout";
1111
import { Confirm } from "../../ui/Confirm";
1212
import { backupError } from "./backupError";
13-
import { CloudAuto } from "./CloudAuto";
14-
import { CloudCopies } from "./CloudCopies";
15-
import { CloudUpload } from "./CloudUpload";
1613

1714
export function CloudSignedIn({
1815
status,
@@ -23,7 +20,6 @@ export function CloudSignedIn({
2320
}) {
2421
const t = useT().account.cloud;
2522
const api = useApi();
26-
const [version, setVersion] = useState(0);
2723
const [removing, setRemoving] = useState(false);
2824
const [asked, setAsked] = useState(false);
2925
const [problem, setProblem] = useState<string | null>(null);
@@ -59,15 +55,6 @@ export function CloudSignedIn({
5955
</Button>
6056
</div>
6157

62-
<CloudUpload
63-
onSent={() => {
64-
setVersion((current) => current + 1);
65-
void refresh();
66-
}}
67-
/>
68-
<CloudAuto />
69-
<CloudCopies version={version} onChanged={refresh} />
70-
7158
<div className="flex flex-col gap-2 border-line border-t pt-3">
7259
{asked ? (
7360
<p role="status" className="text-ink-soft text-sm">

‎app/src/features/account/SettingsDialog.tsx‎

Lines changed: 0 additions & 103 deletions
This file was deleted.

0 commit comments

Comments
 (0)