added two new themes, reworked Crypto.qml and Stats.qml, standardized the buttons for the modules, added a new Sidebar widget which contains new 3 modules
This commit is contained in:
208
widgets/sidebar/Sidebar.qml
Normal file
208
widgets/sidebar/Sidebar.qml
Normal file
@@ -0,0 +1,208 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import Quickshell
|
||||
import Quickshell.Wayland
|
||||
import Quickshell.Hyprland
|
||||
|
||||
import "../../config" as Cfg
|
||||
import "sysinfo"
|
||||
import "mpris"
|
||||
import "weather"
|
||||
|
||||
PanelWindow {
|
||||
id: root
|
||||
|
||||
required property var modelData
|
||||
screen: modelData
|
||||
color: "transparent"
|
||||
visible: false
|
||||
|
||||
anchors { top: true; bottom: true; left: true; right: true }
|
||||
|
||||
WlrLayershell.layer: WlrLayer.Top
|
||||
WlrLayershell.namespace: "main-shell-sidebar"
|
||||
WlrLayershell.exclusiveZone: -1
|
||||
WlrLayershell.keyboardFocus: _open ? WlrKeyboardFocus.OnDemand : WlrKeyboardFocus.None
|
||||
|
||||
Region { id: noMask }
|
||||
mask: _open ? null : noMask
|
||||
|
||||
readonly property var t: Cfg.Config.theme
|
||||
readonly property bool isTop: Cfg.Config.barPosition === "top"
|
||||
readonly property int frameTop: isTop ? Cfg.Config.barHeight : Cfg.Config.margin
|
||||
readonly property int frameBot: isTop ? Cfg.Config.margin : Cfg.Config.barHeight
|
||||
readonly property int inset: Cfg.Config.margin + Cfg.Config.frameBorderWidth + 8
|
||||
readonly property int sbWidth: 260
|
||||
readonly property bool isLeft: Cfg.Config.sideBarPosition === "left"
|
||||
readonly property int slideDist: root.sbWidth + 20
|
||||
readonly property int slideFrom: isLeft ? -slideDist : slideDist
|
||||
readonly property int panelX: isLeft ? root.inset : (width - root.sbWidth - root.inset)
|
||||
|
||||
property bool _open: false
|
||||
readonly property bool isOpen: _open
|
||||
|
||||
GlobalShortcut {
|
||||
name: "sidebar"
|
||||
onPressed: root.toggle()
|
||||
}
|
||||
|
||||
function open() {
|
||||
visible = true
|
||||
_open = true
|
||||
enterAnim.stop()
|
||||
exitAnim.stop()
|
||||
hideTimer.stop()
|
||||
enterAnim.start()
|
||||
}
|
||||
|
||||
function close() {
|
||||
_open = false
|
||||
enterAnim.stop()
|
||||
exitAnim.start()
|
||||
}
|
||||
|
||||
function toggle() { _open ? close() : open() }
|
||||
|
||||
Timer {
|
||||
id: hideTimer
|
||||
interval: 280
|
||||
onTriggered: visible = false
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: root
|
||||
function onActiveChanged() {
|
||||
if (!root.active && root._open) root.close()
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: root.close()
|
||||
}
|
||||
|
||||
// ── Full right-side background panel ──────────────────────────────────
|
||||
Rectangle {
|
||||
id: sidebarPanel
|
||||
transform: Translate { id: panelSlide; x: root.slideFrom }
|
||||
|
||||
x: root.panelX
|
||||
y: root.frameTop + Cfg.Config.frameBorderWidth
|
||||
width: root.sbWidth
|
||||
height: parent.height - root.frameTop - root.frameBot - Cfg.Config.frameBorderWidth * 2
|
||||
radius: Cfg.Config.popupRadius
|
||||
color: "transparent"
|
||||
opacity: 0
|
||||
|
||||
clip: true
|
||||
|
||||
// ── Widget area ───────────────────────────────────────────────────
|
||||
Item {
|
||||
id: widgetArea
|
||||
anchors {
|
||||
fill: parent
|
||||
topMargin: 10
|
||||
bottomMargin: 10
|
||||
leftMargin: 10
|
||||
rightMargin: 10
|
||||
}
|
||||
|
||||
Flickable {
|
||||
id: flick
|
||||
anchors.fill: parent
|
||||
contentWidth: width
|
||||
contentHeight: widgetCol.implicitHeight
|
||||
boundsBehavior: Flickable.StopAtBounds
|
||||
clip: true
|
||||
flickDeceleration: 2000
|
||||
|
||||
ScrollBar.vertical: ScrollBar {
|
||||
policy: ScrollBar.AsNeeded
|
||||
width: 4
|
||||
contentItem: Rectangle {
|
||||
radius: 2
|
||||
color: Qt.alpha(root.t.accent, 0.3)
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
id: widgetCol
|
||||
anchors { left: parent.left; right: parent.right }
|
||||
spacing: 10
|
||||
|
||||
Loader {
|
||||
active: Cfg.Config.sideBarSysInfo
|
||||
sourceComponent: sysInfoComp
|
||||
anchors { left: parent.left; right: parent.right }
|
||||
}
|
||||
|
||||
Loader {
|
||||
active: Cfg.Config.sideBarMpris
|
||||
sourceComponent: mprisComp
|
||||
anchors { left: parent.left; right: parent.right }
|
||||
}
|
||||
|
||||
Loader {
|
||||
active: Cfg.Config.sideBarWeather
|
||||
sourceComponent: weatherComp
|
||||
anchors { left: parent.left; right: parent.right }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: sysInfoComp
|
||||
WidgetCard {
|
||||
SysInfo {
|
||||
anchors { left: parent.left; right: parent.right }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: mprisComp
|
||||
WidgetCard {
|
||||
MprisWidget {
|
||||
anchors { left: parent.left; right: parent.right }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: weatherComp
|
||||
WidgetCard {
|
||||
WeatherWidget {
|
||||
anchors { left: parent.left; right: parent.right }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ── Enter animation ───────────────────────────────────────────────────
|
||||
ParallelAnimation {
|
||||
id: enterAnim
|
||||
NumberAnimation {
|
||||
target: panelSlide; property: "x"
|
||||
to: 0; duration: 320; easing.type: Easing.OutCubic
|
||||
}
|
||||
NumberAnimation {
|
||||
target: sidebarPanel; property: "opacity"
|
||||
to: 1; duration: 280; easing.type: Easing.OutCubic
|
||||
}
|
||||
}
|
||||
|
||||
// ── Exit animation ────────────────────────────────────────────────────
|
||||
ParallelAnimation {
|
||||
id: exitAnim
|
||||
onStopped: hideTimer.restart()
|
||||
NumberAnimation {
|
||||
target: panelSlide; property: "x"
|
||||
to: root.slideFrom; duration: 250; easing.type: Easing.InCubic
|
||||
}
|
||||
NumberAnimation {
|
||||
target: sidebarPanel; property: "opacity"
|
||||
to: 0; duration: 200; easing.type: Easing.InBack
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user