// Online Accounts. // // GNOME's panel of the same name, except for one step. The accounts are GNOME // Online Accounts objects on D-Bus, the daemon already runs here, and listing, // per-service toggles and removal are all done natively on this page. // // Signing in to an OAuth provider is handed to GNOME's panel, because the // credentials are OAuth tokens and the code that obtains them ships without a // scriptable binding. That is stated on the page rather than hidden behind a // button that looks native, because a hand-off the user does not expect reads // as a bug. // // Accounts needing attention are surfaced first. GOA knows when a token has // expired and nothing outside its own panel says so, which is how an account // quietly stops syncing for weeks. import QtQuick import Quickshell import qs.config import qs.services SettingsPage { id: root title: "Online Accounts" lede: OnlineAccounts.attentionCount > 0 ? OnlineAccounts.attentionCount + (OnlineAccounts.attentionCount === 1 ? " account needs you to sign in again." : " accounts need you to sign in again.") : "Accounts your mail, calendar, contacts, and files come from." Component.onCompleted: if (!OnlineAccounts.scanned) OnlineAccounts.refresh() SettingsCard { visible: !OnlineAccounts.available title: "Accounts unavailable" subtitle: OnlineAccounts.lastError } SettingsCard { visible: OnlineAccounts.scanned && OnlineAccounts.available && OnlineAccounts.accounts.length === 0 title: "No accounts yet" subtitle: "Adding one lets mail, calendar, contacts, and file managers share a single sign-in." ActionRow { label: "Add an account" detail: "Google, Nextcloud, Microsoft Exchange, IMAP, WebDAV, and Kerberos" action: "Add account" divider: false onTriggered: SystemSettings.openGnomePanel("online-accounts") } } Repeater { model: OnlineAccounts.accounts SettingsCard { id: accountCard required property var modelData // GOA hands back a preference-ordered chain; this walks it and takes // the first name the active icon theme actually has. Taking the // first name blindly, or the last as a fallback, both looked right // and were not: on Adwaita the tail of these chains ("mail", // "goa-symbolic") does not exist, so a miss would have rendered // nothing at all. icon: { const chain = accountCard.modelData.providerIcons ?? []; for (const name of chain) { if (Quickshell.iconPath(String(name), true) !== "") return String(name); } return ""; } iconFallback: "avatar-default-symbolic" title: accountCard.modelData.identity || accountCard.modelData.providerName subtitle: accountCard.modelData.needsAttention ? accountCard.modelData.providerName + " ยท sign-in expired, so this account has stopped syncing" : accountCard.modelData.providerName // Only when it is true, because it is the one thing on this page // that needs acting on. ActionRow { visible: accountCard.modelData.needsAttention label: "Sign in again" detail: "Re-authorising uses the provider's own sign-in page, which GNOME's panel hosts" action: "Sign in" onTriggered: SystemSettings.openGnomePanel("online-accounts") } Repeater { model: accountCard.modelData.services SettingRow { id: serviceRow required property var modelData required property int index label: serviceRow.modelData.label detail: serviceRow.modelData.enabled ? "Applications using " + serviceRow.modelData.label.toLowerCase() + " can see this account" : "Hidden from applications" controlWidth: 48 SettingsToggle { anchors.right: parent.right anchors.verticalCenter: parent.verticalCenter checked: serviceRow.modelData.enabled onToggled: value => OnlineAccounts.setService( accountCard.modelData.path, serviceRow.modelData.key, value) } } } ActionRow { label: "Remove this account" detail: "Signs out and removes it from every application that was using it" action: "Remove" divider: false onTriggered: OnlineAccounts.remove(accountCard.modelData.path) } } } SettingsCard { visible: OnlineAccounts.available && OnlineAccounts.accounts.length > 0 title: "Add another account" subtitle: "Signing in happens on the provider's own page. GNOME's panel hosts that step; everything after it is managed here." ActionRow { label: "Add an account" detail: "Google, Nextcloud, Microsoft Exchange, IMAP, WebDAV, and Kerberos" action: "Add account" divider: false onTriggered: SystemSettings.openGnomePanel("online-accounts") } } }