- New chatd-rs backend/matrix module: m.login.password auth, /sync-based multi-room connect loop, and full E2EE via matrix-sdk-crypto (device key upload, Megolm session establishment, encrypt/decrypt) - verified live against real homeservers with two independent devices exchanging an encrypted message neither one decrypted itself. - Reactions, edits, redactions, replies, and media upload/download, mapped onto the existing Reaction/Embed/ReplyPreview model. - Frontend wiring: MatrixConnectForm.qml, AccountsPanel/ChatView hookup, and the real addMatrixAccount RPC handler (replacing the stub). - Fix messages doubling in the UI: the Matrix backend never called Runtime::set_own_identity, so every message - including the account's own - was stored with is_own=false, defeating the frontend's optimistic- send reconciliation. - Fix accounts getting stuck showing "connecting" forever: the Connected state transition was gated on this being the account's very first-ever sync (next_batch.is_none()), which is never true again once a cursor is persisted across a restart - a real account could sync successfully forever and never have its state announced as connected. Co-Authored-By: Claude Sonnet 5 <[email protected]>
72 lines
2.1 KiB
QML
72 lines
2.1 KiB
QML
import QtQuick
|
|
import QtQuick.Layouts
|
|
import qs.Common
|
|
import qs.Widgets
|
|
|
|
// Matrix login is homeserver URL + username + password (m.login.password) -
|
|
// no SSO/QR flow in v1, see backend/matrix/auth.rs. Login itself (resolving
|
|
// the homeserver, authenticating, then bootstrapping this device's E2EE
|
|
// identity) can take a moment, so this only ever renders a status string
|
|
// fed by matrixLoginStatus/matrixLoginResult events - see ChatView.qml's
|
|
// handling of those, mirrored from the Sneedchat/Discord equivalents.
|
|
ColumnLayout {
|
|
id: root
|
|
|
|
signal connectRequested(string homeserverUrl, string username, string password)
|
|
|
|
property string statusText: ""
|
|
property bool pending: false
|
|
|
|
onStatusTextChanged: root.pending = false
|
|
|
|
spacing: Theme.spacingXS
|
|
|
|
DankTextField {
|
|
id: homeserverField
|
|
Layout.fillWidth: true
|
|
placeholderText: "homeserver (e.g. https://matrix.org)"
|
|
text: "https://matrix.org"
|
|
}
|
|
|
|
RowLayout {
|
|
Layout.fillWidth: true
|
|
spacing: Theme.spacingXS
|
|
|
|
DankTextField {
|
|
id: usernameField
|
|
Layout.fillWidth: true
|
|
placeholderText: "username"
|
|
}
|
|
|
|
DankTextField {
|
|
id: passwordField
|
|
Layout.preferredWidth: 160
|
|
placeholderText: "password"
|
|
echoMode: TextInput.Password
|
|
}
|
|
}
|
|
|
|
DankButton {
|
|
text: root.pending ? "Connecting..." : "Connect"
|
|
enabled: !root.pending
|
|
onClicked: {
|
|
if (!homeserverField.text || !usernameField.text || !passwordField.text) {
|
|
root.statusText = "Homeserver, username and password are required.";
|
|
return;
|
|
}
|
|
root.pending = true;
|
|
root.statusText = "";
|
|
root.connectRequested(homeserverField.text, usernameField.text, passwordField.text);
|
|
passwordField.text = "";
|
|
}
|
|
}
|
|
|
|
StyledText {
|
|
Layout.fillWidth: true
|
|
visible: root.statusText !== ""
|
|
text: root.statusText
|
|
wrapMode: Text.WordWrap
|
|
color: Theme.surfaceVariantText
|
|
}
|
|
}
|