diff --git a/.config/quickshell/modules/common/Appearance.qml b/.config/quickshell/modules/common/Appearance.qml index 09a71b6c2..de95e5b08 100644 --- a/.config/quickshell/modules/common/Appearance.qml +++ b/.config/quickshell/modules/common/Appearance.qml @@ -169,6 +169,10 @@ Singleton { property int duration: 350 property int type: Easing.OutExpo } + property QtObject positionShift: QtObject { + property int duration: 160 + property int type: Easing.InOutExpo + } } sizes: QtObject { diff --git a/.config/quickshell/modules/sidebarRight/CalendarDayButton.qml b/.config/quickshell/modules/sidebarRight/CalendarDayButton.qml new file mode 100644 index 000000000..0ec588d02 --- /dev/null +++ b/.config/quickshell/modules/sidebarRight/CalendarDayButton.qml @@ -0,0 +1,39 @@ +import "root:/modules/common" +import "root:/modules/common/widgets" +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts + +Button { + id: button + property string day + property int isToday + property bool bold + + Layout.fillWidth: false + Layout.fillHeight: false + implicitWidth: 38; + implicitHeight: 38; + + background: Rectangle { + anchors.fill: parent + radius: Appearance.rounding.full + color: (isToday == 1) ? (button.down ? Appearance.colors.colPrimaryActive : + button.hovered ? Appearance.colors.colPrimaryHover : + Appearance.m3colors.m3primary) : + button.down ? Appearance.colors.colLayer1Active : + button.hovered ? Appearance.colors.colLayer1Hover : + Appearance.transparentize(Appearance.colors.colLayer1, 1) + } + + contentItem: StyledText { + anchors.fill: parent + text: day + horizontalAlignment: Text.AlignHCenter + font.weight: bold ? Font.Bold : isToday == -1 ? Font.Normal : Font.DemiBold + color: (isToday == 1) ? Appearance.m3colors.m3onPrimary : + (isToday == 0) ? Appearance.colors.colOnLayer1 : + Appearance.m3colors.m3outline + } +} + diff --git a/.config/quickshell/modules/sidebarRight/SidebarCalendar.qml b/.config/quickshell/modules/sidebarRight/SidebarCalendar.qml index 9163c056d..c70b9a7c6 100644 --- a/.config/quickshell/modules/sidebarRight/SidebarCalendar.qml +++ b/.config/quickshell/modules/sidebarRight/SidebarCalendar.qml @@ -4,6 +4,7 @@ import QtQuick import QtQuick.Controls import QtQuick.Layouts import Quickshell +import "calendar_layout.js" as CalendarLayout Rectangle { Layout.alignment: Qt.AlignHCenter @@ -11,11 +12,11 @@ Rectangle { Layout.fillWidth: true radius: Appearance.rounding.normal color: Appearance.colors.colLayer1 - height: 300 + implicitHeight: 300 RowLayout { id: calendarRow - anchors.centerIn: parent + anchors.fill: parent width: parent.width - 10 * 2 height: parent.height - 10 * 2 spacing: 10 @@ -24,8 +25,8 @@ Rectangle { ColumnLayout { id: tabBar Layout.fillHeight: true - Layout.leftMargin: 10 - spacing: 10 + Layout.leftMargin: 15 + spacing: 15 Repeater { model: [ {"name": "Calendar", "icon": "calendar_month"}, @@ -46,49 +47,53 @@ Rectangle { Layout.fillWidth: true Layout.fillHeight: true property int realIndex: 0 - // currentIndex: 0 - Connections { - target: calendarRow - function onSelectedTabChanged() { - // console.log("Real index changed to: " + tabStack.realIndex) - delayedStackSwitch.start() - tabStack.realIndex = calendarRow.selectedTab - } - } - Timer { - id: delayedStackSwitch - interval: Appearance.animation.elementDecel.duration - repeat: false - onTriggered: { - tabStack.currentIndex = calendarRow.selectedTab - } - } + property int animationDuration: Appearance.animation.elementDecel.duration * 1.5 + // Calendar Component { id: calendarWidget - Rectangle { - anchors.fill: parent - color: "pink" - width: 30; height: 30; - radius: Appearance.rounding.small - StyledText { - anchors.margins: 10 - anchors.left: parent.left - anchors.right: parent.right - anchors.top: parent.top - text: "## Calendar\n- Lorem ipsum\n- Dolor shit amet\n\nSigma Ohayo rc1 Pro+ Premium Hippuland hi ask vaxry for pleas fix 123 Billions must lorem ipsum ipsum yesterdays tears are tomorrows coom awawawa" - wrapMode: Text.WordWrap - textFormat: Text.MarkdownText + ColumnLayout { + anchors.centerIn: parent + spacing: 5 + RowLayout { + Layout.fillWidth: true + Layout.fillHeight: false + spacing: 5 + Repeater { + model: CalendarLayout.weekDays + delegate: CalendarDayButton { + day: modelData.day + isToday: modelData.today + bold: true + } + } + } + Repeater { + model: CalendarLayout.getCalendarLayout(null, true) + delegate: RowLayout { + Layout.fillWidth: true + Layout.fillHeight: false + spacing: 5 + Repeater { + model: modelData + delegate: CalendarDayButton { + day: modelData.day + isToday: modelData.today + } + } + } } } } + + // To Do Component { id: todoWidget - Rectangle { + Item { anchors.fill: parent - color: "lavender" + // color: "lavender" + // radius: Appearance.rounding.small width: 30; height: 30; - radius: Appearance.rounding.small StyledText { anchors.margins: 10 anchors.left: parent.left @@ -101,6 +106,22 @@ Rectangle { } } + Connections { + target: calendarRow + function onSelectedTabChanged() { + delayedStackSwitch.start() + tabStack.realIndex = calendarRow.selectedTab + } + } + Timer { + id: delayedStackSwitch + interval: tabStack.animationDuration / 2 + repeat: false + onTriggered: { + tabStack.currentIndex = calendarRow.selectedTab + } + } + Repeater { model: [ { type: "calendar" }, @@ -111,12 +132,10 @@ Rectangle { property int tabIndex: index property string tabType: modelData.type property int animDistance: 5 - opacity: (tabStack.currentIndex === tabItem.tabIndex && tabStack.realIndex === tabItem.tabIndex) ? 1 : - (tabStack.currentIndex === tabItem.tabIndex && tabStack.realIndex !== tabItem.tabIndex) ? 0 : - (tabStack.realIndex === tabItem.tabIndex) ? 1 : 0 + opacity: (tabStack.currentIndex === tabItem.tabIndex && tabStack.realIndex === tabItem.tabIndex) ? 1 : 0 y: (tabStack.realIndex === tabItem.tabIndex) ? 0 : (tabStack.realIndex < tabItem.tabIndex) ? animDistance : -animDistance - Behavior on opacity { NumberAnimation { duration: Appearance.animation.elementDecel.duration; easing.type: Easing.OutCubic } } - Behavior on y { NumberAnimation { duration: Appearance.animation.elementDecel.duration * 2; easing.type: Easing.OutCubic } } + Behavior on opacity { NumberAnimation { duration: tabStack.animationDuration / 2; easing.type: Easing.OutCubic } } + Behavior on y { NumberAnimation { duration: tabStack.animationDuration; easing.type: Easing.OutExpo } } Loader { anchors.fill: parent sourceComponent: (tabType === "calendar") ? calendarWidget : todoWidget diff --git a/.config/quickshell/modules/sidebarRight/calendar_layout.js b/.config/quickshell/modules/sidebarRight/calendar_layout.js new file mode 100644 index 000000000..097320acd --- /dev/null +++ b/.config/quickshell/modules/sidebarRight/calendar_layout.js @@ -0,0 +1,95 @@ +const weekDays = [ // MONDAY IS THE FIRST DAY OF THE WEEK :HESRIGHTYOUKNOW: + { day: 'Mo', today: 0 }, + { day: 'Tu', today: 0 }, + { day: 'We', today: 0 }, + { day: 'Th', today: 0 }, + { day: 'Fr', today: 0 }, + { day: 'Sa', today: 0 }, + { day: 'Su', today: 0 }, +] + +function checkLeapYear(year) { + return ( + year % 400 == 0 || + (year % 4 == 0 && year % 100 != 0)); +} + +function getMonthDays(month, year) { + const leapYear = checkLeapYear(year); + if ((month <= 7 && month % 2 == 1) || (month >= 8 && month % 2 == 0)) return 31; + if (month == 2 && leapYear) return 29; + if (month == 2 && !leapYear) return 28; + return 30; +} + +function getNextMonthDays(month, year) { + const leapYear = checkLeapYear(year); + if (month == 1 && leapYear) return 29; + if (month == 1 && !leapYear) return 28; + if (month == 12) return 31; + if ((month <= 7 && month % 2 == 1) || (month >= 8 && month % 2 == 0)) return 30; + return 31; +} + +function getPrevMonthDays(month, year) { + const leapYear = checkLeapYear(year); + if (month == 3 && leapYear) return 29; + if (month == 3 && !leapYear) return 28; + if (month == 1) return 31; + if ((month <= 7 && month % 2 == 1) || (month >= 8 && month % 2 == 0)) return 30; + return 31; +} + +function getCalendarLayout(dateObject, highlight) { + if (!dateObject) dateObject = new Date(); + const weekday = (dateObject.getDay() + 6) % 7; // MONDAY IS THE FIRST DAY OF THE WEEK + const day = dateObject.getDate(); + const month = dateObject.getMonth() + 1; + const year = dateObject.getFullYear(); + const weekdayOfMonthFirst = (weekday + 35 - (day - 1)) % 7; + const daysInMonth = getMonthDays(month, year); + const daysInNextMonth = getNextMonthDays(month, year); + const daysInPrevMonth = getPrevMonthDays(month, year); + + // Fill + var monthDiff = (weekdayOfMonthFirst == 0 ? 0 : -1); + var toFill, dim; + if(weekdayOfMonthFirst == 0) { + toFill = 1; + dim = daysInMonth; + } + else { + toFill = (daysInPrevMonth - (weekdayOfMonthFirst - 1)); + dim = daysInPrevMonth; + } + var calendar = [...Array(6)].map(() => Array(7)); + var i = 0, j = 0; + while (i < 6 && j < 7) { + calendar[i][j] = { + "day": toFill, + "today": ((toFill == day && monthDiff == 0 && highlight) ? 1 : ( + monthDiff == 0 ? 0 : + -1 + )) + }; + // Increment + toFill++; + if (toFill > dim) { // Next month? + monthDiff++; + if (monthDiff == 0) + dim = daysInMonth; + else if (monthDiff == 1) + dim = daysInNextMonth; + toFill = 1; + } + // Next tile + j++; + if (j == 7) { + j = 0; + i++; + } + + } + return calendar; +} +