diff --git a/nobilis b/nobilis index 412c232..d584492 160000 --- a/nobilis +++ b/nobilis @@ -1 +1 @@ -Subproject commit 412c23201d53eb3d70498495867ac6537c2dfe47 +Subproject commit d58449282294dbfccb3411e22664b0ffded240c6 diff --git a/src/renderer/src/components/AccountsPanel.tsx b/src/renderer/src/components/AccountsPanel.tsx index f107fd9..c1227a1 100644 --- a/src/renderer/src/components/AccountsPanel.tsx +++ b/src/renderer/src/components/AccountsPanel.tsx @@ -6,8 +6,28 @@ import { bufferDisplayName, classes, resolveMediaUrl, serviceIcon, serviceLabel import { IRC_NETWORKS, ircNetworkFor } from '../lib/networks' import type { Account } from '../../../shared/wire' -const ADDABLE = ['irc', 'discord', 'sneedchat', 'matrix', 'kick'] as const -type AddableService = (typeof ADDABLE)[number] +/** + * The services this window can draw a sign-in form for. + * + * Not a list of what moho supports - that is the daemon's to say, and it says + * it through `listProtocols`. This is the other half of the question, which + * only the window can answer: a protocol the daemon speaks but this has no + * form for cannot be added from here, and a chip that opens nothing would be + * worse than no chip. + * + * What is offered is the intersection, in the daemon's order. So a protocol + * that gains a backend appears here as soon as it gains a form, and one the + * daemon stops offering disappears without this file being touched. + */ +const FORMS = ['irc', 'discord', 'sneedchat', 'matrix', 'kick'] as const +type AddableService = (typeof FORMS)[number] + +/** What `listProtocols` answers with. */ +interface Protocol { + id: string + name: string + available: boolean +} /** * Account states that make a service's group open itself. @@ -50,12 +70,33 @@ export function AccountsPanel(): JSX.Element { */ const [openGroups, setOpenGroups] = useMapPref('accountGroupOpen') + // Which protocols the daemon offers, asked once. The two are deployed + // separately and either can be older than the other, which is the whole + // reason to ask rather than to assume. + const [protocols, setProtocols] = useState(null) + useEffect(() => { + void window.moho + .rpc('listProtocols') + // A daemon too old to answer leaves the window with what it can draw, + // which is what it did before it asked at all. + .catch(() => null) + .then(setProtocols) + }, []) + + const addable: AddableService[] = ( + protocols + ? protocols.filter((p) => p.available).map((p) => p.id) + : (FORMS as readonly string[]).slice() + ).filter((id): id is AddableService => (FORMS as readonly string[]).includes(id)) + + const nameFor = (service: string): string => + protocols?.find((p) => p.id === service)?.name ?? serviceLabel(service) + // Grouped by service, in the order the picker offers them, so the two // halves of this page agree about what order services come in. - const byService = ADDABLE.map((service) => ({ - service, - accounts: accounts.filter((a) => a.service === service) - })).filter((group) => group.accounts.length > 0) + const byService = addable + .map((service) => ({ service, accounts: accounts.filter((a) => a.service === service) })) + .filter((group) => group.accounts.length > 0) return (
@@ -66,7 +107,7 @@ export function AccountsPanel(): JSX.Element {

Add an account

- {ADDABLE.map((service) => { + {addable.map((service) => { const icon = serviceIcon(service) return ( ) })}