Files
TheaninovOS/desktops/hyprland/ags/modules/calendar.js
2023-11-15 16:09:26 +01:00

394 lines
12 KiB
JavaScript

const {Gio, Gdk, Gtk} = imports.gi
import {App, Widget, Utils} from "../imports.js"
const {Box, CenterBox, Label, Button} = Widget
import {MaterialIcon} from "./lib/materialicon.js"
import {getCalendarLayout} from "../scripts/calendarlayout.js"
import Todo from "../scripts/todo.js"
import {setupCursorHover} from "./lib/cursorhover.js"
import {NavigationIndicator} from "./lib/navigationindicator.js"
let calendarJson = getCalendarLayout(undefined, true)
let monthshift = 0
function fileExists(filePath) {
let file = Gio.File.new_for_path(filePath)
return file.query_exists(null)
}
function getDateInXMonthsTime(x) {
var currentDate = new Date() // Get the current date
var targetMonth = currentDate.getMonth() + x // Calculate the target month
var targetYear = currentDate.getFullYear() // Get the current year
// Adjust the year and month if necessary
targetYear += Math.floor(targetMonth / 12)
targetMonth = ((targetMonth % 12) + 12) % 12
// Create a new date object with the target year and month
var targetDate = new Date(targetYear, targetMonth, 1)
// Set the day to the last day of the month to get the desired date
// targetDate.setDate(0);
return targetDate
}
const weekDays = [
// stupid stupid stupid!! how tf is Sunday the first day of the week??
{day: "Su", today: 0},
{day: "Mo", today: 0},
{day: "Tu", today: 0},
{day: "We", today: 0},
{day: "Th", today: 0},
{day: "Fr", today: 0},
{day: "Sa", today: 0},
]
const CalendarDay = (day, today) =>
Widget.Button({
className: `sidebar-calendar-btn ${
today == 1 ? "sidebar-calendar-btn-today" : today == -1 ? "sidebar-calendar-btn-othermonth" : ""
}`,
child: Widget.Overlay({
child: Box({}),
overlays: [
Label({
halign: "center",
className: "txt-smallie txt-semibold sidebar-calendar-btn-txt",
label: String(day),
}),
],
}),
})
const CalendarWidget = () => {
const calendarMonthYear = Widget.Button({
className: "txt txt-large sidebar-calendar-monthyear-btn",
onClicked: () => shiftCalendarXMonths(0),
setup: button => {
button.label = `${new Date().toLocaleString("default", {month: "long"})} ${new Date().getFullYear()}`
setupCursorHover(button)
},
})
const addCalendarChildren = (box, calendarJson) => {
box.children = calendarJson.map((row, i) =>
Widget.Box({
// homogeneous: true,
className: "spacing-h-5",
children: row.map((day, i) => CalendarDay(day.day, day.today)),
}),
)
}
function shiftCalendarXMonths(x) {
if (x == 0) monthshift = 0
else monthshift += x
var newDate = undefined
if (monthshift == 0) newDate = new Date()
else newDate = getDateInXMonthsTime(monthshift)
calendarJson = getCalendarLayout(newDate, monthshift == 0)
calendarMonthYear.label = `${monthshift == 0 ? "" : "• "}${newDate.toLocaleString("default", {
month: "long",
})} ${newDate.getFullYear()}`
addCalendarChildren(calendarDays, calendarJson)
}
const calendarHeader = Widget.Box({
className: "spacing-h-5 sidebar-calendar-header",
setup: box => {
box.pack_start(calendarMonthYear, false, false, 0)
box.pack_end(
Widget.Box({
className: "spacing-h-5",
children: [
Button({
className: "sidebar-calendar-monthshift-btn",
onClicked: () => shiftCalendarXMonths(-1),
child: MaterialIcon("chevron_left", "norm"),
setup: button => setupCursorHover(button),
}),
Button({
className: "sidebar-calendar-monthshift-btn",
onClicked: () => shiftCalendarXMonths(1),
child: MaterialIcon("chevron_right", "norm"),
setup: button => setupCursorHover(button),
}),
],
}),
false,
false,
0,
)
},
})
const calendarDays = Widget.Box({
hexpand: true,
vertical: true,
className: "spacing-v-5",
setup: box => {
addCalendarChildren(box, calendarJson)
},
})
return Widget.EventBox({
onScrollUp: () => shiftCalendarXMonths(-1),
onScrollDown: () => shiftCalendarXMonths(1),
child: Widget.Box({
halign: "center",
children: [
Widget.Box({
hexpand: true,
vertical: true,
className: "spacing-v-5",
children: [
calendarHeader,
Widget.Box({
homogeneous: true,
className: "spacing-h-5",
children: weekDays.map((day, i) => CalendarDay(day.day, day.today)),
}),
calendarDays,
],
}),
],
}),
})
}
const defaultTodoSelected = "undone"
const todoItems = isDone =>
Widget.Scrollable({
child: Widget.Box({
vertical: true,
connections: [
[
Todo,
self => {
self.children = Todo.todo_json.map((task, i) => {
if (task.done != isDone) return null
return Widget.Box({
className: "spacing-h-5",
children: [
Widget.Label({
className: "txt txt-small",
label: "•",
}),
Widget.Label({
hexpand: true,
xalign: 0,
wrap: true,
className: "txt txt-small sidebar-todo-txt",
label: task.content,
}),
Widget.Button({
valign: "center",
className: "txt sidebar-todo-item-action",
child: MaterialIcon(`${isDone ? "remove_done" : "check"}`, "norm", {valign: "center"}),
onClicked: () => {
if (isDone) Todo.uncheck(i)
else Todo.check(i)
},
setup: button => setupCursorHover(button),
}),
Widget.Button({
valign: "center",
className: "txt sidebar-todo-item-action",
child: MaterialIcon("delete_forever", "norm", {valign: "center"}),
onClicked: () => {
Todo.remove(i)
},
setup: button => setupCursorHover(button),
}),
],
})
})
if (self.children.length == 0) {
self.homogeneous = true
self.children = [
Widget.Box({
hexpand: true,
vertical: true,
valign: "center",
className: "txt",
children: [
MaterialIcon(`${isDone ? "checklist" : "check_circle"}`, "badonkers"),
Label({label: `${isDone ? "Finished tasks will go here" : "Nothing here!"}`}),
],
}),
]
} else self.homogeneous = false
},
"updated",
],
],
}),
})
const todoItemsBox = Widget.Stack({
valign: "fill",
transition: "slide_left_right",
items: [
["undone", todoItems(false)],
["done", todoItems(true)],
],
})
const TodoWidget = () => {
const TodoTabButton = (isDone, navIndex) =>
Widget.Button({
hexpand: true,
className: "sidebar-todo-selector-tab",
onClicked: button => {
todoItemsBox.shown = `${isDone ? "done" : "undone"}`
const kids = button.get_parent().get_children()
for (let i = 0; i < kids.length; i++) {
if (kids[i] != button) kids[i].toggleClassName("sidebar-todo-selector-tab-active", false)
else button.toggleClassName("sidebar-todo-selector-tab-active", true)
}
// Fancy highlighter line width
const buttonWidth = button.get_allocated_width()
const highlightWidth = button.get_children()[0].get_allocated_width()
navIndicator.style = `
font-size: ${navIndex}px;
padding: 0px ${(buttonWidth - highlightWidth) / 2}px;
`
},
child: Box({
halign: "center",
className: "spacing-h-5",
children: [
MaterialIcon(`${isDone ? "task_alt" : "format_list_bulleted"}`, "larger"),
Label({
className: "txt txt-smallie",
label: `${isDone ? "Done" : "Unfinished"}`,
}),
],
}),
setup: button => {
button.toggleClassName(
"sidebar-todo-selector-tab-active",
defaultTodoSelected === `${isDone ? "done" : "undone"}`,
)
setupCursorHover(button)
},
})
const undoneButton = TodoTabButton(false, 0)
const doneButton = TodoTabButton(true, 1)
const navIndicator = NavigationIndicator(2, false, {
className: "sidebar-todo-selector-highlight",
style: "font-size: 0px;",
setup: self => {
// Fancy highlighter line width
const buttonWidth = undoneButton.get_allocated_width()
const highlightWidth = undoneButton.get_children()[0].get_allocated_width()
navIndicator.style = `
font-size: ${navIndex}px;
padding: 0px ${(buttonWidth - highlightWidth) / 2}px;
`
},
})
return Widget.Box({
hexpand: true,
vertical: true,
className: "spacing-v-10",
setup: box => {
// undone/done selector rail
box.pack_start(
Widget.Box({
vertical: true,
children: [
Widget.Box({
className: "sidebar-todo-selectors spacing-h-5",
homogeneous: true,
setup: box => {
box.pack_start(undoneButton, false, true, 0)
box.pack_start(doneButton, false, true, 0)
},
}),
Widget.Box({
className: "sidebar-todo-selector-highlight-offset",
homogeneous: true,
children: [navIndicator],
}),
],
}),
false,
false,
0,
)
box.pack_end(todoItemsBox, true, true, 0)
},
})
}
const defaultShown = "calendar"
const contentStack = Widget.Stack({
hexpand: true,
items: [
["calendar", CalendarWidget()],
["todo", TodoWidget()],
// ['stars', Widget.Label({ label: 'GitHub feed will be here' })],
],
transition: "slide_up_down",
transitionDuration: 180,
setup: stack => {
stack.shown = defaultShown
},
})
const StackButton = (stackItemName, icon, name) =>
Widget.Button({
className: "button-minsize sidebar-navrail-btn sidebar-button-alone txt-small spacing-h-5",
onClicked: button => {
contentStack.shown = stackItemName
const kids = button.get_parent().get_children()
for (let i = 0; i < kids.length; i++) {
if (kids[i] != button) kids[i].toggleClassName("sidebar-navrail-btn-active", false)
else button.toggleClassName("sidebar-navrail-btn-active", true)
}
},
child: Box({
className: "spacing-v-5",
vertical: true,
children: [
Label({
className: `txt icon-material txt-hugeass`,
label: icon,
}),
Label({
label: name,
className: "txt txt-smallie",
}),
],
}),
setup: button => {
button.toggleClassName("sidebar-navrail-btn-active", defaultShown === stackItemName)
setupCursorHover(button)
},
})
export const ModuleCalendar = () =>
Box({
className: "sidebar-group spacing-h-5",
setup: box => {
box.pack_start(
Box({
valign: "center",
homogeneous: true,
vertical: true,
className: "sidebar-navrail spacing-v-10",
children: [
StackButton("calendar", "calendar_month", "Calendar"),
StackButton("todo", "checklist", "To Do"),
// StackButton(box, 'stars', 'star', 'GitHub'),
],
}),
false,
false,
0,
)
// ags.Widget({ // TDOO: replace this sad default calendar with a custom one
// type: imports.gi.Gtk.Calendar,
// }),
box.pack_end(contentStack, false, false, 0)
},
})