v1.1.0: English UI + docs, bundled Bitcoin icon, canonical config page, gitea.a14r.be website URL, journal diagnostics
This commit is contained in:
+66
-35
@@ -1,14 +1,14 @@
|
||||
/*
|
||||
* nl.a14r.bitcoinprice — KDE Plasma 5 widget
|
||||
*
|
||||
* Toont de bitcoinprijs in EUR (CoinGecko API).
|
||||
* - Groen : prijs gestegen t.o.v. vorige meting
|
||||
* - Rood : prijs gedaald t.o.v. vorige meting
|
||||
* - Grijs : gelijk gebleven (of eerste meting)
|
||||
* - "--" : API-fout (netwerkfout, 4xx/5xx, rate limit 429)
|
||||
* Shows the bitcoin price in EUR (CoinGecko API).
|
||||
* - Green : price up compared to the previous reading
|
||||
* - Red : price down compared to the previous reading
|
||||
* - Grey : unchanged (or first reading)
|
||||
* - "--" : API failure (network error, 4xx/5xx, 429 rate limit)
|
||||
*
|
||||
* Vernieuwinterval: configureerbaar, minimaal 5 minuten
|
||||
* (CoinGecko limiet: 1 call per 5 minuten).
|
||||
* Refresh interval: configurable, minimum 5 minutes
|
||||
* (CoinGecko limit: 1 call per 5 minutes).
|
||||
*/
|
||||
|
||||
import QtQuick 2.15
|
||||
@@ -22,42 +22,47 @@ Item {
|
||||
readonly property int refreshMinutes: Math.max(5, plasmoid.configuration.refreshMinutes)
|
||||
readonly property string apiUrl: "https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=eur"
|
||||
|
||||
// -1 = gedaald, 0 = gelijk / nog geen vorige meting, 1 = gestegen
|
||||
// -1 = down, 0 = unchanged / no previous reading yet, 1 = up
|
||||
property int trend: 0
|
||||
property double lastPrice: NaN // laatste succesvol opgehaalde prijs
|
||||
property double lastPrice: NaN // last successfully fetched price
|
||||
property string state: "init" // init | ok | error
|
||||
property string lastUpdated: "" // HH:mm:ss van laatste succesvolle update
|
||||
property string lastUpdated: "" // HH:mm:ss of the last successful update
|
||||
|
||||
readonly property string displayText: {
|
||||
if (state !== "ok" || isNaN(lastPrice)) {
|
||||
return "--";
|
||||
}
|
||||
return "\u20BF " + Number(lastPrice).toLocaleString(Qt.locale(), "f", 0) + " \u20AC";
|
||||
return Number(lastPrice).toLocaleString(Qt.locale(), "f", 0) + " \u20AC";
|
||||
}
|
||||
|
||||
readonly property color priceColor: {
|
||||
if (state !== "ok" || isNaN(lastPrice)) {
|
||||
return PlasmaCore.Theme.disabledTextColor; // "--" bij fout/init
|
||||
return PlasmaCore.Theme.disabledTextColor; // "--" on error/init
|
||||
}
|
||||
if (trend > 0) {
|
||||
return "#2ecc71"; // groen
|
||||
return "#2ecc71"; // green
|
||||
}
|
||||
if (trend < 0) {
|
||||
return "#e74c3c"; // rood
|
||||
return "#e74c3c"; // red
|
||||
}
|
||||
return "#9e9e9e"; // grijs
|
||||
return "#9e9e9e"; // grey
|
||||
}
|
||||
|
||||
readonly property string statusText: {
|
||||
if (state === "error") {
|
||||
return lastUpdated === ""
|
||||
? i18n("API-fout")
|
||||
: i18n("API-fout — laatste geldige prijs: %1", lastUpdated);
|
||||
? i18n("API error")
|
||||
: i18n("API error — last known price: %1", lastUpdated);
|
||||
}
|
||||
if (lastUpdated === "") {
|
||||
return i18n("Bezig met ophalen\u2026");
|
||||
return i18n("Fetching\u2026");
|
||||
}
|
||||
return i18n("Laatst bijgewerkt: %1", lastUpdated);
|
||||
return i18n("Last updated: %1", lastUpdated);
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
console.log("[bitcoinprice] started, refresh interval:",
|
||||
refreshMinutes, "minutes");
|
||||
}
|
||||
|
||||
Plasmoid.backgroundHints: PlasmaCore.Types.StandardBackground
|
||||
@@ -70,22 +75,38 @@ Item {
|
||||
Item {
|
||||
id: compact
|
||||
|
||||
Layout.minimumWidth: priceLabel.implicitWidth + PlasmaCore.Units.smallSpacing * 2
|
||||
Layout.minimumWidth: row.implicitWidth + PlasmaCore.Units.smallSpacing * 2
|
||||
Layout.minimumHeight: PlasmaCore.Units.iconSizes.smallMedium
|
||||
|
||||
Text {
|
||||
id: priceLabel
|
||||
Row {
|
||||
id: row
|
||||
anchors.centerIn: parent
|
||||
text: root.displayText
|
||||
color: root.priceColor
|
||||
textFormat: Text.PlainText
|
||||
elide: Text.ElideRight
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
font.family: PlasmaCore.Theme.defaultFont.family
|
||||
font.pixelSize: compact.height > PlasmaCore.Units.iconSizes.small
|
||||
? Math.round(compact.height * 0.6)
|
||||
: PlasmaCore.Theme.defaultFont.pixelSize
|
||||
spacing: PlasmaCore.Units.smallSpacing
|
||||
|
||||
Image {
|
||||
id: btcIcon
|
||||
source: "../images/bitcoin.svg"
|
||||
sourceSize.width: PlasmaCore.Units.iconSizes.smallMedium
|
||||
sourceSize.height: PlasmaCore.Units.iconSizes.smallMedium
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
fillMode: Image.PreserveAspectFit
|
||||
visible: root.state === "ok"
|
||||
}
|
||||
|
||||
Text {
|
||||
id: priceLabel
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: root.displayText
|
||||
color: root.priceColor
|
||||
textFormat: Text.PlainText
|
||||
elide: Text.ElideRight
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
font.family: PlasmaCore.Theme.defaultFont.family
|
||||
font.pixelSize: compact.height > PlasmaCore.Units.iconSizes.small
|
||||
? Math.round(compact.height * 0.6)
|
||||
: PlasmaCore.Theme.defaultFont.pixelSize
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -95,12 +116,21 @@ Item {
|
||||
id: fullRep
|
||||
|
||||
implicitWidth: PlasmaCore.Units.gridUnit * 14
|
||||
implicitHeight: PlasmaCore.Units.gridUnit * 7
|
||||
implicitHeight: PlasmaCore.Units.gridUnit * 9
|
||||
|
||||
Column {
|
||||
anchors.centerIn: parent
|
||||
spacing: PlasmaCore.Units.smallSpacing
|
||||
|
||||
Image {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
source: "../images/bitcoin.svg"
|
||||
sourceSize.width: PlasmaCore.Units.iconSizes.large
|
||||
sourceSize.height: PlasmaCore.Units.iconSizes.large
|
||||
fillMode: Image.PreserveAspectFit
|
||||
visible: root.state === "ok"
|
||||
}
|
||||
|
||||
Text {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
text: root.displayText
|
||||
@@ -141,14 +171,15 @@ Item {
|
||||
try {
|
||||
var price = JSON.parse(xhr.responseText).bitcoin.eur;
|
||||
if (typeof price === "number" && !isNaN(price)) {
|
||||
console.log("[bitcoinprice] fetched EUR", price);
|
||||
root.applyPrice(price);
|
||||
return;
|
||||
}
|
||||
} catch (e) {
|
||||
// ongeldige JSON → val door naar de foutafhandeling
|
||||
// invalid JSON → fall through to error handling
|
||||
}
|
||||
}
|
||||
// API-fout (netwerk, 4xx/5xx, rate limit 429, onverwachte payload)
|
||||
console.log("[bitcoinprice] fetch failed, HTTP status:", xhr.status);
|
||||
root.state = "error";
|
||||
};
|
||||
xhr.send();
|
||||
|
||||
Reference in New Issue
Block a user