sidebar: static calendar

This commit is contained in:
end-4
2025-04-16 10:41:08 +02:00
parent 199bc99fb5
commit f7c7313087
4 changed files with 199 additions and 42 deletions
@@ -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 {
@@ -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
}
}
@@ -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
@@ -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;
}