diff --git a/nobilis b/nobilis index e0c66ca..d4b6ab8 160000 --- a/nobilis +++ b/nobilis @@ -1 +1 @@ -Subproject commit e0c66ca0c98966f5f382d47c675e5444df732834 +Subproject commit d4b6ab89f3102b6dacb6a00f75021ecdb70cec6d diff --git a/src/renderer/src/app.css b/src/renderer/src/app.css index 99d4124..afb8aeb 100644 --- a/src/renderer/src/app.css +++ b/src/renderer/src/app.css @@ -816,6 +816,21 @@ img.composer-emoji { gap: var(--spacing-s); } +/* The SASL fields read as one decision rather than three loose settings, so + they are boxed together and indent under the switch that turns them on. */ +.sasl-block { + display: flex; + flex-direction: column; + gap: var(--spacing-s); + padding: var(--spacing-s); + border: 1px solid var(--outline-light); + border-radius: var(--corner-radius); +} + +.sasl-block .field { + margin-left: calc(16px + var(--spacing-s)); +} + .qr-image { width: 220px; height: 220px; diff --git a/src/renderer/src/components/AccountsPanel.tsx b/src/renderer/src/components/AccountsPanel.tsx index 566c5e8..abea1d6 100644 --- a/src/renderer/src/components/AccountsPanel.tsx +++ b/src/renderer/src/components/AccountsPanel.tsx @@ -274,6 +274,7 @@ function AccountRow({ account }: { account: Account }): JSX.Element { call('setAccountAutojoin', { accountId: account.id, channels }) } /> + ) => void +}): JSX.Element { + const [username, setUsername] = useState(account.saslUsername) + const [password, setPassword] = useState('') + const [allowPlaintext, setAllowPlaintext] = useState(account.allowPlaintextSasl) + + const apply = (patch: { enabled?: boolean; saslUser?: string; allowPlaintextSasl?: boolean }): void => + call('setAccountSasl', { + accountId: account.id, + enabled: account.saslEnabled, + saslUser: username, + // Empty means "leave the stored one alone" - the daemon never reads a + // password back out, so there is nothing to prefill and clearing the + // box must not be read as clearing the credential. + password, + allowPlaintextSasl: allowPlaintext, + ...patch + }) + + return ( +
+ + + {account.saslEnabled && ( + <> + { + setUsername(value) + apply({ saslUser: value }) + }} + /> + { + setPassword(value) + call('setAccountSasl', { + accountId: account.id, + enabled: true, + saslUser: username, + password: value, + allowPlaintextSasl: allowPlaintext + }) + }} + /> + + {/* Only where it is a live question. On a TLS connection the + allowance decides nothing, and offering it there would be a + switch that appears to weaken something and does not. */} + {!account.ssl && ( + + )} + + )} +
+ ) +} + function LabeledInput({ label, defaultValue, diff --git a/src/shared/wire.ts b/src/shared/wire.ts index 251992c..1965e92 100644 --- a/src/shared/wire.ts +++ b/src/shared/wire.ts @@ -16,6 +16,11 @@ export interface Account { saslEnabled: boolean saslUsername: string allowPlaintextSasl: boolean + /** + * Whether the connection is encrypted. Only IRC is ever false - every other + * service here is HTTPS or WSS by construction. + */ + ssl: boolean hasPassword: boolean avatarUrl?: string sockchatRooms?: SockChatRoom[]