import QtQuick import QtQuick.Layouts import qs.Common import qs.Widgets // Discord has no username/password path here by design (see the project // plan's Discord milestone) - the QR flow is Discord's own official // cross-device login (the same one discord.com/app's "Log in with QR Code" // offers), just driven from chatd instead of a browser. chatd does all the // protocol work (backend/discord.rs) and pushes progress back as events; // this form only ever needs to request a login and render whatever it's // told to render (QR image / status text) - see ChatView.qml's // discordLoginQr/discordLoginScanned/discordLoginResult handling. ColumnLayout { id: root signal connectRequested() property string qrPath: "" property string statusText: "" property bool pending: false // The QML property-binding-vs-assignment rule bites here: `pending` is // only ever *assigned* (never externally bound) so this component can // freely clear it itself once anything comes back - a bound property // would get permanently detached from its binding the instant this // component's own onClicked assigned to it. onQrPathChanged: root.pending = false onStatusTextChanged: root.pending = false spacing: Theme.spacingXS StyledText { Layout.fillWidth: true text: "Log in the same way the Discord app's own \"Log in with QR Code\" does: open Discord on your phone, go to Settings → Scan QR Code, and point it at the code below." wrapMode: Text.WordWrap color: Theme.surfaceVariantText } DankButton { text: root.pending ? "Generating..." : (root.qrPath ? "Show a new QR code" : "Show QR code") enabled: !root.pending onClicked: { root.pending = true; root.qrPath = ""; root.statusText = ""; root.connectRequested(); } } Rectangle { Layout.preferredWidth: 220 Layout.preferredHeight: 220 Layout.alignment: Qt.AlignHCenter Layout.topMargin: Theme.spacingS visible: root.qrPath !== "" color: "white" radius: Theme.cornerRadius Image { anchors.fill: parent anchors.margins: Theme.spacingM // chatd renders the QR code to a temp PNG and hands back a // plain filesystem path (see backend/discord.rs) rather than // embedding it as a base64 data URI in the event - keeps every // line on the JSON-RPC socket small. source: root.qrPath ? "file://" + root.qrPath : "" fillMode: Image.PreserveAspectFit smooth: false cache: false } } StyledText { Layout.fillWidth: true Layout.topMargin: Theme.spacingXS visible: root.statusText !== "" text: root.statusText wrapMode: Text.WordWrap horizontalAlignment: Text.AlignHCenter color: Theme.surfaceVariantText } }