diff --git a/nobilis b/nobilis index 78019ca..1ef66ab 160000 --- a/nobilis +++ b/nobilis @@ -1 +1 @@ -Subproject commit 78019ca762692ef055c99d20d32998bfb969a220 +Subproject commit 1ef66ab532e23ffa4fdeeb5bde12452d87bcaae2 diff --git a/src/renderer/src/components/ConversationTools.tsx b/src/renderer/src/components/ConversationTools.tsx index 865615e..9eb5559 100644 --- a/src/renderer/src/components/ConversationTools.tsx +++ b/src/renderer/src/components/ConversationTools.tsx @@ -6,6 +6,63 @@ import { formatFullTime } from '../lib/util' import type { BufferEntry } from '../state/store' import type { Message } from '../../../shared/wire' +/** + * Asking somebody into a Matrix room. + * + * A field rather than a picker, because a Matrix address names a person + * globally - there is no roster to choose from and nobody to look up first. + * Offered on every Matrix room rather than gated on permission: the server + * decides, and it says so plainly enough that guessing here would only mean + * hiding the action from somebody who could have used it. + */ +function InviteToRoom({ buffer }: { buffer: BufferEntry }): JSX.Element { + const store = useStore() + const [open, setOpen] = useState(false) + const [who, setWho] = useState('') + const [busy, setBusy] = useState(false) + + const invite = (): void => { + const userId = who.trim() + if (!userId) return + setBusy(true) + void window.moho + .rpc('inviteMatrixMember', { accountId: buffer.accountId, bufferId: buffer.id, userId }) + .then(() => { + store.toast('info', `Invited ${userId}`) + setWho('') + setOpen(false) + }) + .catch((e: Error) => store.toast('error', e.message)) + .finally(() => setBusy(false)) + } + + if (!open) { + return setOpen(true)} /> + } + + return ( +
+ + setWho(e.target.value)} + onKeyDown={(e) => { + if (e.key === 'Escape') { + setWho('') + setOpen(false) + } + if (e.key === 'Enter') invite() + }} + onBlur={() => !who.trim() && setOpen(false)} + /> +
+ ) +} + /** * What a channel's restrictions mean, for the ones worth explaining. * @@ -160,6 +217,11 @@ export function ConversationTools({ buffer }: { buffer: BufferEntry }): JSX.Elem the conversation being read rather than on the window. */} {isDiscord && isDm && } + {/* The same job on Matrix, where it needs no picker: a Matrix address + names somebody whether or not this account has ever met them, so + there is no friend list to choose from and nothing to look up. */} + {buffer.accountId.startsWith('matrix:') && } +
Your other logged-in devices. Verify one to let encrypted history decrypt across both.
+ {/* Said because the tick is otherwise a promise this cannot keep. + moho does no cross-signing, so a verification here is recorded + between these two sessions and never published - Element will + still show the device as unverified, and somebody who was not + told that would reasonably conclude one of the two clients is + broken. */} +
+ Verifying marks a session as trusted in moho. moho does not do cross-signing, + so other clients will still show it unverified. +