nichts/modules/styling/config/widgets/sideright/todolist.js

279 lines
10 KiB
JavaScript

import Widget from 'resource:///com/github/Aylur/ags/widget.js';
import * as Utils from 'resource:///com/github/Aylur/ags/utils.js';
const { Box, Button, Label, Revealer } = Widget;
import { MaterialIcon } from "../../lib/materialicon.js";
import Todo from "../../services/todo.js";
import { setupCursorHover } from "../../lib/cursorhover.js";
import { NavigationIndicator } from "../../lib/navigationindicator.js";
const defaultTodoSelected = 'undone';
const todoListItem = (task, id, isDone, isEven = false) => {
const crosser = Widget.Box({
className: 'sidebar-todo-crosser',
});
const todoContent = Widget.Box({
className: 'sidebar-todo-item spacing-h-5',
children: [
Widget.Label({
hexpand: true,
xalign: 0,
wrap: true,
className: 'txt txt-small sidebar-todo-txt',
label: task.content,
selectable: true,
}),
Widget.Button({ // Check/Uncheck
vpack: 'center',
className: 'txt sidebar-todo-item-action',
child: MaterialIcon(`${isDone ? 'remove_done' : 'check'}`, 'norm', { vpack: 'center' }),
onClicked: (self) => {
const contentWidth = todoContent.get_allocated_width();
crosser.toggleClassName('sidebar-todo-crosser-crossed', true);
crosser.css = `margin-left: -${contentWidth}px;`;
Utils.timeout(200, () => {
widgetRevealer.revealChild = false;
})
Utils.timeout(350, () => {
if (isDone)
Todo.uncheck(id);
else
Todo.check(id);
})
},
setup: setupCursorHover,
}),
Widget.Button({ // Remove
vpack: 'center',
className: 'txt sidebar-todo-item-action',
child: MaterialIcon('delete_forever', 'norm', { vpack: 'center' }),
onClicked: () => {
const contentWidth = todoContent.get_allocated_width();
crosser.toggleClassName('sidebar-todo-crosser-removed', true);
crosser.css = `margin-left: -${contentWidth}px;`;
Utils.timeout(200, () => {
widgetRevealer.revealChild = false;
})
Utils.timeout(350, () => {
Todo.remove(id);
})
},
setup: setupCursorHover,
}),
crosser,
]
});
const widgetRevealer = Widget.Revealer({
revealChild: true,
transition: 'slide_down',
transitionDuration: 150,
child: todoContent,
})
return widgetRevealer;
}
const todoItems = (isDone) => Widget.Scrollable({
hscroll: 'never',
vscroll: 'automatic',
child: Widget.Box({
vertical: true,
setup: (self) => self
.hook(Todo, (self) => {
self.children = Todo.todo_json.map((task, i) => {
if (task.done != isDone) return null;
return todoListItem(task, i, isDone);
})
if (self.children.length == 0) {
self.homogeneous = true;
self.children = [
Widget.Box({
hexpand: true,
vertical: true,
vpack: 'center',
className: 'txt',
children: [
MaterialIcon(`${isDone ? 'checklist' : 'check_circle'}`, 'gigantic'),
Label({ label: `${isDone ? 'Finished tasks will go here' : 'Nothing here!'}` })
]
})
]
}
else self.homogeneous = false;
}, 'updated')
,
}),
setup: (listContents) => {
const vScrollbar = listContents.get_vscrollbar();
vScrollbar.get_style_context().add_class('sidebar-scrollbar');
}
});
const UndoneTodoList = () => {
const newTaskButton = Revealer({
transition: 'slide_left',
transitionDuration: 200,
revealChild: true,
child: Button({
className: 'txt-small sidebar-todo-new',
halign: 'end',
vpack: 'center',
label: '+ New task',
setup: setupCursorHover,
onClicked: (self) => {
newTaskButton.revealChild = false;
newTaskEntryRevealer.revealChild = true;
confirmAddTask.revealChild = true;
cancelAddTask.revealChild = true;
newTaskEntry.grab_focus();
}
})
});
const cancelAddTask = Revealer({
transition: 'slide_right',
transitionDuration: 200,
revealChild: false,
child: Button({
className: 'txt-norm icon-material sidebar-todo-add',
halign: 'end',
vpack: 'center',
label: 'close',
setup: setupCursorHover,
onClicked: (self) => {
newTaskEntryRevealer.revealChild = false;
confirmAddTask.revealChild = false;
cancelAddTask.revealChild = false;
newTaskButton.revealChild = true;
newTaskEntry.text = '';
}
})
});
const newTaskEntry = Widget.Entry({
// hexpand: true,
vpack: 'center',
className: 'txt-small sidebar-todo-entry',
placeholderText: 'Add a task...',
onAccept: ({ text }) => {
if (text == '') return;
Todo.add(text)
newTaskEntry.text = '';
},
onChange: ({ text }) => confirmAddTask.child.toggleClassName('sidebar-todo-add-available', text != ''),
});
const newTaskEntryRevealer = Revealer({
transition: 'slide_right',
transitionDuration: 200,
revealChild: false,
child: newTaskEntry,
});
const confirmAddTask = Revealer({
transition: 'slide_right',
transitionDuration: 200,
revealChild: false,
child: Button({
className: 'txt-norm icon-material sidebar-todo-add',
halign: 'end',
vpack: 'center',
label: 'arrow_upward',
setup: setupCursorHover,
onClicked: (self) => {
if (newTaskEntry.text == '') return;
Todo.add(newTaskEntry.text);
newTaskEntry.text = '';
}
})
});
return Box({ // The list, with a New button
vertical: true,
className: 'spacing-v-5',
setup: (box) => {
box.pack_start(todoItems(false), true, true, 0);
box.pack_start(Box({
setup: (self) => {
self.pack_start(cancelAddTask, false, false, 0);
self.pack_start(newTaskEntryRevealer, true, true, 0);
self.pack_start(confirmAddTask, false, false, 0);
self.pack_start(newTaskButton, false, false, 0);
}
}), false, false, 0);
},
});
}
const todoItemsBox = Widget.Stack({
vpack: 'fill',
transition: 'slide_left_right',
children: {
'undone': UndoneTodoList(),
'done': todoItems(true),
},
});
export const TodoWidget = () => {
const TodoTabButton = (isDone, navIndex) => Widget.Button({
hexpand: true,
className: 'sidebar-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-selector-tab-active', false);
else button.toggleClassName('sidebar-selector-tab-active', true);
}
// Fancy highlighter line width
const buttonWidth = button.get_allocated_width();
const highlightWidth = button.get_children()[0].get_allocated_width();
navIndicator.css = `
font-size: ${navIndex}px;
padding: 0px ${(buttonWidth - highlightWidth) / 2}px;
`;
},
child: Box({
hpack: '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) => Utils.timeout(1, () => {
setupCursorHover(button);
button.toggleClassName('sidebar-selector-tab-active', defaultTodoSelected === `${isDone ? 'done' : 'undone'}`);
}),
});
const undoneButton = TodoTabButton(false, 0);
const doneButton = TodoTabButton(true, 1);
const navIndicator = NavigationIndicator(2, false, { // The line thing
className: 'sidebar-selector-highlight',
css: 'font-size: 0px; padding: 0rem 1.636rem;', // Shush
})
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-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-selector-highlight-offset',
homogeneous: true,
children: [navIndicator]
})
]
}), false, false, 0);
box.pack_end(todoItemsBox, true, true, 0);
},
});
};