small component patches + code cleanup
This commit is contained in:
@@ -73,7 +73,6 @@ PanelWindow {
|
||||
item.height = Qt.binding(() => barContent.height - 12)
|
||||
|
||||
const props = {
|
||||
"panelRadius": cfg.radius / 2,
|
||||
"borderWidth": cfg.panelBorderWidth,
|
||||
"isTop": barWindow.isTop,
|
||||
"targetScreen": barWindow.modelData,
|
||||
@@ -95,7 +94,7 @@ PanelWindow {
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
height: parent.height
|
||||
width: Math.max(0, Math.min(leftRow.implicitWidth, barContent.sideMaxWidth))
|
||||
width: Math.min(leftRow.implicitWidth, barContent.sideMaxWidth)
|
||||
clip: true
|
||||
|
||||
Row {
|
||||
@@ -123,7 +122,7 @@ PanelWindow {
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
height: parent.height
|
||||
width: Math.max(0, Math.min(rightRow.implicitWidth, barContent.sideMaxWidth))
|
||||
width: Math.min(rightRow.implicitWidth, barContent.sideMaxWidth)
|
||||
clip: true
|
||||
|
||||
Row {
|
||||
|
||||
@@ -51,11 +51,11 @@ ModuleChip {
|
||||
readonly property bool isLow: batReady && !charging && pct <= 30
|
||||
|
||||
readonly property color iconColor: {
|
||||
if (fullCharge) return t.batteryFull ?? t.accent
|
||||
if (charging) return t.batteryCharging ?? t.accent
|
||||
if (isCritical) return t.batteryCritical ?? "#ff5555"
|
||||
if (isLow) return t.batteryLow ?? "#ffb86c"
|
||||
return t.batteryIcon ?? t.clockIcon
|
||||
if (fullCharge) return t.batteryFull
|
||||
if (charging) return t.batteryCharging
|
||||
if (isCritical) return t.batteryCritical
|
||||
if (isLow) return t.batteryLow
|
||||
return t.batteryIcon
|
||||
}
|
||||
|
||||
readonly property var up: UPower
|
||||
@@ -92,21 +92,17 @@ ModuleChip {
|
||||
return names
|
||||
}
|
||||
|
||||
chipColor: t.batBg
|
||||
chipColorHovered: t.batBgHover
|
||||
chipBorderColor: t.batBorder
|
||||
chipBorderColorHovered: t.batBorderHover
|
||||
chipHoverEnabled: true
|
||||
chipTapAction: () => batteryPopup.toggle()
|
||||
chipAnimWidth: true
|
||||
|
||||
width: batLayout.implicitWidth + 24
|
||||
height: Cfg.Config.moduleHeight
|
||||
radius: panelRadius
|
||||
|
||||
color: hoverHandler.hovered ? t.batBgHover : t.batBg
|
||||
border.color: hoverHandler.hovered ? t.batBorderHover : t.batBorder
|
||||
border.width: borderWidth
|
||||
|
||||
Behavior on width { NumberAnimation { duration: 250; easing.type: Easing.OutCubic } }
|
||||
Behavior on color { ColorAnimation { duration: 150 } }
|
||||
Behavior on border.color { ColorAnimation { duration: 150 } }
|
||||
|
||||
HoverHandler { id: hoverHandler; cursorShape: Qt.PointingHandCursor }
|
||||
TapHandler { onTapped: batteryPopup.toggle() }
|
||||
|
||||
RowLayout {
|
||||
id: batLayout
|
||||
anchors.centerIn: parent
|
||||
@@ -144,8 +140,8 @@ ModuleChip {
|
||||
font.bold: true
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
|
||||
opacity: (hoverHandler.hovered || batteryPopup.popupOpen) ? 1.0 : 0.0
|
||||
Layout.preferredWidth: (hoverHandler.hovered || batteryPopup.popupOpen)
|
||||
opacity: (root.hovered || batteryPopup.popupOpen) ? 1.0 : 0.0
|
||||
Layout.preferredWidth: (root.hovered || batteryPopup.popupOpen)
|
||||
? implicitWidth : 0
|
||||
clip: true
|
||||
|
||||
@@ -154,40 +150,19 @@ ModuleChip {
|
||||
}
|
||||
}
|
||||
|
||||
PopupPanel {
|
||||
StandardPopup {
|
||||
id: batteryPopup
|
||||
ns: "battery"
|
||||
chipRoot: root
|
||||
cardWidth: 260
|
||||
cardColor: t.batPopupBg
|
||||
cardBorderColor: t.batPopupBorder
|
||||
cardHeight: cardCol.implicitHeight + 28
|
||||
showShadow: true
|
||||
layerEnabled: true
|
||||
|
||||
Rectangle {
|
||||
id: cardShadow
|
||||
anchors.fill: card
|
||||
anchors.margins: -3
|
||||
radius: card.radius + 3
|
||||
color: "transparent"
|
||||
border.color: Qt.rgba(0, 0, 0, 0.35)
|
||||
border.width: 6
|
||||
visible: batteryPopup.popupOpen
|
||||
opacity: batteryPopup.popupOpen ? 0.6 : 0
|
||||
Behavior on opacity { NumberAnimation { duration: 200 } }
|
||||
}
|
||||
|
||||
PopupCard {
|
||||
id: card
|
||||
popupOpen: batteryPopup.popupOpen
|
||||
isTop: root.isTop
|
||||
animEnabled: batteryPopup.visible
|
||||
height: cardCol.implicitHeight + 28
|
||||
|
||||
color: root.t.batPopupBg
|
||||
radius: Cfg.Config.popupRadius
|
||||
border.color: root.t.batPopupBorder
|
||||
border.width: Cfg.Config.popupBorderWidth
|
||||
layer.enabled: true
|
||||
|
||||
ColumnLayout {
|
||||
id: cardCol
|
||||
ColumnLayout {
|
||||
id: cardCol
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
@@ -514,6 +489,5 @@ ModuleChip {
|
||||
|
||||
Item { height: 2 }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,29 +9,17 @@ import "../../components"
|
||||
ModuleChip {
|
||||
id: root
|
||||
|
||||
chipColor: t.clockBg
|
||||
chipColorHovered: t.clockBgHover
|
||||
chipBorderColor: t.clockBorder
|
||||
chipBorderColorHovered: t.clockBorderHover
|
||||
chipHoverEnabled: true
|
||||
chipTapAction: () => calendarPopup.toggle()
|
||||
chipAnimWidth: true
|
||||
|
||||
width: clockLayout.implicitWidth + 24
|
||||
height: Cfg.Config.moduleHeight
|
||||
radius: panelRadius
|
||||
|
||||
color: hoverHandler.hovered ? t.clockBgHover : t.clockBg
|
||||
border.color: hoverHandler.hovered ? t.clockBorderHover : t.clockBorder
|
||||
border.width: borderWidth
|
||||
|
||||
anchors.right: parent.right
|
||||
|
||||
Behavior on width { NumberAnimation { duration: 250; easing.type: Easing.OutCubic } }
|
||||
Behavior on color { ColorAnimation { duration: 150 } }
|
||||
Behavior on border.color { ColorAnimation { duration: 150 } }
|
||||
|
||||
HoverHandler {
|
||||
id: hoverHandler
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
}
|
||||
|
||||
TapHandler {
|
||||
onTapped: calendarPopup.toggle()
|
||||
}
|
||||
|
||||
Item {
|
||||
id: timeManager
|
||||
property date now: new Date()
|
||||
@@ -70,9 +58,9 @@ ModuleChip {
|
||||
font.bold: true
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
|
||||
opacity: (hoverHandler.hovered || calendarPopup.popupOpen) && Cfg.Config.clockExtendEnabled ? 1.0 : 0.0
|
||||
opacity: (root.hovered || calendarPopup.popupOpen) && Cfg.Config.clockExtendEnabled ? 1.0 : 0.0
|
||||
visible: opacity > 0
|
||||
Layout.preferredWidth: (hoverHandler.hovered || calendarPopup.popupOpen) && Cfg.Config.clockExtendEnabled ? implicitWidth : 0
|
||||
Layout.preferredWidth: (root.hovered || calendarPopup.popupOpen) && Cfg.Config.clockExtendEnabled ? implicitWidth : 0
|
||||
clip: true
|
||||
|
||||
Behavior on opacity { NumberAnimation { duration: 200 } }
|
||||
@@ -80,32 +68,22 @@ ModuleChip {
|
||||
}
|
||||
}
|
||||
|
||||
PopupPanel {
|
||||
StandardPopup {
|
||||
id: calendarPopup
|
||||
ns: "calendar"
|
||||
chipRoot: root
|
||||
cardWidth: 284
|
||||
cardColor: t.calCardBg
|
||||
cardBorderColor: t.calCardBorder
|
||||
cardHeight: cardCol.implicitHeight + 28
|
||||
|
||||
PopupCard {
|
||||
id: card
|
||||
popupOpen: calendarPopup.popupOpen
|
||||
isTop: root.isTop
|
||||
animEnabled: calendarPopup.visible
|
||||
height: cardCol.implicitHeight + 24
|
||||
component MonthNavButton: Rectangle {
|
||||
id: navBtn
|
||||
required property int direction
|
||||
|
||||
color: root.t.calCardBg
|
||||
radius: Cfg.Config.popupRadius
|
||||
border.color: root.t.calCardBorder
|
||||
border.width: Cfg.Config.popupBorderWidth
|
||||
layer.enabled: true
|
||||
width: 26; height: 26; radius: 6
|
||||
|
||||
component MonthNavButton: Rectangle {
|
||||
id: navBtn
|
||||
required property int direction
|
||||
|
||||
width: 26; height: 26; radius: 6
|
||||
|
||||
color: btnMouse.containsMouse
|
||||
color: btnMouse.containsMouse
|
||||
? (btnMouse.pressed ? root.t.calArrowBgPress : root.t.calArrowBgHover)
|
||||
: root.t.calArrowBg
|
||||
scale: btnMouse.pressed ? 0.88 : 1.0
|
||||
@@ -252,7 +230,7 @@ ModuleChip {
|
||||
Repeater {
|
||||
model: ["Mo","Tu","We","Th","Fr","Sa","Su"]
|
||||
Text {
|
||||
width: (card.width - 32) / 7
|
||||
width: (calendarPopup.card.width - 32) / 7
|
||||
text: modelData; color: root.t.clockPopupDim
|
||||
font.pixelSize: 11; horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
@@ -267,7 +245,7 @@ ModuleChip {
|
||||
Repeater {
|
||||
model: 7
|
||||
delegate: Item {
|
||||
width: (card.width - 32) / 7; height: 26
|
||||
width: (calendarPopup.card.width - 32) / 7; height: 26
|
||||
readonly property int dayNum: (weekRow.weekIndex * 7 + index) - ((new Date(cal.displayYear, cal.displayMonth, 1).getDay() + 6) % 7) + 1
|
||||
readonly property bool inMonth: dayNum >= 1 && dayNum <= new Date(cal.displayYear, cal.displayMonth + 1, 0).getDate()
|
||||
readonly property bool isToday: {
|
||||
@@ -337,6 +315,5 @@ ModuleChip {
|
||||
|
||||
Item { height: 4 }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,29 +12,21 @@ ModuleChip {
|
||||
|
||||
readonly property var cfg: Cfg.Config
|
||||
|
||||
readonly property string configPath:
|
||||
Quickshell.env("HOME") + "/.config/quickshell/config/config.qml"
|
||||
|
||||
Process {
|
||||
id: cryptoConfigWriter
|
||||
running: false
|
||||
onExited: (code) => {
|
||||
if (code !== 0)
|
||||
console.warn("[Crypto] Failed to patch config.qml (exit " + code + ")")
|
||||
}
|
||||
ConfigWriter {
|
||||
id: configWriter
|
||||
}
|
||||
|
||||
width: chipRow.implicitWidth + 24
|
||||
height: cfg.moduleHeight
|
||||
radius: panelRadius
|
||||
|
||||
color: hoverHandler.hovered ? (t.cryptoBgHover ?? "#15ffffff") : (t.cryptoBg ?? "transparent")
|
||||
border.color: (hoverHandler.hovered || cryptoPopup.popupOpen) ? (t.cryptoBorderHover ?? t.accent ?? "#ffc19375") : (t.cryptoBorder ?? "transparent")
|
||||
border.width: borderWidth
|
||||
|
||||
Behavior on width { NumberAnimation { duration: 250; easing.type: Easing.OutCubic } }
|
||||
Behavior on color { ColorAnimation { duration: 150 } }
|
||||
Behavior on border.color { ColorAnimation { duration: 150 } }
|
||||
chipColor: t.cryptoBg
|
||||
chipColorHovered: t.cryptoBgHover
|
||||
chipBorderColor: t.cryptoBorder
|
||||
chipBorderColorHovered: t.cryptoBorderHover
|
||||
chipHoverEnabled: true
|
||||
chipTapAction: () => cryptoPopup.toggle()
|
||||
popupOpen: cryptoPopup.popupOpen
|
||||
chipAnimWidth: true
|
||||
|
||||
property var localPairs: [{ coin: "bitcoin", currency: "usd" }]
|
||||
property int activeCoinIndex: 0
|
||||
@@ -46,18 +38,18 @@ ModuleChip {
|
||||
: "usd"
|
||||
|
||||
property string localVsCur: "usd"
|
||||
property int localDecimals: cfg.cryptoDecimals ?? 1
|
||||
property int localRefreshSec: cfg.cryptoRefreshSec ?? 60
|
||||
property bool localShowIcon: cfg.cryptoShowIcon ?? true
|
||||
property int localDecimals: cfg.cryptoDecimals
|
||||
property int localRefreshSec: cfg.cryptoRefreshSec
|
||||
property bool localShowIcon: cfg.cryptoShowIcon
|
||||
|
||||
function resolveWithPersistence() {
|
||||
root.localPairs = Array.isArray(cfg.cryptoPairs) && cfg.cryptoPairs.length > 0 ? cfg.cryptoPairs : [{ coin: "bitcoin", currency: "usd" }]
|
||||
root.localVsCur = root.localPairs[0].currency
|
||||
root.displayCurrency = root.localPairs[0].currency
|
||||
root.activeCoinIndex = 0
|
||||
root.localDecimals = cfg.cryptoDecimals ?? 1
|
||||
root.localRefreshSec = cfg.cryptoRefreshSec ?? 60
|
||||
root.localShowIcon = cfg.cryptoShowIcon ?? true
|
||||
root.localDecimals = cfg.cryptoDecimals
|
||||
root.localRefreshSec = cfg.cryptoRefreshSec
|
||||
root.localShowIcon = cfg.cryptoShowIcon
|
||||
}
|
||||
|
||||
function persistSettings() {
|
||||
@@ -65,30 +57,17 @@ ModuleChip {
|
||||
const decimals = Math.round(root.localDecimals)
|
||||
const refreshSec = Math.round(root.localRefreshSec)
|
||||
const showIcon = root.localShowIcon
|
||||
const cfgPath = root.configPath
|
||||
|
||||
const pairsQml = "[" + pairs.map(p =>
|
||||
'{ coin: "' + p.coin + '", currency: "' + p.currency + '" }'
|
||||
).join(", ") + "]"
|
||||
|
||||
|
||||
const sh =
|
||||
"CFG=" + JSON.stringify(cfgPath) + "\n" +
|
||||
"sed -i" +
|
||||
" -e 's/\\(property int[ ]\\+cryptoDecimals:[ ]\\+\\)[0-9.]\\+/\\1" + decimals.toString() + "/'" +
|
||||
" -e 's/\\(property int[ ]\\+cryptoRefreshSec:[ ]\\+\\)[0-9.]\\+/\\1" + refreshSec.toString() + "/'" +
|
||||
" -e 's/\\(property bool[ ]\\+cryptoShowIcon:[ ]\\+\\)\\(true\\|false\\)/\\1" + (showIcon ? "true" : "false") + "/'" +
|
||||
" \"$CFG\"\n" +
|
||||
"QS_PAIRS='" + pairsQml + "'\n" +
|
||||
"awk -v pairs=\"$QS_PAIRS\" '" +
|
||||
"/property var cryptoPairs:/{print \" property var cryptoPairs: \"pairs;sk=/\\]/?0:1;next}" +
|
||||
"sk&&/\\]/{sk=0;next}" +
|
||||
"sk{next}" +
|
||||
"{print}'" +
|
||||
" \"$CFG\" > \"${CFG}.tmp\" && mv \"${CFG}.tmp\" \"$CFG\"\n"
|
||||
|
||||
cryptoConfigWriter.command = ["/bin/sh", "-c", sh]
|
||||
cryptoConfigWriter.running = true
|
||||
configWriter.writeInts([
|
||||
{ key: "cryptoDecimals", value: decimals },
|
||||
{ key: "cryptoRefreshSec", value: refreshSec }
|
||||
])
|
||||
configWriter.writeBool("cryptoShowIcon", showIcon)
|
||||
configWriter.writeArray("cryptoPairs", pairsQml)
|
||||
}
|
||||
|
||||
property real price: -1
|
||||
@@ -222,12 +201,6 @@ ModuleChip {
|
||||
|
||||
onLocalRefreshSecChanged: refreshTimer.restart()
|
||||
|
||||
HoverHandler {
|
||||
id: hoverHandler
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
}
|
||||
TapHandler { onTapped: cryptoPopup.toggle() }
|
||||
|
||||
RowLayout {
|
||||
id: chipRow
|
||||
anchors.centerIn: parent
|
||||
@@ -250,7 +223,7 @@ ModuleChip {
|
||||
Text {
|
||||
visible: root.localShowIcon
|
||||
text: ""
|
||||
color: t.cryptoIcon ?? t.accent ?? "#ffc19375"
|
||||
color: t.cryptoIcon
|
||||
font.pixelSize: 14
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
Layout.rightMargin: 7
|
||||
@@ -258,14 +231,14 @@ ModuleChip {
|
||||
|
||||
Text {
|
||||
text: root.coinSymbol + "/" + root.displayCurrency.toUpperCase() + ": "
|
||||
color: t.cryptoLabel ?? t.textDim ?? "#997a8996"
|
||||
color: t.cryptoLabel
|
||||
font.pixelSize: 12
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
|
||||
Text {
|
||||
text: root.hasError ? "err" : root.price < 0 ? "…" : root.compactPrice(root.price)
|
||||
color: t.cryptoValue ?? t.textMain ?? "#ffe8eef2"
|
||||
color: t.cryptoValue
|
||||
font.pixelSize: 13
|
||||
font.bold: true
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
@@ -274,7 +247,7 @@ ModuleChip {
|
||||
Text {
|
||||
visible: root.price >= 0
|
||||
text: root.change24h >= 0 ? "▲" : "▼"
|
||||
color: root.change24h >= 0 ? (t.cryptoUp ?? "#ffb4c9a1") : (t.cryptoDown ?? "#fff38ba8")
|
||||
color: root.change24h >= 0 ? (t.cryptoUp) : (t.cryptoDown)
|
||||
font.pixelSize: 9
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
@@ -284,37 +257,19 @@ ModuleChip {
|
||||
|
||||
}
|
||||
|
||||
PopupPanel {
|
||||
StandardPopup {
|
||||
id: cryptoPopup
|
||||
ns: "crypto"
|
||||
chipRoot: root
|
||||
cardWidth: 300
|
||||
hasKeyboardFocus: true
|
||||
cardColor: t.cryptoPopupBg
|
||||
cardBorderColor: t.cryptoPopupBorder
|
||||
cardHeight: cardCol.implicitHeight + 24
|
||||
layerEnabled: true
|
||||
|
||||
function open() {
|
||||
popupCenterX = root.mapToItem(null, 0, 0).x + root.width / 2
|
||||
_doOpen()
|
||||
}
|
||||
|
||||
PopupCard {
|
||||
id: card
|
||||
popupOpen: cryptoPopup.popupOpen
|
||||
isTop: root.isTop
|
||||
animEnabled: cryptoPopup.visible
|
||||
height: cardCol.implicitHeight + 24
|
||||
|
||||
Behavior on height { NumberAnimation { duration: 220; easing.type: Easing.OutCubic } }
|
||||
|
||||
color: t.cryptoPopupBg ?? t.calCardBg ?? "#cc0c0e12"
|
||||
radius: Cfg.Config.popupRadius
|
||||
border.color: t.cryptoPopupBorder ?? t.calCardBorder ?? "transparent"
|
||||
border.width: Cfg.Config.popupBorderWidth
|
||||
layer.enabled: true
|
||||
|
||||
property int activeTab: 0
|
||||
|
||||
ColumnLayout {
|
||||
id: cardCol
|
||||
ColumnLayout {
|
||||
id: cardCol
|
||||
anchors { left: parent.left; right: parent.right; top: parent.top }
|
||||
anchors.margins: 16
|
||||
anchors.topMargin: 16
|
||||
@@ -324,7 +279,7 @@ ModuleChip {
|
||||
Layout.fillWidth: true
|
||||
height: 30
|
||||
radius: 10
|
||||
color: t.cryptoFieldBg ?? "#15ffffff"
|
||||
color: t.cryptoFieldBg
|
||||
|
||||
RowLayout {
|
||||
anchors.fill: parent
|
||||
@@ -338,16 +293,16 @@ ModuleChip {
|
||||
height: 24
|
||||
radius: 8
|
||||
|
||||
readonly property bool active: card.activeTab === tabIndex
|
||||
readonly property bool active: cryptoPopup.activeTab === tabIndex
|
||||
color: active
|
||||
? (t.accent ?? "#ffc19375")
|
||||
: (tm.containsMouse ? (t.cryptoFieldBgFocus ?? "#22ffffff") : "transparent")
|
||||
? (t.accent)
|
||||
: (tm.containsMouse ? (t.cryptoFieldBgFocus) : "transparent")
|
||||
Behavior on color { ColorAnimation { duration: 130 } }
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: parent.label
|
||||
color: parent.active ? (t.cryptoTextOnAccent ?? "#ff0c0e12") : (t.cryptoPopupDim ?? t.textDim ?? "#997a8996")
|
||||
color: parent.active ? (t.cryptoTextOnAccent) : (t.cryptoPopupDim)
|
||||
font.pixelSize: 11
|
||||
font.bold: parent.active
|
||||
Behavior on color { ColorAnimation { duration: 130 } }
|
||||
@@ -356,7 +311,7 @@ ModuleChip {
|
||||
id: tm
|
||||
anchors.fill: parent; hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: card.activeTab = tabIndex
|
||||
onClicked: cryptoPopup.activeTab = tabIndex
|
||||
}
|
||||
}
|
||||
|
||||
@@ -376,8 +331,8 @@ ModuleChip {
|
||||
ColumnLayout {
|
||||
id: priceContent
|
||||
width: tabContainer.width
|
||||
x: card.activeTab === 0 ? 0 : -tabContainer.width
|
||||
opacity: card.activeTab === 0 ? 1.0 : 0.0
|
||||
x: cryptoPopup.activeTab === 0 ? 0 : -tabContainer.width
|
||||
opacity: cryptoPopup.activeTab === 0 ? 1.0 : 0.0
|
||||
Behavior on x { NumberAnimation { duration: 260; easing.type: Easing.OutCubic } }
|
||||
Behavior on opacity { NumberAnimation { duration: 200; easing.type: Easing.OutCubic } }
|
||||
spacing: 10
|
||||
@@ -387,7 +342,7 @@ ModuleChip {
|
||||
|
||||
Text {
|
||||
text: ""
|
||||
color: t.cryptoIcon ?? t.accent ?? "#ffc19375"
|
||||
color: t.cryptoIcon
|
||||
font.pixelSize: 22
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
}
|
||||
@@ -399,13 +354,13 @@ ModuleChip {
|
||||
|
||||
Text {
|
||||
text: root.coinSymbol + " / " + root.displayCurrency.toUpperCase()
|
||||
color: t.cryptoPopupHeader ?? t.clockPopupHeader ?? "#ffc19375"
|
||||
color: t.cryptoPopupHeader
|
||||
font.pixelSize: 15
|
||||
font.bold: true
|
||||
}
|
||||
Text {
|
||||
text: root.coinName !== "" ? root.coinName : (root.localCoinId.charAt(0).toUpperCase() + root.localCoinId.slice(1))
|
||||
color: t.cryptoPopupDim ?? t.textDim ?? "#997a8996"
|
||||
color: t.cryptoPopupDim
|
||||
font.pixelSize: 11
|
||||
}
|
||||
}
|
||||
@@ -413,13 +368,13 @@ ModuleChip {
|
||||
Rectangle {
|
||||
width: badge.implicitWidth + 12
|
||||
height: 22; radius: 11
|
||||
color: root.change24h >= 0 ? (t.cryptoUpBg ?? "#22b4c9a1") : (t.cryptoDownBg ?? "#22f38ba8")
|
||||
color: root.change24h >= 0 ? (t.cryptoUpBg) : (t.cryptoDownBg)
|
||||
|
||||
Text {
|
||||
id: badge
|
||||
anchors.centerIn: parent
|
||||
text: (root.change24h >= 0 ? "▲ +" : "▼ ") + root.change24h.toFixed(2) + "%"
|
||||
color: root.change24h >= 0 ? (t.cryptoUp ?? "#ffb4c9a1") : (t.cryptoDown ?? "#fff38ba8")
|
||||
color: root.change24h >= 0 ? (t.cryptoUp) : (t.cryptoDown)
|
||||
font.pixelSize: 11
|
||||
font.bold: true
|
||||
}
|
||||
@@ -430,20 +385,20 @@ ModuleChip {
|
||||
Layout.fillWidth: true
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
text: root.price < 0 ? "Loading…" : root.displayCurrency.toUpperCase() + " " + root.fullPrice(root.price)
|
||||
color: t.cryptoPopupText ?? t.textMain ?? "#ffe8eef2"
|
||||
color: t.cryptoPopupText
|
||||
font.pixelSize: 24
|
||||
font.bold: true
|
||||
font.family: "monospace"
|
||||
}
|
||||
|
||||
Rectangle { Layout.fillWidth: true; height: 1; color: t.calSeparator ?? "#334a5d6e" }
|
||||
Rectangle { Layout.fillWidth: true; height: 1; color: t.calSeparator }
|
||||
|
||||
component StatRow: RowLayout {
|
||||
property string label: ""
|
||||
property string value: ""
|
||||
Layout.fillWidth: true
|
||||
Text { text: label; color: t.cryptoPopupDim ?? t.textDim ?? "#997a8996"; font.pixelSize: 12; Layout.fillWidth: true }
|
||||
Text { text: value; color: t.cryptoPopupText ?? t.textMain ?? "#ffe8eef2"; font.pixelSize: 12; font.bold: true; font.family: "monospace" }
|
||||
Text { text: label; color: t.cryptoPopupDim; font.pixelSize: 12; Layout.fillWidth: true }
|
||||
Text { text: value; color: t.cryptoPopupText; font.pixelSize: 12; font.bold: true; font.family: "monospace" }
|
||||
}
|
||||
|
||||
StatRow { label: "Rank"; value: root.rank > 0 ? "#" + root.rank : "—" }
|
||||
@@ -455,16 +410,16 @@ ModuleChip {
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
Text { text: "ATH"; color: t.cryptoPopupDim ?? t.textDim ?? "#997a8996"; font.pixelSize: 12; Layout.fillWidth: true }
|
||||
Text { text: "ATH"; color: t.cryptoPopupDim; font.pixelSize: 12; Layout.fillWidth: true }
|
||||
Text {
|
||||
text: root.ath > 0 ? root.fullPrice(root.ath) : "—"
|
||||
color: t.cryptoPopupText ?? t.textMain ?? "#ffe8eef2"
|
||||
color: t.cryptoPopupText
|
||||
font.pixelSize: 12; font.bold: true; font.family: "monospace"
|
||||
}
|
||||
Text {
|
||||
visible: root.ath > 0
|
||||
text: "(" + root.athChange.toFixed(2) + "%)"
|
||||
color: t.cryptoDown ?? "#fff38ba8"
|
||||
color: t.cryptoDown
|
||||
font.pixelSize: 11; font.bold: true; font.family: "monospace"
|
||||
}
|
||||
}
|
||||
@@ -477,14 +432,14 @@ ModuleChip {
|
||||
Layout.fillWidth: true
|
||||
Text {
|
||||
text: "24h Range"
|
||||
color: t.cryptoPopupDim ?? t.textDim ?? "#997a8996"
|
||||
color: t.cryptoPopupDim
|
||||
font.pixelSize: 12
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
Text {
|
||||
visible: root.high24h > root.low24h && root.price >= 0
|
||||
text: ((root.price - root.low24h) / (root.high24h - root.low24h) * 100).toFixed(1) + "% of range"
|
||||
color: t.cryptoPopupDim ?? t.textDim ?? "#997a8996"
|
||||
color: t.cryptoPopupDim
|
||||
font.pixelSize: 11
|
||||
}
|
||||
}
|
||||
@@ -496,15 +451,15 @@ ModuleChip {
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
radius: 3
|
||||
color: t.cryptoRangeTrack ?? "#1affffff"
|
||||
color: t.cryptoRangeTrack
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
height: parent.height
|
||||
radius: 3
|
||||
color: root.change24h >= 0
|
||||
? (t.cryptoUp ?? "#ffb4c9a1")
|
||||
: (t.cryptoDown ?? "#fff38ba8")
|
||||
? (t.cryptoUp)
|
||||
: (t.cryptoDown)
|
||||
width: (root.high24h > root.low24h && root.price >= 0)
|
||||
? Math.max(radius * 2,
|
||||
Math.min(parent.width,
|
||||
@@ -519,28 +474,28 @@ ModuleChip {
|
||||
Layout.fillWidth: true
|
||||
Text {
|
||||
text: root.low24h > 0 ? root.fullPrice(root.low24h) : "—"
|
||||
color: t.cryptoDown ?? "#fff38ba8"
|
||||
color: t.cryptoDown
|
||||
font.pixelSize: 10
|
||||
font.family: "monospace"
|
||||
}
|
||||
Item { Layout.fillWidth: true }
|
||||
Text {
|
||||
text: root.high24h > 0 ? root.fullPrice(root.high24h) : "—"
|
||||
color: t.cryptoUp ?? "#ffb4c9a1"
|
||||
color: t.cryptoUp
|
||||
font.pixelSize: 10
|
||||
font.family: "monospace"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle { Layout.fillWidth: true; height: 1; color: t.calSeparator ?? "#334a5d6e" }
|
||||
Rectangle { Layout.fillWidth: true; height: 1; color: t.calSeparator }
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
|
||||
Text {
|
||||
text: root.hasError ? "⚠ fetch error" : "Updated " + (root.lastUpdated || "—")
|
||||
color: t.cryptoPopupDim ?? t.textDim ?? "#997a8996"
|
||||
color: t.cryptoPopupDim
|
||||
font.pixelSize: 11
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
@@ -549,7 +504,7 @@ ModuleChip {
|
||||
id: refreshBtn
|
||||
width: 26; height: 26; radius: 8
|
||||
color: rMouse.containsMouse
|
||||
? (rMouse.pressed ? (t.accent ?? "#ffc19375") : (t.cryptoFieldBgFocus ?? "#22ffffff"))
|
||||
? (rMouse.pressed ? (t.accent) : (t.cryptoFieldBgFocus))
|
||||
: "transparent"
|
||||
Behavior on color { ColorAnimation { duration: 120 } }
|
||||
|
||||
@@ -557,7 +512,7 @@ ModuleChip {
|
||||
id: refreshIcon
|
||||
anchors.centerIn: parent
|
||||
text: ""
|
||||
color: t.cryptoIcon ?? t.accent ?? "#ffc19375"
|
||||
color: t.cryptoIcon
|
||||
font.pixelSize: 14
|
||||
|
||||
RotationAnimator {
|
||||
@@ -585,8 +540,8 @@ ModuleChip {
|
||||
ColumnLayout {
|
||||
id: settingsContent
|
||||
width: tabContainer.width
|
||||
x: card.activeTab === 1 ? 0 : tabContainer.width
|
||||
opacity: card.activeTab === 1 ? 1.0 : 0.0
|
||||
x: cryptoPopup.activeTab === 1 ? 0 : tabContainer.width
|
||||
opacity: cryptoPopup.activeTab === 1 ? 1.0 : 0.0
|
||||
Behavior on x { NumberAnimation { duration: 260; easing.type: Easing.OutCubic } }
|
||||
Behavior on opacity { NumberAnimation { duration: 200; easing.type: Easing.OutCubic } }
|
||||
spacing: 12
|
||||
@@ -600,7 +555,7 @@ ModuleChip {
|
||||
|
||||
Text {
|
||||
text: label
|
||||
color: t.cryptoPopupDim ?? t.textDim ?? "#997a8996"
|
||||
color: t.cryptoPopupDim
|
||||
font.pixelSize: 11
|
||||
font.capitalization: Font.AllUppercase
|
||||
}
|
||||
@@ -609,8 +564,8 @@ ModuleChip {
|
||||
Layout.fillWidth: true
|
||||
height: 30
|
||||
radius: 8
|
||||
color: fi.activeFocus ? (t.cryptoFieldBgFocus ?? "#22ffffff") : (t.cryptoFieldBg ?? "#15ffffff")
|
||||
border.color: fi.activeFocus ? (t.accent ?? "#ffc19375") : "transparent"
|
||||
color: fi.activeFocus ? (t.cryptoFieldBgFocus) : (t.cryptoFieldBg)
|
||||
border.color: fi.activeFocus ? (t.accent) : "transparent"
|
||||
border.width: 1
|
||||
Behavior on color { ColorAnimation { duration: 120 } }
|
||||
Behavior on border.color { ColorAnimation { duration: 120 } }
|
||||
@@ -618,16 +573,16 @@ ModuleChip {
|
||||
TextInput {
|
||||
id: fi
|
||||
anchors { fill: parent; leftMargin: 10; rightMargin: 10; topMargin: 7; bottomMargin: 7 }
|
||||
color: t.cryptoPopupText ?? t.textMain ?? "#ffe8eef2"
|
||||
color: t.cryptoPopupText
|
||||
font.pixelSize: 12
|
||||
font.family: "monospace"
|
||||
selectionColor: t.accent ?? "#ffc19375"
|
||||
selectionColor: t.accent
|
||||
clip: true
|
||||
|
||||
Text {
|
||||
anchors.fill: parent
|
||||
text: parent.parent.parent.placeholder
|
||||
color: t.cryptoPlaceholder ?? "#557a8996"
|
||||
color: t.cryptoPlaceholder
|
||||
font.pixelSize: 12
|
||||
font.family: "monospace"
|
||||
visible: fi.text === "" && !fi.activeFocus
|
||||
@@ -645,26 +600,26 @@ ModuleChip {
|
||||
signal stepped(int v)
|
||||
Layout.fillWidth: true
|
||||
|
||||
Text { text: label; color: t.cryptoPopupDim ?? t.textDim ?? "#997a8996"; font.pixelSize: 12; Layout.fillWidth: true }
|
||||
Text { text: label; color: t.cryptoPopupDim; font.pixelSize: 12; Layout.fillWidth: true }
|
||||
|
||||
Rectangle {
|
||||
width: 24; height: 24; radius: 7
|
||||
color: mm.containsMouse ? (mm.pressed ? (t.accent ?? "#ffc19375") : (t.cryptoFieldBgFocus ?? "#22ffffff")) : (t.cryptoFieldBg ?? "#15ffffff")
|
||||
color: mm.containsMouse ? (mm.pressed ? (t.accent) : (t.cryptoFieldBgFocus)) : (t.cryptoFieldBg)
|
||||
Behavior on color { ColorAnimation { duration: 100 } }
|
||||
Text { anchors.centerIn: parent; text: "−"; font.pixelSize: 14; font.bold: true; color: t.cryptoPopupText ?? t.textMain ?? "#ffe8eef2" }
|
||||
Text { anchors.centerIn: parent; text: "−"; font.pixelSize: 14; font.bold: true; color: t.cryptoPopupText }
|
||||
MouseArea { id: mm; anchors.fill: parent; hoverEnabled: true; cursorShape: Qt.PointingHandCursor; onClicked: if (value > minVal) stepped(value - 1) }
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: 54; height: 24; radius: 6; color: t.cryptoFieldBg ?? "#15ffffff"
|
||||
Text { anchors.centerIn: parent; text: value; color: t.cryptoPopupText ?? t.textMain ?? "#ffe8eef2"; font.pixelSize: 12; font.bold: true; font.family: "monospace" }
|
||||
width: 54; height: 24; radius: 6; color: t.cryptoFieldBg
|
||||
Text { anchors.centerIn: parent; text: value; color: t.cryptoPopupText; font.pixelSize: 12; font.bold: true; font.family: "monospace" }
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: 24; height: 24; radius: 7
|
||||
color: pm.containsMouse ? (pm.pressed ? (t.accent ?? "#ffc19375") : (t.cryptoFieldBgFocus ?? "#22ffffff")) : (t.cryptoFieldBg ?? "#15ffffff")
|
||||
color: pm.containsMouse ? (pm.pressed ? (t.accent) : (t.cryptoFieldBgFocus)) : (t.cryptoFieldBg)
|
||||
Behavior on color { ColorAnimation { duration: 100 } }
|
||||
Text { anchors.centerIn: parent; text: "+"; font.pixelSize: 14; font.bold: true; color: t.cryptoPopupText ?? t.textMain ?? "#ffe8eef2" }
|
||||
Text { anchors.centerIn: parent; text: "+"; font.pixelSize: 14; font.bold: true; color: t.cryptoPopupText }
|
||||
MouseArea { id: pm; anchors.fill: parent; hoverEnabled: true; cursorShape: Qt.PointingHandCursor; onClicked: if (value < maxVal) stepped(value + 1) }
|
||||
}
|
||||
}
|
||||
@@ -675,11 +630,11 @@ ModuleChip {
|
||||
signal toggled(bool v)
|
||||
Layout.fillWidth: true
|
||||
|
||||
Text { text: label; color: t.cryptoPopupDim ?? t.textDim ?? "#997a8996"; font.pixelSize: 12; Layout.fillWidth: true }
|
||||
Text { text: label; color: t.cryptoPopupDim; font.pixelSize: 12; Layout.fillWidth: true }
|
||||
|
||||
Rectangle {
|
||||
width: 36; height: 20; radius: 10
|
||||
color: checked ? (t.accent ?? "#ffc19375") : (t.cryptoFieldBgFocus ?? "#22ffffff")
|
||||
color: checked ? (t.accent) : (t.cryptoFieldBgFocus)
|
||||
Behavior on color { ColorAnimation { duration: 150 } }
|
||||
|
||||
Rectangle {
|
||||
@@ -699,7 +654,7 @@ ModuleChip {
|
||||
|
||||
Text {
|
||||
text: "Pairs to cycle"
|
||||
color: t.cryptoPopupDim ?? t.textDim ?? "#997a8996"
|
||||
color: t.cryptoPopupDim
|
||||
font.pixelSize: 11
|
||||
font.capitalization: Font.AllUppercase
|
||||
}
|
||||
@@ -718,7 +673,7 @@ ModuleChip {
|
||||
width: 12; z: 2
|
||||
gradient: Gradient {
|
||||
orientation: Gradient.Horizontal
|
||||
GradientStop { position: 0.0; color: t.cryptoPopupBg ?? "#cc0c0e12" }
|
||||
GradientStop { position: 0.0; color: t.cryptoPopupBg }
|
||||
GradientStop { position: 1.0; color: "transparent" }
|
||||
}
|
||||
visible: chipScroll.contentX > 0
|
||||
@@ -729,7 +684,7 @@ ModuleChip {
|
||||
gradient: Gradient {
|
||||
orientation: Gradient.Horizontal
|
||||
GradientStop { position: 0.0; color: "transparent" }
|
||||
GradientStop { position: 1.0; color: t.cryptoPopupBg ?? "#cc0c0e12" }
|
||||
GradientStop { position: 1.0; color: t.cryptoPopupBg }
|
||||
}
|
||||
visible: chipScroll.contentX < chipScroll.contentWidth - chipScroll.width - 1
|
||||
}
|
||||
@@ -761,7 +716,7 @@ ModuleChip {
|
||||
id: dotSpace
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
x: 0; width: 5; height: 5; radius: 3
|
||||
color: isActive ? (t.accent ?? "#ffc19375") : "#33ffffff"
|
||||
color: isActive ? (t.accent) : "#33ffffff"
|
||||
Behavior on color { ColorAnimation { duration: 150 } }
|
||||
}
|
||||
|
||||
@@ -771,8 +726,8 @@ ModuleChip {
|
||||
x: dotSpace.width + 5
|
||||
text: (modelData.coin ?? "?") + "/" + (modelData.currency ?? "?").toUpperCase()
|
||||
color: isActive
|
||||
? (t.accent ?? "#ffc19375")
|
||||
: (t.cryptoPopupText ?? t.textMain ?? "#ffe8eef2")
|
||||
? (t.accent)
|
||||
: (t.cryptoPopupText)
|
||||
font.pixelSize: 12
|
||||
font.bold: isActive
|
||||
font.family: "monospace"
|
||||
@@ -784,12 +739,12 @@ ModuleChip {
|
||||
anchors { right: parent.right
|
||||
verticalCenter: parent.verticalCenter }
|
||||
width: 14; height: 14; radius: 4
|
||||
color: rmChipMouse.containsMouse ? (t.cryptoChipRemoveBg ?? "#44f38ba8") : "transparent"
|
||||
color: rmChipMouse.containsMouse ? (t.cryptoChipRemoveBg) : "transparent"
|
||||
Behavior on color { ColorAnimation { duration: 100 } }
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: "×"; font.pixelSize: 11; font.bold: true
|
||||
color: t.cryptoDown ?? "#fff38ba8"
|
||||
color: t.cryptoDown
|
||||
}
|
||||
MouseArea {
|
||||
id: rmChipMouse
|
||||
@@ -818,13 +773,13 @@ ModuleChip {
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
radius: 2
|
||||
color: t.cryptoFieldBg ?? "#15ffffff"
|
||||
color: t.cryptoFieldBg
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
height: parent.height
|
||||
radius: 2
|
||||
color: t.accent ?? "#ffc19375"
|
||||
color: t.accent
|
||||
opacity: 0.7
|
||||
|
||||
readonly property real ratio: chipScroll.width / Math.max(1, chipScroll.contentWidth)
|
||||
@@ -846,7 +801,7 @@ ModuleChip {
|
||||
|
||||
Text {
|
||||
text: "Coin ID"
|
||||
color: t.cryptoPopupDim ?? t.textDim ?? "#997a8996"
|
||||
color: t.cryptoPopupDim
|
||||
font.pixelSize: 11
|
||||
font.capitalization: Font.AllUppercase
|
||||
}
|
||||
@@ -854,8 +809,8 @@ ModuleChip {
|
||||
Rectangle {
|
||||
Layout.fillWidth: true
|
||||
height: 30; radius: 8
|
||||
color: addCoinInput.activeFocus ? (t.cryptoFieldBgFocus ?? "#22ffffff") : (t.cryptoFieldBg ?? "#15ffffff")
|
||||
border.color: addCoinInput.activeFocus ? (t.accent ?? "#ffc19375") : "transparent"
|
||||
color: addCoinInput.activeFocus ? (t.cryptoFieldBgFocus) : (t.cryptoFieldBg)
|
||||
border.color: addCoinInput.activeFocus ? (t.accent) : "transparent"
|
||||
border.width: 1
|
||||
Behavior on color { ColorAnimation { duration: 120 } }
|
||||
Behavior on border.color { ColorAnimation { duration: 120 } }
|
||||
@@ -863,15 +818,15 @@ ModuleChip {
|
||||
TextInput {
|
||||
id: addCoinInput
|
||||
anchors { fill: parent; leftMargin: 10; rightMargin: 10; topMargin: 7; bottomMargin: 7 }
|
||||
color: t.cryptoPopupText ?? t.textMain ?? "#ffe8eef2"
|
||||
color: t.cryptoPopupText
|
||||
font.pixelSize: 12; font.family: "monospace"
|
||||
selectionColor: t.accent ?? "#ffc19375"
|
||||
selectionColor: t.accent
|
||||
clip: true
|
||||
|
||||
Text {
|
||||
anchors.fill: parent
|
||||
text: "e.g. bitcoin, monero, solana"
|
||||
color: t.cryptoPlaceholder ?? "#557a8996"
|
||||
color: t.cryptoPlaceholder
|
||||
font.pixelSize: 12; font.family: "monospace"
|
||||
visible: parent.text === "" && !parent.activeFocus
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
@@ -888,7 +843,7 @@ ModuleChip {
|
||||
|
||||
Text {
|
||||
text: "Currency"
|
||||
color: t.cryptoPopupDim ?? t.textDim ?? "#997a8996"
|
||||
color: t.cryptoPopupDim
|
||||
font.pixelSize: 11
|
||||
font.capitalization: Font.AllUppercase
|
||||
}
|
||||
@@ -900,8 +855,8 @@ ModuleChip {
|
||||
Rectangle {
|
||||
Layout.fillWidth: true
|
||||
height: 30; radius: 8
|
||||
color: addCurrencyInput.activeFocus ? (t.cryptoFieldBgFocus ?? "#22ffffff") : (t.cryptoFieldBg ?? "#15ffffff")
|
||||
border.color: addCurrencyInput.activeFocus ? (t.accent ?? "#ffc19375") : "transparent"
|
||||
color: addCurrencyInput.activeFocus ? (t.cryptoFieldBgFocus) : (t.cryptoFieldBg)
|
||||
border.color: addCurrencyInput.activeFocus ? (t.accent) : "transparent"
|
||||
border.width: 1
|
||||
Behavior on color { ColorAnimation { duration: 120 } }
|
||||
Behavior on border.color { ColorAnimation { duration: 120 } }
|
||||
@@ -909,15 +864,15 @@ ModuleChip {
|
||||
TextInput {
|
||||
id: addCurrencyInput
|
||||
anchors { fill: parent; leftMargin: 10; rightMargin: 10; topMargin: 7; bottomMargin: 7 }
|
||||
color: t.cryptoPopupText ?? t.textMain ?? "#ffe8eef2"
|
||||
color: t.cryptoPopupText
|
||||
font.pixelSize: 12; font.family: "monospace"
|
||||
selectionColor: t.accent ?? "#ffc19375"
|
||||
selectionColor: t.accent
|
||||
clip: true
|
||||
|
||||
Text {
|
||||
anchors.fill: parent
|
||||
text: "e.g. usd, eur, brl"
|
||||
color: t.cryptoPlaceholder ?? "#557a8996"
|
||||
color: t.cryptoPlaceholder
|
||||
font.pixelSize: 12; font.family: "monospace"
|
||||
visible: parent.text === "" && !parent.activeFocus
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
@@ -938,13 +893,13 @@ ModuleChip {
|
||||
Rectangle {
|
||||
width: 30; height: 30; radius: 8
|
||||
color: addPairMouse.containsMouse
|
||||
? (addPairMouse.pressed ? (t.accent ?? "#ffc19375") : (t.cryptoFieldBgFocus ?? "#22ffffff"))
|
||||
: (t.cryptoFieldBg ?? "#15ffffff")
|
||||
? (addPairMouse.pressed ? (t.accent) : (t.cryptoFieldBgFocus))
|
||||
: (t.cryptoFieldBg)
|
||||
Behavior on color { ColorAnimation { duration: 100 } }
|
||||
Text {
|
||||
anchors.centerIn: parent; text: "+"
|
||||
font.pixelSize: 14; font.bold: true
|
||||
color: t.cryptoPopupText ?? t.textMain ?? "#ffe8eef2"
|
||||
color: t.cryptoPopupText
|
||||
}
|
||||
MouseArea {
|
||||
id: addPairMouse
|
||||
@@ -978,7 +933,7 @@ ModuleChip {
|
||||
|
||||
Text {
|
||||
text: "Refresh (seconds)"
|
||||
color: t.cryptoPopupDim ?? t.textDim ?? "#997a8996"
|
||||
color: t.cryptoPopupDim
|
||||
font.pixelSize: 12
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
@@ -986,10 +941,10 @@ ModuleChip {
|
||||
Rectangle {
|
||||
width: 24; height: 24; radius: 7
|
||||
color: decMouse.containsMouse
|
||||
? (decMouse.pressed ? (t.accent ?? "#ffc19375") : (t.cryptoFieldBgFocus ?? "#22ffffff"))
|
||||
: (t.cryptoFieldBg ?? "#15ffffff")
|
||||
? (decMouse.pressed ? (t.accent) : (t.cryptoFieldBgFocus))
|
||||
: (t.cryptoFieldBg)
|
||||
Behavior on color { ColorAnimation { duration: 100 } }
|
||||
Text { anchors.centerIn: parent; text: "−"; font.pixelSize: 14; font.bold: true; color: t.cryptoPopupText ?? t.textMain ?? "#ffe8eef2" }
|
||||
Text { anchors.centerIn: parent; text: "−"; font.pixelSize: 14; font.bold: true; color: t.cryptoPopupText }
|
||||
MouseArea {
|
||||
id: decMouse
|
||||
anchors.fill: parent; hoverEnabled: true; cursorShape: Qt.PointingHandCursor
|
||||
@@ -999,8 +954,8 @@ ModuleChip {
|
||||
|
||||
Rectangle {
|
||||
width: 54; height: 24; radius: 6
|
||||
color: refreshInput.activeFocus ? (t.cryptoFieldBgFocus ?? "#22ffffff") : (t.cryptoFieldBg ?? "#15ffffff")
|
||||
border.color: refreshInput.activeFocus ? (t.accent ?? "#ffc19375") : "transparent"
|
||||
color: refreshInput.activeFocus ? (t.cryptoFieldBgFocus) : (t.cryptoFieldBg)
|
||||
border.color: refreshInput.activeFocus ? (t.accent) : "transparent"
|
||||
border.width: 1
|
||||
Behavior on color { ColorAnimation { duration: 120 } }
|
||||
Behavior on border.color { ColorAnimation { duration: 120 } }
|
||||
@@ -1009,11 +964,11 @@ ModuleChip {
|
||||
id: refreshInput
|
||||
anchors { fill: parent; leftMargin: 6; rightMargin: 6; topMargin: 4; bottomMargin: 4 }
|
||||
text: root.localRefreshSec.toString()
|
||||
color: t.cryptoPopupText ?? t.textMain ?? "#ffe8eef2"
|
||||
color: t.cryptoPopupText
|
||||
font.pixelSize: 12
|
||||
font.bold: true
|
||||
font.family: "monospace"
|
||||
selectionColor: t.accent ?? "#ffc19375"
|
||||
selectionColor: t.accent
|
||||
horizontalAlignment: TextInput.AlignHCenter
|
||||
inputMethodHints: Qt.ImhDigitsOnly
|
||||
validator: IntValidator { bottom: 10; top: 3600 }
|
||||
@@ -1048,10 +1003,10 @@ ModuleChip {
|
||||
Rectangle {
|
||||
width: 24; height: 24; radius: 7
|
||||
color: incMouse.containsMouse
|
||||
? (incMouse.pressed ? (t.accent ?? "#ffc19375") : (t.cryptoFieldBgFocus ?? "#22ffffff"))
|
||||
: (t.cryptoFieldBg ?? "#15ffffff")
|
||||
? (incMouse.pressed ? (t.accent) : (t.cryptoFieldBgFocus))
|
||||
: (t.cryptoFieldBg)
|
||||
Behavior on color { ColorAnimation { duration: 100 } }
|
||||
Text { anchors.centerIn: parent; text: "+"; font.pixelSize: 14; font.bold: true; color: t.cryptoPopupText ?? t.textMain ?? "#ffe8eef2" }
|
||||
Text { anchors.centerIn: parent; text: "+"; font.pixelSize: 14; font.bold: true; color: t.cryptoPopupText }
|
||||
MouseArea {
|
||||
id: incMouse
|
||||
anchors.fill: parent; hoverEnabled: true; cursorShape: Qt.PointingHandCursor
|
||||
@@ -1066,7 +1021,7 @@ ModuleChip {
|
||||
onToggled: (v) => root.localShowIcon = v
|
||||
}
|
||||
|
||||
Rectangle { Layout.fillWidth: true; height: 1; color: t.calSeparator ?? "#334a5d6e" }
|
||||
Rectangle { Layout.fillWidth: true; height: 1; color: t.calSeparator }
|
||||
|
||||
Rectangle {
|
||||
Layout.fillWidth: true
|
||||
@@ -1074,15 +1029,15 @@ ModuleChip {
|
||||
radius: 9
|
||||
color: applyMouse.containsMouse
|
||||
? (applyMouse.pressed
|
||||
? Qt.darker(t.accent ?? "#ffc19375", 1.15)
|
||||
: (t.accent ?? "#ffc19375"))
|
||||
: (t.cryptoApplyIdleBg ?? "#33c19375")
|
||||
? Qt.darker(t.accent, 1.15)
|
||||
: (t.accent))
|
||||
: (t.cryptoApplyIdleBg)
|
||||
Behavior on color { ColorAnimation { duration: 130 } }
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: "Apply & Refresh"
|
||||
color: applyMouse.containsMouse ? (t.cryptoTextOnAccent ?? "#ff0c0e12") : (t.cryptoPopupText ?? t.textMain ?? "#ffe8eef2")
|
||||
color: applyMouse.containsMouse ? (t.cryptoTextOnAccent) : (t.cryptoPopupText)
|
||||
font.pixelSize: 12
|
||||
font.bold: true
|
||||
Behavior on color { ColorAnimation { duration: 130 } }
|
||||
@@ -1097,7 +1052,7 @@ ModuleChip {
|
||||
root.coinSymbol = root.localCoinId.toUpperCase().slice(0, 4)
|
||||
root.persistSettings()
|
||||
root.fetchPrice()
|
||||
card.activeTab = 0
|
||||
cryptoPopup.activeTab = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1105,7 +1060,7 @@ ModuleChip {
|
||||
Text {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
text: "Reset to defaults"
|
||||
color: t.cryptoPopupDim ?? t.textDim ?? "#997a8996"
|
||||
color: t.cryptoPopupDim
|
||||
font.pixelSize: 11
|
||||
font.underline: true
|
||||
|
||||
@@ -1116,12 +1071,12 @@ ModuleChip {
|
||||
root.localVsCur = "usd"
|
||||
root.displayCurrency = root.localPairs.length > 0 ? root.localPairs[0].currency : "usd"
|
||||
root.activeCoinIndex = 0
|
||||
root.localDecimals = cfg.cryptoDecimals ?? 1
|
||||
root.localRefreshSec = cfg.cryptoRefreshSec ?? 60
|
||||
root.localShowIcon = cfg.cryptoShowIcon ?? true
|
||||
root.localDecimals = cfg.cryptoDecimals
|
||||
root.localRefreshSec = cfg.cryptoRefreshSec
|
||||
root.localShowIcon = cfg.cryptoShowIcon
|
||||
root.persistSettings()
|
||||
root.price = -1
|
||||
card.activeTab = 0
|
||||
cryptoPopup.activeTab = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1130,6 +1085,5 @@ ModuleChip {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ ModuleChip {
|
||||
property var launcher: null
|
||||
|
||||
readonly property bool launcherActive: !!launcher && launcher.isOpen
|
||||
readonly property bool isHovered: hoverHandler.hovered
|
||||
readonly property bool isHovered: hovered
|
||||
|
||||
property real spinTarget: 0
|
||||
|
||||
@@ -26,16 +26,12 @@ ModuleChip {
|
||||
width: Cfg.Config.logoIconSize * 2 + 4
|
||||
height: parent.height
|
||||
|
||||
color: isHovered ? t.logoBgHover : t.logoBg
|
||||
radius: panelRadius
|
||||
|
||||
border.color: launcherActive ? t.logoBorderActive : t.logoBorder
|
||||
border.width: borderWidth
|
||||
|
||||
Behavior on color { ColorAnimation { duration: 250 } }
|
||||
Behavior on border.color { ColorAnimation { duration: 250 } }
|
||||
|
||||
HoverHandler { id: hoverHandler }
|
||||
chipColor: t.logoBg
|
||||
chipColorHovered: t.logoBgHover
|
||||
chipBorderColor: t.logoBorder
|
||||
chipBorderColorHovered: t.logoBorderActive
|
||||
popupOpen: launcherActive
|
||||
chipAnimDuration: 250
|
||||
|
||||
TapHandler {
|
||||
onTapped: {
|
||||
|
||||
@@ -107,16 +107,14 @@ ModuleChip {
|
||||
implicitWidth: chipRow.implicitWidth + 24
|
||||
height: Cfg.Config.moduleHeight
|
||||
radius: panelRadius
|
||||
color: chipHover.hovered ? t.netBgHover : t.netBg
|
||||
border.color: chipHover.hovered ? t.netBorderHover : t.netBorder
|
||||
border.width: borderWidth
|
||||
|
||||
Behavior on implicitWidth { NumberAnimation { duration: 250; easing.type: Easing.OutCubic } }
|
||||
Behavior on color { ColorAnimation { duration: 150 } }
|
||||
Behavior on border.color { ColorAnimation { duration: 150 } }
|
||||
|
||||
HoverHandler { id: chipHover; cursorShape: Qt.PointingHandCursor }
|
||||
TapHandler { onTapped: netPopup.toggle() }
|
||||
chipColor: t.netBg
|
||||
chipColorHovered: t.netBgHover
|
||||
chipBorderColor: t.netBorder
|
||||
chipBorderColorHovered: t.netBorderHover
|
||||
chipHoverEnabled: true
|
||||
chipTapAction: () => netPopup.toggle()
|
||||
chipAnimImplicitWidth: true
|
||||
|
||||
RowLayout {
|
||||
id: chipRow
|
||||
@@ -150,11 +148,15 @@ ModuleChip {
|
||||
}
|
||||
}
|
||||
|
||||
PopupPanel {
|
||||
StandardPopup {
|
||||
id: netPopup
|
||||
ns: "network"
|
||||
chipRoot: root
|
||||
cardWidth: 310
|
||||
cardColor: t.netPopupBg
|
||||
cardBorderColor: t.netPopupBorder
|
||||
cardHeight: cardBody.implicitHeight + 28
|
||||
layerEnabled: true
|
||||
|
||||
function open() {
|
||||
root.cancelConnect()
|
||||
@@ -163,20 +165,8 @@ ModuleChip {
|
||||
root.wifiDevice.scannerEnabled = true
|
||||
}
|
||||
|
||||
PopupCard {
|
||||
popupOpen: netPopup.popupOpen
|
||||
isTop: root.isTop
|
||||
animEnabled: netPopup.visible
|
||||
height: cardBody.implicitHeight + 24
|
||||
|
||||
color: root.t.netPopupBg
|
||||
radius: Cfg.Config.popupRadius
|
||||
border.color: root.t.netPopupBorder
|
||||
border.width: Cfg.Config.popupBorderWidth
|
||||
layer.enabled: true
|
||||
|
||||
ColumnLayout {
|
||||
id: cardBody
|
||||
ColumnLayout {
|
||||
id: cardBody
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
@@ -655,6 +645,5 @@ ModuleChip {
|
||||
|
||||
Item { height: 4 }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,17 +16,17 @@ ModuleChip {
|
||||
property bool historyOpen: historyPopup.popupOpen
|
||||
|
||||
width: 35
|
||||
height: 40
|
||||
height: Cfg.Config.moduleHeight
|
||||
radius: panelRadius
|
||||
|
||||
color: hoverHandler.hovered ? t.notifBgHover : t.notifBg
|
||||
chipColor: t.notifBg
|
||||
chipColorHovered: t.notifBgHover
|
||||
popupOpen: historyOpen
|
||||
|
||||
border.color: root.doNotDisturb
|
||||
? t.notifDnd
|
||||
: ((hoverHandler.hovered || historyOpen) ? t.notifBorderActive : t.notifBorder)
|
||||
border.width: borderWidth
|
||||
: ((hovered || historyOpen) ? t.notifBorderActive : t.notifBorder)
|
||||
|
||||
Behavior on color { ColorAnimation { duration: 150 } }
|
||||
Behavior on border.color { ColorAnimation { duration: 150 } }
|
||||
Behavior on width { NumberAnimation { duration: 200; easing.type: Easing.OutCubic } }
|
||||
|
||||
component NotificationCard: Item {
|
||||
@@ -41,8 +41,8 @@ ModuleChip {
|
||||
property int timeout: 5000
|
||||
|
||||
property var t
|
||||
property var urgencyColor: function(u) { return "#ffffff" }
|
||||
property var urgencyIcon: function(u) { return "" }
|
||||
property var urgencyColor
|
||||
property var urgencyIcon
|
||||
|
||||
signal dismissed(string toastId)
|
||||
|
||||
@@ -250,8 +250,8 @@ ModuleChip {
|
||||
property string timeStr: ""
|
||||
|
||||
property var t
|
||||
property var urgencyColor: function(u) { return "#ffffff" }
|
||||
property var urgencyIcon: function(u) { return "" }
|
||||
property var urgencyColor
|
||||
property var urgencyIcon
|
||||
|
||||
signal dismissed(int itemIndex)
|
||||
|
||||
@@ -334,7 +334,7 @@ ModuleChip {
|
||||
}
|
||||
}
|
||||
|
||||
HoverHandler { id: hoverHandler; cursorShape: Qt.PointingHandCursor; onHoveredChanged: if (hovered && Cfg.Config.notificationShakeEnabled) bellRingAnim.start() }
|
||||
HoverHandler { cursorShape: Qt.PointingHandCursor; onHoveredChanged: if (hovered && Cfg.Config.notificationShakeEnabled) bellRingAnim.start() }
|
||||
TapHandler {
|
||||
onTapped: {
|
||||
if (historyPopup.popupOpen) {
|
||||
@@ -458,7 +458,7 @@ ModuleChip {
|
||||
var finalTimeout = (notif.expireTimeout > 0) ? notif.expireTimeout : cfgTimeout
|
||||
|
||||
if (!root.doNotDisturb) {
|
||||
var toastEntry = { toastId, nid: notif.id, appName, summary, body, urgency, timeStr, timeout: finalTimeout }
|
||||
var toastEntry = { toastId, appName, summary, body, urgency, timeStr, timeout: finalTimeout }
|
||||
if (toastLayer.atBottom) activeToasts.append(toastEntry)
|
||||
else activeToasts.insert(0, toastEntry)
|
||||
if (!root.historyOpen) root.unreadCount++
|
||||
|
||||
@@ -9,22 +9,14 @@ ModuleChip {
|
||||
id: root
|
||||
|
||||
width: statsLayout.implicitWidth + 20
|
||||
height: Cfg.Config.moduleHeight
|
||||
color: t.statsBg
|
||||
radius: panelRadius
|
||||
border.color: t.statsBorder
|
||||
border.width: borderWidth
|
||||
chipColor: t.statsBg
|
||||
chipBorderColor: t.statsBorder
|
||||
|
||||
Behavior on width {
|
||||
NumberAnimation { duration: 250; easing.type: Easing.OutCubic }
|
||||
}
|
||||
|
||||
property bool expanded: Cfg.Config.statsStartExpanded
|
||||
property bool hovered: false
|
||||
|
||||
HoverHandler {
|
||||
onHoveredChanged: root.hovered = hovered
|
||||
}
|
||||
|
||||
TapHandler {
|
||||
onTapped: {
|
||||
|
||||
@@ -8,25 +8,17 @@ import Quickshell.Widgets
|
||||
import "../../config" as Cfg
|
||||
import "../../components"
|
||||
|
||||
Item {
|
||||
ModuleChip {
|
||||
id: root
|
||||
|
||||
property real panelRadius: Cfg.Config.radius / 2
|
||||
property int borderWidth: Cfg.Config.panelBorderWidth
|
||||
|
||||
property var targetScreen: null
|
||||
property string barSide: "right"
|
||||
property bool isTop: true
|
||||
|
||||
readonly property var t: Cfg.Config.theme
|
||||
|
||||
property string barSide: "right"
|
||||
property bool expanded: false
|
||||
property bool manuallyExpanded: false
|
||||
|
||||
readonly property bool effectiveExpanded: expanded || trayMenuPopup.popupOpen
|
||||
|
||||
implicitWidth: bgRect.width
|
||||
implicitHeight: bgRect.height
|
||||
implicitWidth: mainRow.width
|
||||
implicitHeight: Cfg.Config.barHeight
|
||||
|
||||
readonly property color tmBg: t.trayMenuBg
|
||||
readonly property color tmBorder: t.trayMenuBorder
|
||||
@@ -36,47 +28,37 @@ Item {
|
||||
readonly property color tmCheck: t.trayMenuCheck
|
||||
readonly property color tmSeparator: t.trayMenuSeparator
|
||||
|
||||
Rectangle {
|
||||
id: bgRect
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
chipColor: t.trayBg
|
||||
chipColorHovered: t.trayBgHover
|
||||
chipBorderColor: t.trayBorder
|
||||
chipBorderColorHovered: t.trayBorderHover
|
||||
popupOpen: trayMenuPopup.popupOpen
|
||||
|
||||
height: parent.height
|
||||
width: mainRow.width
|
||||
radius: root.panelRadius
|
||||
|
||||
color: bgHover.hovered ? root.t.trayBgHover : root.t.trayBg
|
||||
border.color: bgHover.hovered ? root.t.trayBorderHover : root.t.trayBorder
|
||||
border.width: root.borderWidth
|
||||
|
||||
Behavior on color { ColorAnimation { duration: 150 } }
|
||||
Behavior on border.color { ColorAnimation { duration: 150 } }
|
||||
|
||||
HoverHandler {
|
||||
id: bgHover
|
||||
onHoveredChanged: {
|
||||
if (!root.manuallyExpanded) {
|
||||
root.expanded = hovered;
|
||||
}
|
||||
HoverHandler {
|
||||
onHoveredChanged: {
|
||||
if (!root.manuallyExpanded) {
|
||||
root.expanded = hovered;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
id: mainRow
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
Row {
|
||||
id: mainRow
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
leftPadding: root.effectiveExpanded && root.barSide === "right" ? 8 : 0
|
||||
rightPadding: root.effectiveExpanded && root.barSide === "left" ? 8 : 0
|
||||
leftPadding: root.effectiveExpanded && root.barSide === "right" ? 8 : 0
|
||||
rightPadding: root.effectiveExpanded && root.barSide === "left" ? 8 : 0
|
||||
|
||||
Behavior on leftPadding { NumberAnimation { duration: 200; easing.type: Easing.OutCubic } }
|
||||
Behavior on rightPadding { NumberAnimation { duration: 200; easing.type: Easing.OutCubic } }
|
||||
Behavior on leftPadding { NumberAnimation { duration: 200; easing.type: Easing.OutCubic } }
|
||||
Behavior on rightPadding { NumberAnimation { duration: 200; easing.type: Easing.OutCubic } }
|
||||
|
||||
layoutDirection: root.barSide === "left" ? Qt.LeftToRight : Qt.RightToLeft
|
||||
spacing: root.effectiveExpanded ? 4 : 0
|
||||
layoutDirection: root.barSide === "left" ? Qt.LeftToRight : Qt.RightToLeft
|
||||
spacing: root.effectiveExpanded ? 4 : 0
|
||||
|
||||
Behavior on spacing { NumberAnimation { duration: 180; easing.type: Easing.OutCubic } }
|
||||
Behavior on spacing { NumberAnimation { duration: 180; easing.type: Easing.OutCubic } }
|
||||
|
||||
Item {
|
||||
id: toggleArea
|
||||
Item {
|
||||
id: toggleArea
|
||||
width: Cfg.Config.trayToggleSize
|
||||
height: Cfg.Config.trayToggleSize
|
||||
z: 10
|
||||
@@ -149,8 +131,8 @@ Item {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -14,41 +14,24 @@ ModuleChip {
|
||||
property int outputMaxVolume: Cfg.Config.volumeOutputMax
|
||||
property int inputMaxVolume: Cfg.Config.volumeInputMax
|
||||
|
||||
// Path to config.qml — using HOME to avoid Qt.resolvedUrl ambiguity
|
||||
readonly property string configPath:
|
||||
Quickshell.env("HOME") + "/.config/quickshell/config/config.qml"
|
||||
|
||||
// Process that patches volumeOutputMax / volumeInputMax in config.qml
|
||||
Process {
|
||||
id: volConfigWriter
|
||||
running: false
|
||||
onExited: (code) => {
|
||||
if (code !== 0)
|
||||
console.warn("[Volume] Failed to patch config.qml (exit " + code + ")")
|
||||
}
|
||||
ConfigWriter {
|
||||
id: configWriter
|
||||
}
|
||||
|
||||
// Debounce: write to disk 800 ms after the last limit change
|
||||
Timer {
|
||||
id: saveDebounce
|
||||
interval: 800
|
||||
repeat: false
|
||||
onTriggered: {
|
||||
const outMax = Math.round(root.outputMaxVolume).toString()
|
||||
const inMax = Math.round(root.inputMaxVolume).toString()
|
||||
const cfgPath = root.configPath
|
||||
const sh =
|
||||
"sed -i" +
|
||||
" -e 's/\\(property int[ ]\\+volumeOutputMax:[ ]\\+\\)[0-9.]\\+/\\1" + outMax + "/'" +
|
||||
" -e 's/\\(property int[ ]\\+volumeInputMax:[ ]\\+\\)[0-9.]\\+/\\1" + inMax + "/'" +
|
||||
" " + JSON.stringify(cfgPath)
|
||||
volConfigWriter.command = ["/bin/sh", "-c", sh]
|
||||
volConfigWriter.running = true
|
||||
configWriter.writeInts([
|
||||
{ key: "volumeOutputMax", value: root.outputMaxVolume },
|
||||
{ key: "volumeInputMax", value: root.inputMaxVolume }
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
onOutputMaxVolumeChanged: { if (root.outputMaxVolume >= 10) saveDebounce.restart() }
|
||||
onInputMaxVolumeChanged: { if (root.inputMaxVolume >= 10) saveDebounce.restart() }
|
||||
onOutputMaxVolumeChanged: saveDebounce.restart()
|
||||
onInputMaxVolumeChanged: saveDebounce.restart()
|
||||
|
||||
readonly property var sink: Pipewire.defaultAudioSink
|
||||
readonly property var source: Pipewire.defaultAudioSource
|
||||
@@ -115,24 +98,22 @@ ModuleChip {
|
||||
}
|
||||
|
||||
width: chipLayout.implicitWidth + 15
|
||||
height: Cfg.Config.moduleHeight
|
||||
radius: panelRadius
|
||||
|
||||
color: hoverHandler.hovered ? t.volBgHover : t.volBg
|
||||
border.color: (hoverHandler.hovered || volumePopup.popupOpen) ? t.volBorderHover : t.volBorder
|
||||
border.width: borderWidth
|
||||
chipColor: t.volBg
|
||||
chipColorHovered: t.volBgHover
|
||||
chipBorderColor: t.volBorder
|
||||
chipBorderColorHovered: t.volBorderHover
|
||||
chipHoverEnabled: true
|
||||
chipTapAction: () => volumePopup.toggle()
|
||||
popupOpen: volumePopup.popupOpen
|
||||
|
||||
Behavior on color { ColorAnimation { duration: 150 } }
|
||||
Behavior on border.color { ColorAnimation { duration: 150 } }
|
||||
|
||||
HoverHandler {
|
||||
id: hoverHandler
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
HoverHandler {
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onHoveredChanged: {
|
||||
if (hovered && Cfg.Config.volumeShakeEnabled) shakeAnim.restart()
|
||||
}
|
||||
}
|
||||
TapHandler { onTapped: volumePopup.toggle() }
|
||||
|
||||
SequentialAnimation {
|
||||
id: shakeAnim
|
||||
@@ -159,29 +140,21 @@ ModuleChip {
|
||||
}
|
||||
}
|
||||
|
||||
PopupPanel {
|
||||
StandardPopup {
|
||||
id: volumePopup
|
||||
ns: "volume"
|
||||
chipRoot: root
|
||||
cardWidth: Cfg.Config.volumePopupWidth
|
||||
cardColor: t.volPopupBg
|
||||
cardBorderColor: t.volPopupBorder
|
||||
cardHeight: popupCol.implicitHeight + 34
|
||||
|
||||
PopupCard {
|
||||
popupOpen: volumePopup.popupOpen
|
||||
isTop: root.isTop
|
||||
animEnabled: volumePopup.visible
|
||||
height: popupCol.implicitHeight + 32
|
||||
|
||||
radius: Cfg.Config.popupRadius
|
||||
color: root.t.volPopupBg
|
||||
border.color: root.t.volPopupBorder
|
||||
border.width: Cfg.Config.popupBorderWidth
|
||||
|
||||
ColumnLayout {
|
||||
id: popupCol
|
||||
anchors { left: parent.left; right: parent.right; top: parent.top }
|
||||
anchors.margins: 16
|
||||
anchors.topMargin: 18
|
||||
spacing: 14
|
||||
ColumnLayout {
|
||||
id: popupCol
|
||||
anchors { left: parent.left; right: parent.right; top: parent.top }
|
||||
anchors.margins: 16
|
||||
anchors.topMargin: 18
|
||||
spacing: 14
|
||||
|
||||
VolumeSection {
|
||||
id: outputSection
|
||||
@@ -272,7 +245,6 @@ ModuleChip {
|
||||
}
|
||||
Item { height: 2 }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
component VolumeSection: ColumnLayout {
|
||||
|
||||
@@ -10,10 +10,8 @@ ModuleChip {
|
||||
|
||||
width: workspaceLayout.implicitWidth + 24
|
||||
height: Cfg.Config.moduleHeight
|
||||
color: t.wsPanelBg
|
||||
radius: panelRadius
|
||||
border.color: t.wsPanelBorder
|
||||
border.width: borderWidth
|
||||
chipColor: t.wsPanelBg
|
||||
chipBorderColor: t.wsPanelBorder
|
||||
|
||||
RowLayout {
|
||||
id: workspaceLayout
|
||||
|
||||
68
components/ConfigWriter.qml
Normal file
68
components/ConfigWriter.qml
Normal file
@@ -0,0 +1,68 @@
|
||||
import QtQuick
|
||||
import Quickshell
|
||||
import Quickshell.Io
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
property string configPath:
|
||||
Quickshell.env("HOME") + "/.config/quickshell/config/config.qml"
|
||||
|
||||
Process {
|
||||
id: writerProc
|
||||
running: false
|
||||
onExited: (code) => {
|
||||
if (code !== 0)
|
||||
console.warn("[ConfigWriter] Patch failed (exit " + code + ")")
|
||||
}
|
||||
property string _name: "ConfigWriter"
|
||||
}
|
||||
|
||||
function writeInt(key, value) {
|
||||
const n = Math.round(value).toString()
|
||||
const sh = "sed -i" +
|
||||
" -e 's/\\(property int[[:space:]]\\+\\b" + key + "\\b:[ ]*\\)[0-9.]\\+/\\1" + n + "/'" +
|
||||
" " + JSON.stringify(root.configPath)
|
||||
writerProc.command = ["/bin/sh", "-c", sh]
|
||||
writerProc.running = true
|
||||
}
|
||||
|
||||
function writeBool(key, value) {
|
||||
const v = value ? "true" : "false"
|
||||
const sh = "sed -i" +
|
||||
" -e 's/\\(property bool[[:space:]]\\+\\b" + key + "\\b:[ ]*\\)\\(true\\|false\\)/\\1" + v + "/'" +
|
||||
" " + JSON.stringify(root.configPath)
|
||||
writerProc.command = ["/bin/sh", "-c", sh]
|
||||
writerProc.running = true
|
||||
}
|
||||
|
||||
function writeInts(pairs) {
|
||||
let args = ""
|
||||
for (let i = 0; i < pairs.length; i++) {
|
||||
const n = Math.round(pairs[i].value).toString()
|
||||
args += " -e 's/\\(property int[[:space:]]\\+\\b" + pairs[i].key + "\\b:[ ]*\\)[0-9.]\\+/\\1" + n + "/'"
|
||||
}
|
||||
const sh = "sed -i" + args + " " + JSON.stringify(root.configPath)
|
||||
writerProc.command = ["/bin/sh", "-c", sh]
|
||||
writerProc.running = true
|
||||
}
|
||||
|
||||
function writeArray(key, pairsQml) {
|
||||
const sh =
|
||||
"CFG=" + JSON.stringify(root.configPath) + "\n" +
|
||||
"QS_PAIRS='" + pairsQml + "'\n" +
|
||||
"awk -v pairs=\"$QS_PAIRS\" '" +
|
||||
"/^[[:space:]]*property var[[:space:]]+" + key + ":[[:space:]]/{print \" property var " + key + ": \"pairs;sk=/\\]/?0:1;next}" +
|
||||
"sk&&/\\]/{sk=0;next}" +
|
||||
"sk{next}" +
|
||||
"{print}'" +
|
||||
" \"$CFG\" > \"${CFG}.tmp\" && mv \"${CFG}.tmp\" \"$CFG\"\n"
|
||||
writerProc.command = ["/bin/sh", "-c", sh]
|
||||
writerProc.running = true
|
||||
}
|
||||
|
||||
function writeScript(sh) {
|
||||
writerProc.command = ["/bin/sh", "-c", sh]
|
||||
writerProc.running = true
|
||||
}
|
||||
}
|
||||
34
components/HoverButton.qml
Normal file
34
components/HoverButton.qml
Normal file
@@ -0,0 +1,34 @@
|
||||
import QtQuick
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
|
||||
property color idleColor: "transparent"
|
||||
property color hoverColor: "transparent"
|
||||
property color pressColor: "transparent"
|
||||
property color borderIdleColor: "transparent"
|
||||
property color borderHoverColor: "transparent"
|
||||
property real pressScale: 0.97
|
||||
property int animDuration: 150
|
||||
|
||||
readonly property bool hovered: _hover.hovered
|
||||
readonly property bool pressed: _tap.pressed
|
||||
|
||||
signal clicked()
|
||||
|
||||
color: pressed ? pressColor : (hovered ? hoverColor : idleColor)
|
||||
border.color: hovered ? borderHoverColor : borderIdleColor
|
||||
|
||||
scale: pressed ? pressScale : 1.0
|
||||
|
||||
Behavior on color { ColorAnimation { duration: root.animDuration } }
|
||||
Behavior on border.color { ColorAnimation { duration: root.animDuration } }
|
||||
Behavior on scale { NumberAnimation { duration: 100; easing.type: Easing.OutQuad } }
|
||||
|
||||
HoverHandler { id: _hover }
|
||||
TapHandler {
|
||||
id: _tap
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onTapped: root.clicked()
|
||||
}
|
||||
}
|
||||
@@ -13,4 +13,44 @@ Rectangle {
|
||||
readonly property var t: Cfg.Config.theme
|
||||
|
||||
property bool moduleEnabled: true
|
||||
|
||||
property bool hovered: false
|
||||
property bool popupOpen: false
|
||||
|
||||
property color chipColor: "transparent"
|
||||
property color chipColorHovered: "transparent"
|
||||
property color chipBorderColor: "transparent"
|
||||
property color chipBorderColorHovered: "transparent"
|
||||
property bool chipHoverEnabled: false
|
||||
property var chipTapAction: null
|
||||
|
||||
property int chipAnimDuration: 150
|
||||
property bool chipAnimWidth: false
|
||||
property bool chipAnimImplicitWidth: false
|
||||
|
||||
radius: panelRadius
|
||||
color: hovered ? chipColorHovered : chipColor
|
||||
border.color: (hovered || popupOpen) ? chipBorderColorHovered : chipBorderColor
|
||||
border.width: borderWidth
|
||||
|
||||
Behavior on color { ColorAnimation { duration: chip.chipAnimDuration } }
|
||||
Behavior on border.color { ColorAnimation { duration: chip.chipAnimDuration } }
|
||||
Behavior on width {
|
||||
NumberAnimation { duration: 250; easing.type: Easing.OutCubic }
|
||||
enabled: chipAnimWidth
|
||||
}
|
||||
Behavior on implicitWidth {
|
||||
NumberAnimation { duration: 250; easing.type: Easing.OutCubic }
|
||||
enabled: chipAnimImplicitWidth
|
||||
}
|
||||
|
||||
HoverHandler {
|
||||
id: hoverHandler
|
||||
cursorShape: chipHoverEnabled ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||
onHoveredChanged: chip.hovered = hovered
|
||||
}
|
||||
|
||||
TapHandler {
|
||||
onTapped: if (chip.chipTapAction) chip.chipTapAction()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ Rectangle {
|
||||
required property bool popupOpen
|
||||
required property bool isTop
|
||||
property bool animEnabled: true
|
||||
property bool showShadow: false
|
||||
|
||||
width: parent.width
|
||||
|
||||
@@ -27,6 +28,18 @@ Rectangle {
|
||||
opacity: popupOpen ? 1.0 : 0.0
|
||||
Behavior on opacity { NumberAnimation { duration: 200 } }
|
||||
|
||||
Rectangle {
|
||||
visible: card.showShadow && card.popupOpen
|
||||
anchors.fill: parent
|
||||
anchors.margins: -3
|
||||
radius: card.radius + 3
|
||||
color: "transparent"
|
||||
border.color: Qt.rgba(0, 0, 0, 0.35)
|
||||
border.width: 6
|
||||
opacity: card.showShadow && card.popupOpen ? 0.6 : 0
|
||||
Behavior on opacity { NumberAnimation { duration: 200 } }
|
||||
}
|
||||
|
||||
default property alias _popupCardContent: _content.data
|
||||
|
||||
Item {
|
||||
|
||||
31
components/StandardPopup.qml
Normal file
31
components/StandardPopup.qml
Normal file
@@ -0,0 +1,31 @@
|
||||
import QtQuick
|
||||
import "../config" as Cfg
|
||||
|
||||
PopupPanel {
|
||||
id: popup
|
||||
|
||||
property color cardColor: "transparent"
|
||||
property color cardBorderColor: "transparent"
|
||||
property alias cardHeight: card.height
|
||||
property alias showShadow: card.showShadow
|
||||
property bool layerEnabled: false
|
||||
property alias hasKeyboardFocus: popup.hasKeyboardFocus
|
||||
property alias card: card
|
||||
property int activeTab: 0
|
||||
|
||||
default property alias popupContent: card._popupCardContent
|
||||
|
||||
PopupCard {
|
||||
id: card
|
||||
popupOpen: popup.popupOpen
|
||||
isTop: popup.chipRoot ? popup.chipRoot.isTop : true
|
||||
animEnabled: popup.visible
|
||||
color: popup.cardColor
|
||||
radius: Cfg.Config.popupRadius
|
||||
border.color: popup.cardBorderColor
|
||||
border.width: Cfg.Config.popupBorderWidth
|
||||
layer.enabled: popup.layerEnabled
|
||||
|
||||
Behavior on height { NumberAnimation { duration: 220; easing.type: Easing.OutCubic } }
|
||||
}
|
||||
}
|
||||
@@ -29,7 +29,7 @@ Item {
|
||||
}
|
||||
|
||||
Timer {
|
||||
interval: 1800000
|
||||
interval: 300000
|
||||
running: root.tz !== ""
|
||||
repeat: true
|
||||
onTriggered: tzProc.running = true
|
||||
|
||||
@@ -19,7 +19,7 @@ QtObject {
|
||||
// ────────────────────────────────────────────────────────────────────────
|
||||
|
||||
// ── Position & Dimensions ─────────────────────────────────────────────────
|
||||
property string barPosition: "bottom"
|
||||
property string barPosition: "top"
|
||||
property int barHeight: 35
|
||||
property int margin: 20
|
||||
property int radius: 26
|
||||
@@ -49,7 +49,7 @@ QtObject {
|
||||
|
||||
// ── Timezone (IANA name, e.g. "America/New_York", "Europe/London") ──────────
|
||||
// Leave empty to use the system timezone.
|
||||
property string timezone: none
|
||||
property string timezone: "America/New_York"
|
||||
|
||||
// Date format used in the clock popup and background date widget.
|
||||
// "MDY" → month/day/year (e.g. May 14, 2026)
|
||||
@@ -76,7 +76,7 @@ QtObject {
|
||||
property int volumeSliderHeight: 2
|
||||
property int volumeHandleSize: 20
|
||||
property int volumePopupWidth: 280
|
||||
property int volumeOutputMax: 140
|
||||
property int volumeOutputMax: 190
|
||||
property int volumeInputMax: 200
|
||||
|
||||
|
||||
@@ -127,7 +127,7 @@ QtObject {
|
||||
//
|
||||
// This list is the *default*; pairs can be added/removed live in the
|
||||
// Settings popup and those changes are persisted across restarts.
|
||||
property var cryptoPairs: [{ coin: "bitcoin", currency: "usd" }, { coin: "ethereum", currency: "eur" }, { coin: "monero", currency: "usd" }, { coin: "solana", currency: "brl" }]
|
||||
property var cryptoPairs: [{ coin: "bitcoin", currency: "usd" }, { coin: "ethereum", currency: "eur" }, { coin: "monero", currency: "usd" }]
|
||||
|
||||
// ── Compact label decimals ────────────────────────────────────────────────
|
||||
// 0 → "80k"
|
||||
|
||||
@@ -4,6 +4,7 @@ import Quickshell.Wayland
|
||||
import Quickshell.Services.Polkit
|
||||
|
||||
import "../config" as Cfg
|
||||
import "../components"
|
||||
|
||||
|
||||
Item {
|
||||
@@ -115,37 +116,18 @@ Item {
|
||||
color: t.polkitOverlayBg
|
||||
}
|
||||
|
||||
component DialogButton: Rectangle {
|
||||
component DialogButton: HoverButton {
|
||||
property string label
|
||||
property int labelWeight: Font.Normal
|
||||
property color bgColor
|
||||
property color bgHoverColor
|
||||
property color borderColor
|
||||
property color borderHoverColor
|
||||
property color labelColor
|
||||
signal tapped()
|
||||
|
||||
width: (parent.width - 12) / 2
|
||||
height: 44
|
||||
radius: 10
|
||||
|
||||
HoverHandler { id: hover }
|
||||
|
||||
color: hover.hovered ? bgHoverColor : bgColor
|
||||
border.color: hover.hovered ? borderHoverColor : borderColor
|
||||
border.width: 1
|
||||
|
||||
Behavior on color { ColorAnimation { duration: 200 } }
|
||||
Behavior on border.color { ColorAnimation { duration: 200 } }
|
||||
|
||||
scale: pressHandler.pressed ? 0.97 : 1.0
|
||||
Behavior on scale { NumberAnimation { duration: 100; easing.type: Easing.OutQuad } }
|
||||
|
||||
TapHandler {
|
||||
id: pressHandler
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onTapped: parent.tapped()
|
||||
}
|
||||
onClicked: tapped()
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
@@ -464,20 +446,22 @@ Item {
|
||||
label: "Authenticate"
|
||||
labelWeight: Font.Medium
|
||||
labelColor: t.polkitAuthText
|
||||
bgColor: t.polkitAuthBg
|
||||
bgHoverColor: t.polkitAuthBgHover
|
||||
borderColor: t.polkitAuthBg
|
||||
idleColor: t.polkitAuthBg
|
||||
hoverColor: t.polkitAuthBgHover
|
||||
borderIdleColor: t.polkitAuthBg
|
||||
borderHoverColor: t.polkitAuthBgHover
|
||||
animDuration: 200
|
||||
onTapped: root.submitAuth()
|
||||
}
|
||||
|
||||
DialogButton {
|
||||
label: "Cancel"
|
||||
labelColor: t.polkitCancelText
|
||||
bgColor: t.polkitCancelBg
|
||||
bgHoverColor: t.polkitCancelBgHover
|
||||
borderColor: t.polkitCancelBorder
|
||||
idleColor: t.polkitCancelBg
|
||||
hoverColor: t.polkitCancelBgHover
|
||||
borderIdleColor: t.polkitCancelBorder
|
||||
borderHoverColor: t.polkitCancelBgHover
|
||||
animDuration: 200
|
||||
onTapped: overlay.cancelAndClose()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ ShellRoot {
|
||||
readonly property bool isTop: Cfg.Config.barPosition === "top"
|
||||
|
||||
property color frameBackground: Cfg.Config.theme.bgFrame
|
||||
property color frameBorderColor: Cfg.Config.theme.frameBorder ?? Cfg.Config.theme.borderPopup
|
||||
property color frameBorderColor: Cfg.Config.theme.frameBorder
|
||||
|
||||
// ── Polkit Agent ─────────────────────────────────────────────────────────
|
||||
Loader {
|
||||
|
||||
@@ -14,6 +14,7 @@ PanelWindow {
|
||||
anchors { top: true; bottom: true; left: true; right: true }
|
||||
|
||||
WlrLayershell.layer: WlrLayer.Background
|
||||
WlrLayershell.namespace: "main-shell-bgDate"
|
||||
WlrLayershell.exclusiveZone: -1
|
||||
mask: Region {}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user