214 lines
6.0 KiB
QML
214 lines
6.0 KiB
QML
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 barEdgePad: Cfg.Config.frameVariant === "bar" ? (isTop ? Cfg.Config.frameBarPadTop : Cfg.Config.frameBarPadBottom) : 0
|
|
readonly property int frameTop: isTop ? Cfg.Config.barHeight + barEdgePad : Cfg.Config.margin
|
|
readonly property int frameBot: isTop ? Cfg.Config.margin : Cfg.Config.barHeight + barEdgePad
|
|
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() {
|
|
var fm = Hyprland.focusedMonitor
|
|
if (!fm || fm.name !== screen.name) return
|
|
visible = true
|
|
_open = true
|
|
enterAnim.stop()
|
|
exitAnim.stop()
|
|
hideTimer.stop()
|
|
enterAnim.start()
|
|
}
|
|
|
|
function close() {
|
|
_open = false
|
|
enterAnim.stop()
|
|
exitAnim.start()
|
|
}
|
|
|
|
function toggle() {
|
|
if (!_open) {
|
|
var fm = Hyprland.focusedMonitor
|
|
if (!fm || fm.name !== screen.name) return
|
|
}
|
|
_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()
|
|
}
|
|
|
|
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
|
|
|
|
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 }
|
|
}
|
|
}
|
|
}
|
|
|
|
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
|
|
}
|
|
}
|
|
|
|
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
|
|
}
|
|
}
|
|
}
|