import QtQuick import qs.Common import qs.Services import qs.Widgets import qs.Modules.Plugins // Composite-plugin "widget" surface: the DankBar pill. Reads connection/ // unread state the daemon surface (ChatDaemon.qml) publishes via // PluginService global vars - see PLUGINS/README.md's "Plugin Global // Variables" section for why this indirection exists (daemon and widget // are separate object instances with no direct reference to each other). // // Clicking the pill bumps a "toggleNonce" global var the daemon watches, // rather than PluginService.togglePlugin(pluginId) - that generic lookup // didn't reliably find this composite plugin's daemon instance when // tested against this DMS version. See ChatDaemon.qml for the other end. PluginComponent { id: root pillClickAction: () => { const n = PluginService.getGlobalVar(root.pluginId, "toggleNonce", 0); PluginService.setGlobalVar(root.pluginId, "toggleNonce", n + 1); } PluginGlobalVar { id: chatdConnected varName: "chatdConnected" defaultValue: false } PluginGlobalVar { id: totalUnread varName: "totalUnread" defaultValue: 0 } // Set by ChatDaemon.qml whenever a pinned buffer (see BufferList.qml's // Pin menu item) has an unread DM or highlighted mention pending - // chatd only ever emits the underlying "notification" event for one // of those two cases, never plain traffic, so this is exactly "unread // DM or mention from a pinned channel", not just "any unread". PluginGlobalVar { id: hasPinnedAlert varName: "hasPinnedAlert" defaultValue: false } // Deliberately just the icon+count Row, no background/sizing of our // own - the host BasePill (see PluginComponent.qml, which wraps // whatever horizontalBarPill provides as this component's `content`) // already supplies the pill's real background, padding, and radius, // sized from this Row's own natural implicitWidth/implicitHeight. // Matches every other composite-plugin bar widget's own convention // (see PLUGINS/ExampleCompositePlugin/CompositeBarWidget.qml) - // wrapping this in a second StyledRect of our own, as it used to be, // just draws a redundant background with its own different padding // math, which is what made this pill a different size than its // siblings in the first place. horizontalBarPill: Component { Row { id: content spacing: Theme.spacingXS DankIcon { id: chatIcon name: "chat" size: Theme.iconSize - 4 color: hasPinnedAlert.value ? Theme.error : (chatdConnected.value ? Theme.primary : Theme.surfaceVariantText) anchors.verticalCenter: parent.verticalCenter // Pulses opacity while a pinned alert is pending - stops // (and resets to fully opaque, rather than possibly // freezing mid-fade) the instant hasPinnedAlert clears, // e.g. once the buffer's actually been read. SequentialAnimation { running: hasPinnedAlert.value loops: Animation.Infinite onRunningChanged: if (!running) chatIcon.opacity = 1.0 NumberAnimation { target: chatIcon property: "opacity" to: 0.35 duration: 500 easing.type: Easing.InOutQuad } NumberAnimation { target: chatIcon property: "opacity" to: 1.0 duration: 500 easing.type: Easing.InOutQuad } } } StyledText { visible: totalUnread.value > 0 text: totalUnread.value font.pixelSize: Theme.fontSizeSmall color: Theme.surfaceText anchors.verticalCenter: parent.verticalCenter } } } }