aboutsummaryrefslogtreecommitdiffstats
path: root/desktop
diff options
context:
space:
mode:
Diffstat (limited to 'desktop')
-rw-r--r--desktop/modules/updates/UpdatesPage.qml136
1 files changed, 106 insertions, 30 deletions
diff --git a/desktop/modules/updates/UpdatesPage.qml b/desktop/modules/updates/UpdatesPage.qml
index 967b0e0..2cce13c 100644
--- a/desktop/modules/updates/UpdatesPage.qml
+++ b/desktop/modules/updates/UpdatesPage.qml
@@ -23,23 +23,30 @@ Column {
spacing: 16
+ // Rows carry `from` and `to` apart so the target can stand out; a row
+ // with a single value (new, removed) leaves `from` empty.
function tracked(list) {
- return list.map(r => ({ name: r.name, repo: r.repo, ver: r.from + " → " + r.to }));
+ return list.map(r => ({ name: r.name, repo: r.repo, from: r.from, to: r.to }));
}
readonly property var sections: !d ? [] : [
{ title: "Slackware upgrades", err: d.errors.mirror || "",
- rows: d.slackware.upgrade.map(r => ({ name: r.name, repo: "", ver: r.from + " → " + r.to })) },
+ rows: d.slackware.upgrade.map(r => ({ name: r.name, repo: "", from: r.from, to: r.to })) },
{ title: "New in Slackware", err: "",
- rows: d.slackware.new.map(r => ({ name: r.name, repo: "", ver: r.version })) },
+ rows: d.slackware.new.map(r => ({ name: r.name, repo: "", from: "", to: r.version })) },
{ title: "Removed from Slackware", err: "",
- rows: d.slackware.removed.map(r => ({ name: r.name, repo: "", ver: "removed " + r.date })) },
+ rows: d.slackware.removed.map(r => ({ name: r.name, repo: "", from: "", to: "removed " + r.date })) },
{ title: "Upgrade here", err: d.errors.repo || "", rows: tracked(d.upgrade) },
{ title: "Awaiting build", err: "", rows: tracked(d.build) },
{ title: "Upstream newer", err: d.errors.nvchecker || "", rows: tracked(d.upstream) },
{ title: "App updates", err: "", rows: tracked(d.apps) },
]
+ function repoColor(r) {
+ return { "personal": Theme.blue, "my-sbo": Theme.mauve, "pentesting": Theme.peach,
+ "SBo": Theme.teal }[r] || Theme.overlay;
+ }
+
function ago(t) {
const m = Math.round((Date.now() / 1000 - t) / 60);
return m < 1 ? "just now" : m < 60 ? m + " min ago" : Math.round(m / 60) + " h ago";
@@ -50,61 +57,130 @@ Column {
&& page.d.upstream.length === 0 && page.d.apps.length === 0
text: "Up to date"
color: Theme.subtext
- font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 2 }
+ font { family: Theme.fontFamily; pixelSize: Theme.fontSize }
}
Repeater {
model: page.sections
Column {
+ id: section
required property var modelData
width: page.width
- spacing: 4
+ spacing: 2
visible: modelData.rows.length > 0 || modelData.err !== ""
- Text {
- text: modelData.title + (modelData.rows.length ? " " + modelData.rows.length : "")
- color: Theme.text
- font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 1; bold: true }
+ // A long section starts folded, so 471 Slackware upgrades do not
+ // bury everything below them. A refresh rebuilds the delegates
+ // and folds it again.
+ property bool open: modelData.rows.length <= 10
+
+ Item {
+ width: page.width
+ height: heading.implicitHeight + 6
+
+ Row {
+ id: heading
+ anchors.verticalCenter: parent.verticalCenter
+ spacing: 8
+
+ Text {
+ anchors.verticalCenter: parent.verticalCenter
+ width: 14
+ text: section.open ? "\uf078" : "\uf054"
+ color: Theme.subtext
+ font { family: Theme.iconFamily; pixelSize: Theme.fontSize - 3 }
+ }
+ Text {
+ text: section.modelData.title
+ color: Theme.text
+ font { family: Theme.fontFamily; pixelSize: Theme.fontSize + 1; bold: true }
+ }
+ Text {
+ anchors.verticalCenter: parent.verticalCenter
+ visible: section.modelData.rows.length > 0
+ text: section.modelData.rows.length
+ color: Theme.subtext
+ font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 1 }
+ }
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ cursorShape: Qt.PointingHandCursor
+ onClicked: section.open = !section.open
+ }
}
Text {
- visible: modelData.err !== ""
- text: modelData.err
+ visible: section.modelData.err !== ""
+ text: section.modelData.err
color: Theme.subtext
- font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 3; italic: true }
+ font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 1; italic: true }
}
Repeater {
- model: modelData.rows
+ model: section.open ? section.modelData.rows : []
- Item {
+ Rectangle {
required property var modelData
+ required property int index
width: page.width
- height: 22
+ height: 26
+ radius: 4
+ // Every other row shaded, to carry the eye from the name
+ // across to its version.
+ color: index % 2 ? Qt.alpha(Theme.surface, 0.45) : "transparent"
Text {
- anchors { left: parent.left; right: repo.left; rightMargin: 8; verticalCenter: parent.verticalCenter }
+ anchors { left: parent.left; leftMargin: 8; right: repo.left; rightMargin: 8; verticalCenter: parent.verticalCenter }
elide: Text.ElideRight
textFormat: Text.PlainText
text: modelData.name
color: Theme.text
- font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 3 }
+ font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 1 }
}
- Text {
+ // The repo as a pill, one colour per repo. Never red, green,
+ // yellow or the accent: those carry meaning elsewhere.
+ Rectangle {
id: repo
- anchors { right: ver.left; rightMargin: 12; verticalCenter: parent.verticalCenter }
- text: modelData.repo
- color: Theme.subtext
- font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 4 }
+ readonly property color tint: page.repoColor(modelData.repo)
+ anchors { right: ver.left; rightMargin: 16; verticalCenter: parent.verticalCenter }
+ visible: modelData.repo !== ""
+ width: visible ? repoText.implicitWidth + 14 : 0
+ height: repoText.implicitHeight + 4
+ radius: height / 2
+ color: Qt.alpha(tint, 0.18)
+ border { width: 1; color: Qt.alpha(tint, 0.5) }
+
+ Text {
+ id: repoText
+ anchors.centerIn: parent
+ text: modelData.repo
+ color: repo.tint
+ font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 3 }
+ }
}
- Text {
+ // Monospace so digits line up down the column; the
+ // version being moved to is the bright one.
+ Row {
id: ver
- anchors { right: parent.right; verticalCenter: parent.verticalCenter }
- textFormat: Text.PlainText
- text: modelData.ver
- color: Theme.subtext
- font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 3 }
+ anchors { right: parent.right; rightMargin: 8; verticalCenter: parent.verticalCenter }
+ spacing: 6
+
+ Text {
+ visible: modelData.from !== ""
+ textFormat: Text.PlainText
+ text: modelData.from + " →"
+ color: Theme.subtext
+ font { family: Theme.iconFamily; pixelSize: Theme.fontSize - 1 }
+ }
+ Text {
+ textFormat: Text.PlainText
+ text: modelData.to
+ color: Theme.text
+ font { family: Theme.iconFamily; pixelSize: Theme.fontSize - 1 }
+ }
}
}
}
@@ -119,7 +195,7 @@ Column {
text: page.up.checking ? "checking…"
: page.d && page.d.checked ? "checked " + page.ago(page.d.checked) : ""
color: Theme.subtext
- font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 3 }
+ font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 1 }
}
Button {