Skip to content

Commit 686fa1b

Browse files
committed
fix: unify provider notification logos
1 parent 9bfd153 commit 686fa1b

12 files changed

Lines changed: 199 additions & 31 deletions

File tree

AiOverviewControlSettings.qml

Lines changed: 83 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import QtQuick.Layouts
33
import Quickshell
44
import Quickshell.Io
55
import qs.Common
6+
import qs.Services
67
import qs.Widgets
78
import qs.Modules.Plugins
89

@@ -14,6 +15,7 @@ PluginSettings {
1415
property var selectedIds: normalizeProviderSelection(loadValue("providerSelection", "codex,claude,copilot"))
1516
property var pinnedIds: normalizeCsvList(loadValue("pinnedProviders", ""))
1617
property var pillIds: normalizePillSelection(loadValue("pillProviders", selectedIds.join(",")))
18+
property color providerLogoColor: loadValue("providerLogoColor", Theme.primary.toString())
1719

1820
function normalizeCsvList(value) {
1921
const parts = String(value || "").split(",");
@@ -48,6 +50,18 @@ PluginSettings {
4850

4951
function isPinned(id) { return pinnedIds.indexOf(id) >= 0; }
5052

53+
function openProviderLogoColorPicker() {
54+
const modal = PopoutService.colorPickerModal;
55+
if (!modal) return;
56+
modal.selectedColor = loadValue("providerLogoColor", Theme.primary.toString());
57+
modal.pickerTitle = t("settings.logo_color", "Provider logo color");
58+
modal.onColorSelectedCallback = function(selectedColor) {
59+
root.providerLogoColor = selectedColor;
60+
saveValue("providerLogoColor", selectedColor.toString());
61+
};
62+
modal.show();
63+
}
64+
5165
function togglePinned(id) {
5266
const result = pinnedIds.slice();
5367
const index = result.indexOf(id);
@@ -469,7 +483,7 @@ PluginSettings {
469483
providerId: pillProviderChip.modelData.id
470484
fallbackIcon: pillProviderChip.modelData.icon
471485
logoSize: 16
472-
tintColor: pillProviderChip.active ? Theme.primary : Theme.surfaceVariantText
486+
tintColor: root.providerLogoColor
473487
anchors.verticalCenter: parent.verticalCenter
474488
}
475489

@@ -522,6 +536,72 @@ PluginSettings {
522536
onToggled: function(checked) { saveValue("showErrorProviders", checked ? "true" : "false"); }
523537
}
524538

539+
Column {
540+
width: parent.width
541+
spacing: Theme.spacingXS
542+
543+
StyledText {
544+
width: parent.width
545+
text: t("settings.logo_color", "Provider logo color")
546+
color: Theme.surfaceText
547+
font.pixelSize: Theme.fontSizeSmall
548+
font.weight: Font.Medium
549+
}
550+
551+
StyledText {
552+
width: parent.width
553+
text: t("settings.logo_color_desc", "One monochrome color for every provider logo in the dashboard and desktop notifications.")
554+
color: Theme.surfaceVariantText
555+
font.pixelSize: Theme.fontSizeSmall - 1
556+
wrapMode: Text.WordWrap
557+
}
558+
559+
Rectangle {
560+
width: parent.width
561+
height: 46
562+
radius: Theme.cornerRadius
563+
color: Theme.surfaceContainerHigh
564+
565+
Row {
566+
anchors.fill: parent
567+
anchors.leftMargin: Theme.spacingM
568+
anchors.rightMargin: Theme.spacingM
569+
spacing: Theme.spacingM
570+
571+
Rectangle {
572+
width: 28
573+
height: 28
574+
radius: width / 2
575+
color: root.providerLogoColor
576+
border.color: Theme.outline
577+
border.width: 1
578+
anchors.verticalCenter: parent.verticalCenter
579+
}
580+
581+
StyledText {
582+
text: root.providerLogoColor.toString()
583+
color: Theme.surfaceText
584+
font.pixelSize: Theme.fontSizeSmall
585+
anchors.verticalCenter: parent.verticalCenter
586+
}
587+
588+
Item { width: 1; height: 1; Layout.fillWidth: true }
589+
590+
DankIcon {
591+
name: "edit"
592+
size: Theme.iconSizeSmall
593+
color: Theme.surfaceVariantText
594+
anchors.verticalCenter: parent.verticalCenter
595+
}
596+
}
597+
598+
StateLayer {
599+
stateColor: Theme.surfaceText
600+
onClicked: root.openProviderLogoColorPicker()
601+
}
602+
}
603+
}
604+
525605
DankToggle {
526606
width: parent.width
527607
text: t("settings.show_projects", "Show Claude projects")
@@ -880,7 +960,7 @@ PluginSettings {
880960
providerId: providerChip.modelData.id
881961
fallbackIcon: providerChip.modelData.icon
882962
logoSize: 16
883-
tintColor: providerChip.active ? Theme.primary : Theme.surfaceVariantText
963+
tintColor: root.providerLogoColor
884964
anchors.verticalCenter: parent.verticalCenter
885965
}
886966
StyledText { text:modelData.name; color:providerChip.active ? Theme.primary : Theme.surfaceVariantText; font.pixelSize:Theme.fontSizeSmall; font.weight:providerChip.active ? Font.Medium : Font.Normal }
@@ -930,7 +1010,7 @@ PluginSettings {
9301010
providerId: providerDetailRow.modelData.id
9311011
fallbackIcon: providerDetailRow.modelData.icon
9321012
logoSize: 16
933-
tintColor: Theme.primary
1013+
tintColor: root.providerLogoColor
9341014
}
9351015
}
9361016

AiOverviewControlWidget.qml

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ PluginComponent {
4040
// In-process dispatch bookkeeping. The helper owns the durable state so
4141
// this remains only a cheap guard between refreshes in this instance.
4242
property var notifiedMap: ({})
43+
property color providerLogoColor: {
44+
const saved = String(pluginData.providerLogoColor || "").trim();
45+
return saved.length > 0 ? saved : Theme.primary;
46+
}
4347
property bool notifyEnabled: String(pluginData.quotaNotifications ?? "true") === "true"
4448
property int notifyThreshold: {
4549
const parsed = parseInt(pluginData.notifyThreshold || "85");
@@ -1230,6 +1234,7 @@ PluginComponent {
12301234
String(notifyCooldownSecs),
12311235
exhausted ? "critical" : "normal",
12321236
notificationIconPath(provider.provider),
1237+
providerLogoColor.toString(),
12331238
title,
12341239
bodyParts.join(" · ")
12351240
]);
@@ -1278,6 +1283,9 @@ PluginComponent {
12781283
const lastSlash = withoutScheme.lastIndexOf("/");
12791284
_pluginDir = lastSlash !== -1 ? withoutScheme.substring(0, lastSlash) : withoutScheme;
12801285
}
1286+
// One-time, idempotent cleanup of the legacy state whose full reset
1287+
// timestamp made jitter look like a new quota window every refresh.
1288+
Quickshell.execDetached(["bash", notifyAlertScript, "--migrate"]);
12811289
detectBinary();
12821290
}
12831291

@@ -2195,7 +2203,7 @@ PluginComponent {
21952203
providerId: pillEntry.modelData.provider
21962204
fallbackIcon: root.iconForProvider(pillEntry.modelData.provider)
21972205
logoSize: 14
2198-
tintColor: root.providerAccent(pillEntry.modelData.provider)
2206+
tintColor: root.providerLogoColor
21992207
anchors.verticalCenter: parent.verticalCenter
22002208
}
22012209

@@ -2261,7 +2269,7 @@ PluginComponent {
22612269
providerId: modelData.provider
22622270
fallbackIcon: root.iconForProvider(modelData.provider)
22632271
logoSize: 13
2264-
tintColor: root.providerAccent(modelData.provider)
2272+
tintColor: root.providerLogoColor
22652273
anchors.horizontalCenter: parent.horizontalCenter
22662274
}
22672275

@@ -2631,16 +2639,21 @@ PluginComponent {
26312639
anchors.fill: parent
26322640
anchors.margins: 4
26332641
radius: width / 2
2634-
color: Theme.withAlpha(card.accentColor, 0.14)
2635-
border.width: card.hasUsage ? 0 : 1
2636-
border.color: Theme.withAlpha(card.accentColor, 0.4)
2642+
// Logo surfaces intentionally use the single
2643+
// user-selected provider-logo colour. Usage state
2644+
// remains on the surrounding progress ring instead
2645+
// of making each provider mark look like a different
2646+
// brand-coloured icon.
2647+
color: Theme.withAlpha(root.providerLogoColor, 0.14)
2648+
border.width: 1
2649+
border.color: Theme.withAlpha(root.providerLogoColor, 0.32)
26372650

26382651
ProviderLogo {
26392652
anchors.centerIn: parent
26402653
providerId: card.provider.provider
26412654
fallbackIcon: root.iconForProvider(card.provider.provider)
26422655
logoSize: card.dense ? 15 : (card.compact ? 17 : 20)
2643-
tintColor: card.accentColor
2656+
tintColor: root.providerLogoColor
26442657
}
26452658
}
26462659
}

CHANGELOG.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,14 @@
66

77
- Reworked quota-alert deduplication around a stable provider/window identity. Timestamp jitter, locale changes, and threshold edits no longer re-arm alerts or flood the DankMaterialShell notification popup.
88
- High-usage alerts now escalate in place to a critical “quota reached” notification at 100%; reminders reuse the same DMS notification instead of stacking cards, and a critical alert is never downgraded back to a warning.
9-
- Notification popups now use each provider's bundled brand logo and concise localized text for the quota window, usage percentage, and reset time.
9+
- Notification popups now use a padded monochrome rendering of each provider's bundled logo and concise localized text for the quota window, usage percentage, and reset time.
1010
- Clarified the notification settings, re-alert behavior, and documentation in every supported locale.
1111

12+
### Provider logo presentation
13+
14+
- All provider marks in the DankBar pill, dashboard, settings, and new desktop alerts now use one configurable monochrome color while preserving the vector silhouette and transparent canvas.
15+
- Provider-card logo surfaces now share that same color instead of individual brand accents, and Copilot uses the GitHub Copilot mark.
16+
1217
## 1.7.0 - 2026-07-13
1318

1419
### DankBar and provider identity

ProviderLogo.qml

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,6 @@ Item {
2727
const normalized = String(providerId || "").trim().toLowerCase();
2828
return aliases[normalized] || normalized;
2929
}
30-
readonly property var colorLogoIds: [
31-
"9router", "ai21", "amp", "antigravity", "byteplus", "claude",
32-
"cloudflare", "cohere", "copilot", "deepseek", "fireworks",
33-
"gemini", "glm", "kimi", "kiro", "minimax", "mistral",
34-
"nvidia", "perplexity", "qwen", "together", "vertexai", "warp"
35-
]
36-
readonly property bool usesBrandColors: colorLogoIds.indexOf(canonicalId) >= 0
3730
readonly property string logoExtension: canonicalId === "byteplus" ? ".png" : ".svg"
3831
readonly property url logoSource: canonicalId.length > 0
3932
? Qt.resolvedUrl("assets/provider-logos/" + canonicalId + logoExtension)
@@ -57,15 +50,16 @@ Item {
5750
mipmap: true
5851
asynchronous: true
5952
cache: true
60-
visible: root.usesBrandColors && root.logoReady
61-
}
6253

63-
MultiEffect {
64-
anchors.fill: logoImage
65-
source: logoImage
66-
visible: !root.usesBrandColors && root.logoReady
67-
colorization: 1.0
68-
colorizationColor: root.tintColor
54+
// Applying the colorization to the image layer keeps the original
55+
// transparent SVG silhouette; do not use it as a sibling effect
56+
// source, which is opaque with this renderer.
57+
layer.enabled: true
58+
layer.effect: MultiEffect {
59+
brightness: 1.0
60+
colorization: 1.0
61+
colorizationColor: root.tintColor
62+
}
6963
}
7064

7165
DankIcon {

assets/provider-logos/SOURCES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,6 @@ All marks are stored locally so the plugin never depends on a network request at
88
- 9Router: [official `public/favicon.svg`](https://github.com/decolua/9router/blob/master/public/favicon.svg), MIT.
99
- BytePlus Ark: [official BytePlus favicon](https://sf-bpcms.bytepluscdn.com/obj/byteplus-public-aiso/portal/assets/favicon.png), discovered from the ModelArk product page.
1010
- Warp: [Simple Icons `warp`](https://simpleicons.org/?q=warp), CC0-1.0, brand color `#01A4FF`.
11+
- GitHub Copilot: [Simple Icons `githubcopilot`](https://simpleicons.org/?q=githubcopilot), CC0-1.0.
1112

1213
The included license files cover the MIT-licensed Lobe Icons and 9Router assets. Product names and logos remain trademarks of their respective owners.

assets/provider-logos/copilot.svg

Lines changed: 1 addition & 1 deletion
Loading

i18n/de_DE.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@
8989
"settings.informational_providers_desc": "Diese Anbieter bieten keine öffentliche, schreibgeschützte Kontingent-API. Ihre Karten verweisen auf die offizielle Nutzungsoberfläche.",
9090
"settings.language.description": "Sprache der Plugin-Oberfläche. Auto folgt der Systemsprache.",
9191
"settings.language.label": "Sprache",
92+
"settings.logo_color": "Farbe der Anbieterlogos",
93+
"settings.logo_color_desc": "Eine monochrome Farbe für alle Anbieterlogos im Dashboard und in Desktop-Benachrichtigungen.",
9294
"settings.notify.description": "Warnt einmal, wenn ein Anbieter den Schwellwert überschreitet, und aktualisiert dieselbe Benachrichtigung bei ausgeschöpftem Kontingent.",
9395
"settings.notify.label": "Kontingent-Benachrichtigungen",
9496
"settings.notify.overrides": "Schwellwerte pro Anbieter",

i18n/en.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@
8989
"settings.informational_providers_desc": "These providers expose no public read-only quota API. Their cards point to the official usage surface.",
9090
"settings.language.description": "UI language for this plugin. Auto follows system locale.",
9191
"settings.language.label": "Language",
92+
"settings.logo_color": "Provider logo color",
93+
"settings.logo_color_desc": "One monochrome color for every provider logo in the dashboard and desktop notifications.",
9294
"settings.notify.description": "Alert once when a provider crosses the threshold, then update the same notification if its quota is exhausted.",
9395
"settings.notify.label": "Quota notifications",
9496
"settings.notify.overrides": "Per-provider threshold overrides",

0 commit comments

Comments
 (0)