mirror of
https://github.com/noctalia-dev/noctalia-shell.git
synced 2026-05-11 17:08:27 +08:00
about: supporters subtab
This commit is contained in:
@@ -469,6 +469,7 @@
|
||||
"sources": "Quellen",
|
||||
"start": "Start",
|
||||
"stop": "Stopp",
|
||||
"supporters": "Unterstützer",
|
||||
"suspend": "Energie sparen",
|
||||
"templates": "Vorlagen",
|
||||
"tertiary": "Tertiär",
|
||||
@@ -646,6 +647,7 @@
|
||||
},
|
||||
"panels": {
|
||||
"about": {
|
||||
"become-supporter": "Werde Unterstützer",
|
||||
"changelog": "Änderungsprotokoll anzeigen",
|
||||
"contributors-desc": "Ein Dankeschön an unseren {count} <b>großartigen</b> Mitwirkenden!",
|
||||
"contributors-description-plural": "Ein Dankeschön an unsere {count} <b>großartigen</b> Mitwirkenden!",
|
||||
@@ -658,6 +660,9 @@
|
||||
"noctalia-title": "Noctalia Shell",
|
||||
"privacy-policy": "Datenschutzbestimmungen",
|
||||
"support": "Unterstütze uns",
|
||||
"supporter-badge": "Unterstützer",
|
||||
"supporters-desc-singular": "Ein riesiges Dankeschön an unseren großartigen Unterstützer!",
|
||||
"supporters-loading": "Supporter werden geladen...",
|
||||
"system-cpu": "CPU:",
|
||||
"system-disk": "Festplatte:",
|
||||
"system-gpu": "GPU:",
|
||||
|
||||
@@ -469,6 +469,7 @@
|
||||
"sources": "Sources",
|
||||
"start": "Start",
|
||||
"stop": "Stop",
|
||||
"supporters": "Supporters",
|
||||
"suspend": "Suspend",
|
||||
"templates": "Templates",
|
||||
"tertiary": "Tertiary",
|
||||
@@ -646,6 +647,7 @@
|
||||
},
|
||||
"panels": {
|
||||
"about": {
|
||||
"become-supporter": "Become a supporter",
|
||||
"changelog": "View changelog",
|
||||
"contributors-desc": "Shout-out to our {count} <b>awesome</b> contributor!",
|
||||
"contributors-description-plural": "Shout-out to our {count} <b>awesome</b> contributors!",
|
||||
@@ -658,6 +660,10 @@
|
||||
"noctalia-title": "Noctalia shell",
|
||||
"privacy-policy": "Privacy policy",
|
||||
"support": "Support us",
|
||||
"supporter-badge": "Supporter",
|
||||
"supporters-desc-plural": "A huge thank you to our <b>{count} amazing</b> supporters!",
|
||||
"supporters-desc-singular": "A huge thank you to our amazing supporter!",
|
||||
"supporters-loading": "Loading supporters...",
|
||||
"system-cpu": "CPU:",
|
||||
"system-disk": "Disk:",
|
||||
"system-gpu": "GPU:",
|
||||
|
||||
@@ -469,6 +469,7 @@
|
||||
"sources": "Fuentes",
|
||||
"start": "Comienzo",
|
||||
"stop": "Parar",
|
||||
"supporters": "Apoyadores",
|
||||
"suspend": "Suspender",
|
||||
"templates": "Plantillas",
|
||||
"tertiary": "Terciario",
|
||||
@@ -646,6 +647,7 @@
|
||||
},
|
||||
"panels": {
|
||||
"about": {
|
||||
"become-supporter": "Hazte patrocinador",
|
||||
"changelog": "Ver registro de cambios",
|
||||
"contributors-desc": "¡Un saludo a nuestro <b>increíble</b> colaborador número {count}!",
|
||||
"contributors-description-plural": "¡Un saludo a nuestros {count} <b>increíbles</b> colaboradores!",
|
||||
@@ -658,6 +660,9 @@
|
||||
"noctalia-title": "Shell Noctalia",
|
||||
"privacy-policy": "Política de privacidad",
|
||||
"support": "Apóyanos",
|
||||
"supporter-badge": "Colaborador",
|
||||
"supporters-desc-singular": "¡Un enorme agradecimiento a nuestro increíble colaborador!",
|
||||
"supporters-loading": "Cargando patrocinadores...",
|
||||
"system-cpu": "CPU:",
|
||||
"system-disk": "Disco:",
|
||||
"system-gpu": "GPU:",
|
||||
|
||||
@@ -469,6 +469,7 @@
|
||||
"sources": "Sources",
|
||||
"start": "Commencer",
|
||||
"stop": "Arrêtez",
|
||||
"supporters": "Soutiens",
|
||||
"suspend": "Mettre en veille",
|
||||
"templates": "Modèles",
|
||||
"tertiary": "Tertiaire",
|
||||
@@ -646,6 +647,7 @@
|
||||
},
|
||||
"panels": {
|
||||
"about": {
|
||||
"become-supporter": "Devenir un soutien",
|
||||
"changelog": "Afficher le journal des modifications",
|
||||
"contributors-desc": "Un grand merci à notre {count} <b>super</b> contributeur !",
|
||||
"contributors-description-plural": "Un grand merci à nos {count} <b>super</b> contributeurs !",
|
||||
@@ -658,6 +660,9 @@
|
||||
"noctalia-title": "Shell Noctalia",
|
||||
"privacy-policy": "Politique de confidentialité",
|
||||
"support": "Soutenez-nous",
|
||||
"supporter-badge": "Soutien",
|
||||
"supporters-desc-singular": "Un immense merci à notre incroyable soutien !",
|
||||
"supporters-loading": "Chargement des contributeurs...",
|
||||
"system-cpu": "Processeur :",
|
||||
"system-disk": "Disque :",
|
||||
"system-gpu": "GPU :",
|
||||
|
||||
@@ -469,6 +469,7 @@
|
||||
"sources": "Források",
|
||||
"start": "Kezdés",
|
||||
"stop": "Állj",
|
||||
"supporters": "Támogatók",
|
||||
"suspend": "Felfüggesztés",
|
||||
"templates": "Sablonok",
|
||||
"tertiary": "Harmadlagos",
|
||||
@@ -646,6 +647,7 @@
|
||||
},
|
||||
"panels": {
|
||||
"about": {
|
||||
"become-supporter": "Legyél támogató",
|
||||
"changelog": "Változások megtekintése",
|
||||
"contributors-desc": "Köszönet a(z) {count} <b>fantasztikus</b> közreműködőnknek!",
|
||||
"contributors-description-plural": "Köszönet a(z) {count} <b>fantasztikus</b> közreműködőnknek!",
|
||||
@@ -658,6 +660,9 @@
|
||||
"noctalia-title": "Noctalia shell",
|
||||
"privacy-policy": "Adatvédelmi irányelvek",
|
||||
"support": "Támogasson minket",
|
||||
"supporter-badge": "Támogató",
|
||||
"supporters-desc-singular": "Hatalmas köszönet csodálatos támogatóinknak!",
|
||||
"supporters-loading": "Támogatók betöltése...",
|
||||
"system-cpu": "CPU:",
|
||||
"system-disk": "Lemez:",
|
||||
"system-gpu": "GPU:",
|
||||
|
||||
@@ -469,6 +469,7 @@
|
||||
"sources": "ソース",
|
||||
"start": "開始",
|
||||
"stop": "停止",
|
||||
"supporters": "サポーター",
|
||||
"suspend": "サスペンド",
|
||||
"templates": "テンプレート",
|
||||
"tertiary": "第三",
|
||||
@@ -646,6 +647,7 @@
|
||||
},
|
||||
"panels": {
|
||||
"about": {
|
||||
"become-supporter": "サポーターになる",
|
||||
"changelog": "変更履歴を見る",
|
||||
"contributors-desc": "{count}人の<b>素晴らしい</b>コントリビューターに感謝!",
|
||||
"contributors-description-plural": "{count}人の<b>素晴らしい</b>コントリビューターに感謝!",
|
||||
@@ -658,6 +660,9 @@
|
||||
"noctalia-title": "Noctalia shell",
|
||||
"privacy-policy": "プライバシーポリシー",
|
||||
"support": "支援する",
|
||||
"supporter-badge": "サポーター",
|
||||
"supporters-desc-singular": "素晴らしいサポーターに心からの感謝を!",
|
||||
"supporters-loading": "サポーターを読み込み中...",
|
||||
"system-cpu": "CPU:",
|
||||
"system-disk": "ディスク:",
|
||||
"system-gpu": "GPU:",
|
||||
|
||||
@@ -469,6 +469,7 @@
|
||||
"sources": "소스",
|
||||
"start": "시작",
|
||||
"stop": "중지",
|
||||
"supporters": "후원자",
|
||||
"suspend": "대기 모드",
|
||||
"templates": "템플릿",
|
||||
"tertiary": "세번째",
|
||||
@@ -646,6 +647,7 @@
|
||||
},
|
||||
"panels": {
|
||||
"about": {
|
||||
"become-supporter": "후원자 되기",
|
||||
"changelog": "변경 로그 보기",
|
||||
"contributors-desc": "{count}명의 <b>멋진</b> 기여자에게 감사를 전합니다!",
|
||||
"contributors-description-plural": "{count}명의 <b>멋진</b> 기여자들에게 감사를 전합니다!",
|
||||
@@ -658,6 +660,9 @@
|
||||
"noctalia-title": "Noctalia 셸",
|
||||
"privacy-policy": "개인정보 처리방침",
|
||||
"support": "후원하기",
|
||||
"supporter-badge": "후원자",
|
||||
"supporters-desc-singular": "멋진 후원자분께 진심으로 감사드립니다!",
|
||||
"supporters-loading": "후원자 불러오는 중...",
|
||||
"system-cpu": "CPU:",
|
||||
"system-disk": "디스크:",
|
||||
"system-gpu": "GPU:",
|
||||
|
||||
@@ -469,6 +469,7 @@
|
||||
"sources": "Bronnen",
|
||||
"start": "Begin",
|
||||
"stop": "Stop",
|
||||
"supporters": "Ondersteuners",
|
||||
"suspend": "Onderbreken",
|
||||
"templates": "Sjablonen",
|
||||
"tertiary": "Tertiair",
|
||||
@@ -646,6 +647,7 @@
|
||||
},
|
||||
"panels": {
|
||||
"about": {
|
||||
"become-supporter": "Word supporter",
|
||||
"changelog": "Bekijk wijzigingslogboek",
|
||||
"contributors-desc": "Een shout-out naar onze {count} <b>geweldige</b> bijdrager!",
|
||||
"contributors-description-plural": "Een shout-out naar onze {count} <b>geweldige</b> bijdragers!",
|
||||
@@ -658,6 +660,9 @@
|
||||
"noctalia-title": "Noctalia-shell",
|
||||
"privacy-policy": "Privacybeleid",
|
||||
"support": "Steun ons",
|
||||
"supporter-badge": "Supporter",
|
||||
"supporters-desc-singular": "Een enorme dank aan onze geweldige supporter!",
|
||||
"supporters-loading": "Donateurs laden...",
|
||||
"system-cpu": "CPU:",
|
||||
"system-disk": "Schijf:",
|
||||
"system-gpu": "GPU:",
|
||||
|
||||
@@ -469,6 +469,7 @@
|
||||
"sources": "Źródła",
|
||||
"start": "Start",
|
||||
"stop": "Stop",
|
||||
"supporters": "Wspierający",
|
||||
"suspend": "Wstrzymaj",
|
||||
"templates": "Szablony",
|
||||
"tertiary": "Trzeciorzędowy",
|
||||
@@ -646,6 +647,7 @@
|
||||
},
|
||||
"panels": {
|
||||
"about": {
|
||||
"become-supporter": "Zostań wspierającym",
|
||||
"changelog": "Zobacz dziennik zmian",
|
||||
"contributors-desc": "Podziękowania dla naszego {count} <b>niesamowitego</b> współtwórcy!",
|
||||
"contributors-description-plural": "Podziękowania dla naszych {count} <b>niesamowitych</b> współtwórców!",
|
||||
@@ -658,6 +660,9 @@
|
||||
"noctalia-title": "Noctalia shell",
|
||||
"privacy-policy": "Polityka prywatności",
|
||||
"support": "Wesprzyj nas",
|
||||
"supporter-badge": "Wspierający",
|
||||
"supporters-desc-singular": "Ogromne podziękowania dla naszego wspaniałego wspierającego!",
|
||||
"supporters-loading": "Ładowanie wspierających...",
|
||||
"system-cpu": "Procesor:",
|
||||
"system-disk": "Dysk:",
|
||||
"system-gpu": "GPU:",
|
||||
|
||||
@@ -469,6 +469,7 @@
|
||||
"sources": "Fontes",
|
||||
"start": "Começar",
|
||||
"stop": "Pare",
|
||||
"supporters": "Apoiadores",
|
||||
"suspend": "Suspender",
|
||||
"templates": "Modelos",
|
||||
"tertiary": "Terciário",
|
||||
@@ -646,6 +647,7 @@
|
||||
},
|
||||
"panels": {
|
||||
"about": {
|
||||
"become-supporter": "Torne-se um apoiador",
|
||||
"changelog": "Ver histórico de alterações",
|
||||
"contributors-desc": "Agradecimentos ao nosso <b>incrível</b> colaborador!",
|
||||
"contributors-description-plural": "Agradecimentos aos nossos {count} <b>incríveis</b> colaboradores!",
|
||||
@@ -658,6 +660,9 @@
|
||||
"noctalia-title": "Shell Noctalia",
|
||||
"privacy-policy": "Política de privacidade",
|
||||
"support": "Apoie-nos",
|
||||
"supporter-badge": "Apoiador",
|
||||
"supporters-desc-singular": "Um enorme obrigado ao nosso incrível apoiador!",
|
||||
"supporters-loading": "Carregando apoiadores...",
|
||||
"system-cpu": "CPU:",
|
||||
"system-disk": "Disco:",
|
||||
"system-gpu": "GPU:",
|
||||
|
||||
@@ -469,6 +469,7 @@
|
||||
"sources": "Источники",
|
||||
"start": "Начать",
|
||||
"stop": "Стоп",
|
||||
"supporters": "Поддерживающие",
|
||||
"suspend": "Приостановить",
|
||||
"templates": "Шаблоны",
|
||||
"tertiary": "Третичный",
|
||||
@@ -646,6 +647,7 @@
|
||||
},
|
||||
"panels": {
|
||||
"about": {
|
||||
"become-supporter": "Стать спонсором",
|
||||
"changelog": "Посмотреть список изменений",
|
||||
"contributors-desc": "Благодарим нашего <b>замечательного</b> участника: {count}!",
|
||||
"contributors-description-plural": "Благодарим наших <b>замечательных</b> участников: {count}!",
|
||||
@@ -658,6 +660,9 @@
|
||||
"noctalia-title": "Оболочка Noctalia",
|
||||
"privacy-policy": "Политика конфиденциальности",
|
||||
"support": "Поддержать нас",
|
||||
"supporter-badge": "Сторонник",
|
||||
"supporters-desc-singular": "Огромное спасибо нашему замечательному стороннику!",
|
||||
"supporters-loading": "Загрузка спонсоров...",
|
||||
"system-cpu": "ЦП:",
|
||||
"system-disk": "Диск:",
|
||||
"system-gpu": "Графический процессор",
|
||||
|
||||
@@ -469,6 +469,7 @@
|
||||
"sources": "Källor",
|
||||
"start": "Starta",
|
||||
"stop": "Stoppa",
|
||||
"supporters": "Stödjare",
|
||||
"suspend": "Avbryt",
|
||||
"templates": "Mallar",
|
||||
"tertiary": "Tertiär",
|
||||
@@ -646,6 +647,7 @@
|
||||
},
|
||||
"panels": {
|
||||
"about": {
|
||||
"become-supporter": "Bli supporter",
|
||||
"changelog": "Visa ändringslogg",
|
||||
"contributors-desc": "Tack till våra {count} <b>fantastiska</b> bidragsgivare!",
|
||||
"contributors-description-plural": "Tack till våra {count} <b>fantastiska</b> bidragsgivare!",
|
||||
@@ -658,6 +660,9 @@
|
||||
"noctalia-title": "Noctalia-skal",
|
||||
"privacy-policy": "Sekretesspolicy",
|
||||
"support": "Stöd oss",
|
||||
"supporter-badge": "Supporter",
|
||||
"supporters-desc-singular": "Ett stort tack till vår fantastiska supporter!",
|
||||
"supporters-loading": "Laddar supportrar...",
|
||||
"system-cpu": "CPU:",
|
||||
"system-disk": "Disk:",
|
||||
"system-gpu": "GPU:",
|
||||
|
||||
@@ -469,6 +469,7 @@
|
||||
"sources": "Kaynaklar",
|
||||
"start": "Başlat",
|
||||
"stop": "Dur",
|
||||
"supporters": "Destekçiler",
|
||||
"suspend": "Askıya al",
|
||||
"templates": "Şablonlar",
|
||||
"tertiary": "Üçüncül",
|
||||
@@ -646,6 +647,7 @@
|
||||
},
|
||||
"panels": {
|
||||
"about": {
|
||||
"become-supporter": "Destekçi ol",
|
||||
"changelog": "Değişiklik günlüğünü görüntüle",
|
||||
"contributors-desc": "{count} <b>harika</b> katılımcımıza <b>teşekkürler</b>!",
|
||||
"contributors-description-plural": "{count} <b>harika</b> katılımcımıza <b>teşekkürler</b>!",
|
||||
@@ -658,6 +660,9 @@
|
||||
"noctalia-title": "Noctalia kabuğu",
|
||||
"privacy-policy": "Gizlilik politikası",
|
||||
"support": "Bizi destekleyin",
|
||||
"supporter-badge": "Destekçi",
|
||||
"supporters-desc-singular": "Harika destekçimize kocaman bir teşekkür!",
|
||||
"supporters-loading": "Destekçiler yükleniyor...",
|
||||
"system-cpu": "İşlemci:",
|
||||
"system-disk": "Disk:",
|
||||
"system-gpu": "GPU:",
|
||||
|
||||
@@ -469,6 +469,7 @@
|
||||
"sources": "Джерела",
|
||||
"start": "Почати",
|
||||
"stop": "Зупиніться",
|
||||
"supporters": "Прихильники",
|
||||
"suspend": "Призупинити",
|
||||
"templates": "Шаблони",
|
||||
"tertiary": "Третинний",
|
||||
@@ -646,6 +647,7 @@
|
||||
},
|
||||
"panels": {
|
||||
"about": {
|
||||
"become-supporter": "Стати прихильником",
|
||||
"changelog": "Переглянути журнал змін",
|
||||
"contributors-desc": "Подяка нашому {count} <b>чудовому</b> учаснику!",
|
||||
"contributors-description-plural": "Подяка нашим {count} <b>чудовим</b> учасникам!",
|
||||
@@ -658,6 +660,9 @@
|
||||
"noctalia-title": "Оболонка Noctalia",
|
||||
"privacy-policy": "Політика конфіденційності",
|
||||
"support": "Підтримати нас",
|
||||
"supporter-badge": "Прихильник",
|
||||
"supporters-desc-singular": "Величезне дякую нашому чудовому прихильнику!",
|
||||
"supporters-loading": "Завантаження прихильників...",
|
||||
"system-cpu": "ЦП:",
|
||||
"system-disk": "Диск:",
|
||||
"system-gpu": "GPU:",
|
||||
|
||||
@@ -469,6 +469,7 @@
|
||||
"sources": "来源",
|
||||
"start": "开始",
|
||||
"stop": "停止",
|
||||
"supporters": "支持者",
|
||||
"suspend": "挂起",
|
||||
"templates": "模板",
|
||||
"tertiary": "第三",
|
||||
@@ -646,6 +647,7 @@
|
||||
},
|
||||
"panels": {
|
||||
"about": {
|
||||
"become-supporter": "成为支持者",
|
||||
"changelog": "查看更改日志",
|
||||
"contributors-desc": "向我们 {count} 位<b>超棒的</b>贡献者致敬!",
|
||||
"contributors-description-plural": "向我们 {count} 位<b>超棒的</b>贡献者致敬!",
|
||||
@@ -658,6 +660,9 @@
|
||||
"noctalia-title": "Noctalia shell",
|
||||
"privacy-policy": "隐私政策",
|
||||
"support": "支持我们",
|
||||
"supporter-badge": "支持者",
|
||||
"supporters-desc-singular": "非常感谢我们出色的支持者!",
|
||||
"supporters-loading": "正在加载支持者...",
|
||||
"system-cpu": "中央处理器:",
|
||||
"system-disk": "磁盘:",
|
||||
"system-gpu": "图形处理器:",
|
||||
|
||||
@@ -469,6 +469,7 @@
|
||||
"sources": "來源",
|
||||
"start": "開始",
|
||||
"stop": "停止",
|
||||
"supporters": "支持者",
|
||||
"suspend": "暫停",
|
||||
"templates": "模板",
|
||||
"tertiary": "第三",
|
||||
@@ -646,6 +647,7 @@
|
||||
},
|
||||
"panels": {
|
||||
"about": {
|
||||
"become-supporter": "成為支持者",
|
||||
"changelog": "檢視更新日誌",
|
||||
"contributors-desc": "特別感謝我們這{count}位<b>超讚</b>的貢獻者!!",
|
||||
"contributors-description-plural": "特別感謝我們這{count}位<b>超讚</b>的貢獻者!!",
|
||||
@@ -658,6 +660,9 @@
|
||||
"noctalia-title": "Noctalia Shell",
|
||||
"privacy-policy": "隱私權政策",
|
||||
"support": "支持我們",
|
||||
"supporter-badge": "支持者",
|
||||
"supporters-desc-singular": "非常感謝我們出色的支持者!",
|
||||
"supporters-loading": "正在載入支持者...",
|
||||
"system-cpu": "CPU:",
|
||||
"system-disk": "磁碟:",
|
||||
"system-gpu": "GPU:",
|
||||
|
||||
@@ -25,6 +25,11 @@ ColumnLayout {
|
||||
tabIndex: 1
|
||||
checked: subTabBar.currentIndex === 1
|
||||
}
|
||||
NTabButton {
|
||||
text: I18n.tr("common.supporters")
|
||||
tabIndex: 2
|
||||
checked: subTabBar.currentIndex === 2
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
@@ -38,5 +43,6 @@ ColumnLayout {
|
||||
|
||||
VersionSubTab {}
|
||||
ContributorsSubTab {}
|
||||
SupportersSubTab {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,244 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import Quickshell
|
||||
import qs.Commons
|
||||
import qs.Services.Noctalia
|
||||
import qs.Services.UI
|
||||
import qs.Widgets
|
||||
|
||||
ColumnLayout {
|
||||
id: root
|
||||
|
||||
property var supporters: SupporterService.supporters
|
||||
property int avatarCacheVersion: 0
|
||||
|
||||
Connections {
|
||||
target: SupporterService
|
||||
function onCachedAvatarsChanged() {
|
||||
root.avatarCacheVersion++;
|
||||
}
|
||||
}
|
||||
|
||||
spacing: Style.marginL
|
||||
|
||||
NHeader {
|
||||
description: root.supporters.length === 0 ? I18n.tr("panels.about.supporters-loading") : root.supporters.length === 1 ? I18n.tr("panels.about.supporters-desc-singular", {
|
||||
"count": 1
|
||||
}) : I18n.tr("panels.about.supporters-desc-plural", {
|
||||
"count": root.supporters.length
|
||||
})
|
||||
enableDescriptionRichText: true
|
||||
}
|
||||
|
||||
NButton {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
icon: "heart"
|
||||
text: I18n.tr("panels.about.become-supporter")
|
||||
outlined: true
|
||||
onClicked: {
|
||||
Quickshell.execDetached(["xdg-open", "https://buymeacoffee.com/noctalia"]);
|
||||
ToastService.showNotice(I18n.tr("panels.about.support"), I18n.tr("toast.donation-opened"));
|
||||
}
|
||||
}
|
||||
|
||||
NDivider {
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
}
|
||||
|
||||
// Supporter cards
|
||||
Flow {
|
||||
id: supportersFlow
|
||||
visible: root.supporters.length > 0
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.fillWidth: true
|
||||
spacing: Style.marginL
|
||||
|
||||
Repeater {
|
||||
model: root.supporters.length
|
||||
|
||||
delegate: Rectangle {
|
||||
id: supporterCard
|
||||
|
||||
property bool hasGithub: !!root.supporters[index].github_username
|
||||
|
||||
width: Math.max(Math.round(supportersFlow.width / 2 - Style.marginL - 1), Math.round(Style.baseWidgetSize * 4.5))
|
||||
height: Math.round(Style.baseWidgetSize * 2.6)
|
||||
radius: Style.radiusM
|
||||
color: supporterArea.containsMouse && hasGithub ? Color.mHover : Qt.alpha(Color.mPrimary, 0.05)
|
||||
border.width: Style.borderM
|
||||
border.color: supporterArea.containsMouse && hasGithub ? Color.mPrimary : Qt.alpha(Color.mPrimary, 0.5)
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: Style.animationFast
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on border.color {
|
||||
ColorAnimation {
|
||||
duration: Style.animationFast
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
anchors.fill: parent
|
||||
anchors.margins: Style.marginM
|
||||
spacing: Style.marginM
|
||||
|
||||
// Avatar with heart badge
|
||||
Item {
|
||||
id: avatarWrapper
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
Layout.preferredWidth: Style.baseWidgetSize * 2.0
|
||||
Layout.preferredHeight: Style.baseWidgetSize * 2.0
|
||||
|
||||
property bool isRounded: false
|
||||
|
||||
Item {
|
||||
anchors.fill: parent
|
||||
|
||||
Image {
|
||||
anchors.fill: parent
|
||||
visible: supporterCard.hasGithub
|
||||
source: {
|
||||
if (!supporterCard.hasGithub)
|
||||
return "";
|
||||
var _ = root.avatarCacheVersion;
|
||||
var username = root.supporters[index].github_username;
|
||||
var cached = SupporterService.getAvatarPath(username);
|
||||
if (cached) {
|
||||
avatarWrapper.isRounded = true;
|
||||
return cached;
|
||||
}
|
||||
return "https://github.com/" + username + ".png?size=256";
|
||||
}
|
||||
fillMode: Image.PreserveAspectFit
|
||||
mipmap: true
|
||||
smooth: true
|
||||
asynchronous: true
|
||||
opacity: status === Image.Ready ? 1.0 : 0.0
|
||||
|
||||
Behavior on opacity {
|
||||
NumberAnimation {
|
||||
duration: Style.animationFast
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback logo for supporters without GitHub
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
visible: !supporterCard.hasGithub
|
||||
radius: width * 0.5
|
||||
color: Qt.alpha(Color.mPrimary, 0.15)
|
||||
|
||||
Image {
|
||||
anchors.centerIn: parent
|
||||
source: "../../../../../Assets/noctalia.svg"
|
||||
width: parent.width * 0.8
|
||||
height: width
|
||||
fillMode: Image.PreserveAspectFit
|
||||
mipmap: true
|
||||
smooth: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
visible: avatarWrapper.isRounded
|
||||
anchors.fill: parent
|
||||
color: "transparent"
|
||||
radius: width * 0.5
|
||||
border.width: Style.borderM
|
||||
border.color: Color.mPrimary
|
||||
}
|
||||
|
||||
// Heart badge
|
||||
Rectangle {
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.rightMargin: -2
|
||||
anchors.bottomMargin: -2
|
||||
width: Style.fontSizeM + Style.marginS
|
||||
height: width
|
||||
radius: width * 0.5
|
||||
color: Color.mPrimary
|
||||
|
||||
NIcon {
|
||||
anchors.centerIn: parent
|
||||
icon: "heart-filled"
|
||||
pointSize: Style.fontSizeXS
|
||||
color: Color.mOnPrimary
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Info column
|
||||
ColumnLayout {
|
||||
spacing: 2
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
Layout.fillWidth: true
|
||||
|
||||
NText {
|
||||
text: root.supporters[index].name || root.supporters[index].github_username || "Unknown"
|
||||
font.weight: Style.fontWeightBold
|
||||
color: supporterArea.containsMouse && supporterCard.hasGithub ? Color.mOnHover : Color.mOnSurface
|
||||
elide: Text.ElideRight
|
||||
Layout.fillWidth: true
|
||||
pointSize: Style.fontSizeS
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
spacing: Style.marginXS
|
||||
Layout.fillWidth: true
|
||||
|
||||
NIcon {
|
||||
icon: "heart"
|
||||
pointSize: Style.fontSizeXS
|
||||
color: Color.mPrimary
|
||||
}
|
||||
|
||||
NText {
|
||||
text: I18n.tr("panels.about.supporter-badge")
|
||||
pointSize: Style.fontSizeXS
|
||||
color: Color.mPrimary
|
||||
font.weight: Style.fontWeightMedium
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Hover indicator (only for supporters with GitHub)
|
||||
NIcon {
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
icon: "arrow-right"
|
||||
pointSize: Style.fontSizeS
|
||||
color: Color.mPrimary
|
||||
visible: supporterCard.hasGithub
|
||||
opacity: supporterArea.containsMouse ? 1.0 : 0.0
|
||||
|
||||
Behavior on opacity {
|
||||
NumberAnimation {
|
||||
duration: Style.animationFast
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: supporterArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: supporterCard.hasGithub ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||
onClicked: {
|
||||
var username = root.supporters[index].github_username;
|
||||
if (username) {
|
||||
Quickshell.execDetached(["xdg-open", "https://github.com/" + username]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -515,7 +515,7 @@ ColumnLayout {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
onClicked: {
|
||||
Quickshell.execDetached(["xdg-open", "https://buymeacoffee.com/noctalia"]);
|
||||
ToastService.showNotice(I18n.tr("panels.about.support"), I18n.tr("toast.kofi-opened"));
|
||||
ToastService.showNotice(I18n.tr("panels.about.support"), I18n.tr("toast.donation-opened"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,169 @@
|
||||
pragma Singleton
|
||||
|
||||
import QtQuick
|
||||
import Quickshell
|
||||
import Quickshell.Io
|
||||
import qs.Commons
|
||||
import qs.Services.UI
|
||||
|
||||
Singleton {
|
||||
id: root
|
||||
|
||||
property string supporterDataFile: Settings.cacheDir + "supporters.json"
|
||||
property int updateFrequency: 60 * 60 // 1 hour in seconds
|
||||
property bool isFetching: false
|
||||
property bool isInitialized: false
|
||||
|
||||
readonly property alias data: adapter
|
||||
|
||||
property var supporters: []
|
||||
property var cachedAvatars: ({}) // username -> file:// path
|
||||
property bool avatarsCached: false
|
||||
|
||||
FileView {
|
||||
id: supporterDataFileView
|
||||
path: supporterDataFile
|
||||
printErrors: false
|
||||
watchChanges: false
|
||||
|
||||
onLoaded: {
|
||||
if (!root.isInitialized) {
|
||||
root.isInitialized = true;
|
||||
loadFromCache();
|
||||
}
|
||||
}
|
||||
onLoadFailed: function (error) {
|
||||
if (error.toString().includes("No such file") || error === 2) {
|
||||
root.isInitialized = true;
|
||||
fetchFromApi();
|
||||
}
|
||||
}
|
||||
|
||||
JsonAdapter {
|
||||
id: adapter
|
||||
property var supporters: []
|
||||
property real timestamp: 0
|
||||
}
|
||||
}
|
||||
|
||||
function init() {
|
||||
Logger.i("Supporter", "Service started");
|
||||
}
|
||||
|
||||
function loadFromCache() {
|
||||
const now = Time.timestamp;
|
||||
var needsRefetch = false;
|
||||
|
||||
if (!data.timestamp || (now >= data.timestamp + updateFrequency)) {
|
||||
needsRefetch = true;
|
||||
Logger.i("Supporter", "Cache expired or missing, scheduling fetch");
|
||||
} else {
|
||||
Logger.i("Supporter", "Cache is fresh, using cached data");
|
||||
}
|
||||
|
||||
if (data.supporters && data.supporters.length > 0) {
|
||||
root.supporters = data.supporters;
|
||||
Logger.d("Supporter", "Loaded", data.supporters.length, "supporters from cache");
|
||||
}
|
||||
|
||||
if (needsRefetch) {
|
||||
fetchFromApi();
|
||||
}
|
||||
}
|
||||
|
||||
function fetchFromApi() {
|
||||
if (isFetching) {
|
||||
Logger.d("Supporter", "Already fetching");
|
||||
return;
|
||||
}
|
||||
|
||||
isFetching = true;
|
||||
supporterProcess.running = true;
|
||||
}
|
||||
|
||||
function saveData() {
|
||||
data.timestamp = Time.timestamp;
|
||||
Quickshell.execDetached(["mkdir", "-p", Settings.cacheDir]);
|
||||
|
||||
try {
|
||||
supporterDataFileView.writeAdapter();
|
||||
Logger.d("Supporter", "Cache file written successfully");
|
||||
} catch (error) {
|
||||
Logger.e("Supporter", "Failed to write cache file:", error);
|
||||
}
|
||||
}
|
||||
|
||||
function getAvatarPath(username) {
|
||||
return cachedAvatars[username] || "";
|
||||
}
|
||||
|
||||
function cacheAvatars() {
|
||||
if (supporters.length === 0)
|
||||
return;
|
||||
|
||||
avatarsCached = true;
|
||||
|
||||
for (var i = 0; i < supporters.length; i++) {
|
||||
var supporter = supporters[i];
|
||||
var username = supporter.github_username;
|
||||
|
||||
// Only cache avatars for supporters with GitHub accounts
|
||||
if (!username)
|
||||
continue;
|
||||
|
||||
var avatarUrl = "https://github.com/" + username + ".png?size=256";
|
||||
|
||||
(function (uname, url) {
|
||||
ImageCacheService.getCircularAvatar(url, "supporter_" + uname, function (cachedPath, success) {
|
||||
if (success) {
|
||||
cachedAvatars[uname] = "file://" + cachedPath;
|
||||
cachedAvatarsChanged();
|
||||
}
|
||||
});
|
||||
})(username, avatarUrl);
|
||||
}
|
||||
}
|
||||
|
||||
onSupportersChanged: {
|
||||
if (supporters.length > 0 && !avatarsCached && ImageCacheService.initialized) {
|
||||
Qt.callLater(cacheAvatars);
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: ImageCacheService
|
||||
function onInitializedChanged() {
|
||||
if (ImageCacheService.initialized && supporters.length > 0 && !avatarsCached) {
|
||||
Qt.callLater(cacheAvatars);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Process {
|
||||
id: supporterProcess
|
||||
|
||||
command: ["curl", "-s", "https://noctalia.dev:7777/supporters"]
|
||||
|
||||
stdout: StdioCollector {
|
||||
onStreamFinished: {
|
||||
try {
|
||||
const response = text;
|
||||
if (response && response.trim()) {
|
||||
const parsed = JSON.parse(response);
|
||||
if (Array.isArray(parsed)) {
|
||||
root.data.supporters = parsed;
|
||||
root.supporters = parsed;
|
||||
root.saveData();
|
||||
Logger.d("Supporter", "Fetched", parsed.length, "supporters");
|
||||
} else if (parsed.message) {
|
||||
Logger.w("Supporter", "API error:", parsed.message);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
Logger.e("Supporter", "Failed to parse response:", e);
|
||||
}
|
||||
root.isFetching = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user