feat(frontend): relay discoverability toggle, sign-up disclosure, offline badge

- setRelayDiscoverable IPC wrapper in tauri.ts
- relay_discoverable in defaultSettings + toggleRelayDiscoverable function
- Privacy settings: discoverable on relay toggle
- Sign-up: disclosure text about relay username storage
- User directory: WifiOff badge for relay-only (offline) peers
- Improved empty state hint text

Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
This commit is contained in:
cloudwithax 2026-02-19 12:42:09 -05:00
parent 72a82c1a11
commit ef6114a751
5 changed files with 42 additions and 2 deletions

View File

@ -167,6 +167,11 @@ const SignUpScreen: Component<SignUpScreenProps> = (props) => {
an ed25519 keypair will be generated and stored locally on your
device
</p>
<p class="text-[11px] font-mono text-white/30 text-center mt-2 leading-relaxed">
your username will be stored on the relay server so others can
find you even when you're offline.{" "}
<span class="text-white/40">you can turn this off in settings.</span>
</p>
</div>
</Match>
</Switch>

View File

@ -16,6 +16,7 @@ import {
Users,
Copy,
Check,
WifiOff,
} from "lucide-solid";
import Avatar from "../common/Avatar";
import Button from "../common/Button";
@ -263,7 +264,9 @@ const UserDirectoryModal: Component<UserDirectoryModalProps> = (props) => {
<p class="text-[14px] text-white/20">
{activeTab() === "friends"
? "add friends from the all peers tab"
: "peers will appear as you join communities"}
: searchQuery().trim().length > 0
? "try searching by peer id or check your relay connection"
: "peers will appear as you join communities or search by name"}
</p>
</div>
}
@ -283,6 +286,12 @@ const UserDirectoryModal: Component<UserDirectoryModalProps> = (props) => {
friend
</span>
</Show>
<Show when={!peer.public_key}>
<span class="flex items-center gap-1 text-[10px] font-mono uppercase tracking-[0.05em] text-white/30 px-1.5 py-0.5 border border-white/10 shrink-0">
<WifiOff size={8} />
offline
</span>
</Show>
</div>
<Show when={peer.bio}>
<p class="text-[13px] text-white/40 truncate">

View File

@ -21,11 +21,12 @@ import {
toggleMessagePreview,
toggleShowOnlineStatus,
toggleAllowDMsFromAnyone,
toggleRelayDiscoverable,
setMessageDisplay,
setFontSize,
} from "../../stores/settings";
import { identity, updateIdentity } from "../../stores/identity";
import { updateProfile } from "../../lib/tauri";
import { updateProfile, setRelayDiscoverable } from "../../lib/tauri";
import type { UserStatus } from "../../lib/types";
import Avatar from "../common/Avatar";
import Button from "../common/Button";
@ -378,6 +379,19 @@ const PrivacySection: Component<{
checked={current().allow_dms_from_anyone}
onChange={toggleAllowDMsFromAnyone}
/>
<ToggleRow
label="discoverable on relay"
description="lets others find you by username even when you're offline. turning this off removes your profile from the relay index."
checked={current().relay_discoverable ?? true}
onChange={async () => {
toggleRelayDiscoverable();
try {
await setRelayDiscoverable(!current().relay_discoverable);
} catch (e) {
console.error("failed to set relay discoverable:", e);
}
}}
/>
{/* danger zone */}
<div class="mt-8 pt-6 border-t border-red-500/20">

View File

@ -296,6 +296,10 @@ export async function discoverGlobalPeers(): Promise<void> {
return invoke("discover_global_peers");
}
export async function setRelayDiscoverable(enabled: boolean): Promise<void> {
return invoke("set_relay_discoverable", { enabled });
}
export async function setRelayAddress(relayAddr: string): Promise<void> {
return invoke("set_relay_address", { relayAddr });
}

View File

@ -11,6 +11,7 @@ const defaultSettings: UserSettings = {
enable_message_preview: true,
show_online_status: true,
allow_dms_from_anyone: true,
relay_discoverable: true,
message_display: "cozy",
font_size: "default",
};
@ -86,6 +87,13 @@ export function toggleAllowDMsFromAnyone() {
}));
}
export function toggleRelayDiscoverable() {
setSettings((prev) => ({
...prev,
relay_discoverable: !prev.relay_discoverable,
}));
}
export function setMessageDisplay(mode: "cozy" | "compact") {
updateSettings({ message_display: mode });
}