mirror of
https://codeberg.org/vyn/mirai.git
synced 2025-07-01 08:53:20 +00:00
Compare commits
3 commits
ef56efd314
...
4bca7fac3e
Author | SHA1 | Date | |
---|---|---|---|
4bca7fac3e | |||
d208fc6ca4 | |||
e10b466b60 |
16 changed files with 112 additions and 50 deletions
|
@ -24,7 +24,8 @@ class Mirai
|
|||
void addSource(
|
||||
const std::string &name, const std::string &type, std::unique_ptr<DataProvider> &&source
|
||||
);
|
||||
void editSource(int id, const std::string &name, const std::string &path);
|
||||
void
|
||||
editSource(int id, const std::string &name, const std::string &color, const std::string &path);
|
||||
void deleteSource(int id);
|
||||
void unloadAllSources();
|
||||
void save();
|
||||
|
|
|
@ -32,6 +32,7 @@ struct createEventParams {
|
|||
|
||||
struct SourceConstructor {
|
||||
std::string name;
|
||||
std::string color;
|
||||
DataProvider *sourceDataProvider;
|
||||
};
|
||||
|
||||
|
@ -39,7 +40,8 @@ class Source
|
|||
{
|
||||
public:
|
||||
Source(SourceConstructor params)
|
||||
: data(params.sourceDataProvider), name_(params.name), type_("FileSystemMarkdown")
|
||||
: data(params.sourceDataProvider), name_(params.name), color_(params.color),
|
||||
type_("FileSystemMarkdown")
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -56,9 +58,11 @@ class Source
|
|||
|
||||
std::string name() const;
|
||||
std::string type() const;
|
||||
std::string color() const;
|
||||
DataProvider *dataProvider();
|
||||
|
||||
void setName(const std::string &name);
|
||||
void setColor(const std::string &color);
|
||||
|
||||
void createTask(const createTaskParams &task);
|
||||
void removeTask(const Task &task);
|
||||
|
@ -92,6 +96,7 @@ class Source
|
|||
|
||||
std::string name_;
|
||||
std::string type_;
|
||||
std::string color_;
|
||||
DataProvider *data;
|
||||
};
|
||||
} // namespace mirai
|
||||
|
|
13
external/mirai-core/src/Mirai.cpp
vendored
13
external/mirai-core/src/Mirai.cpp
vendored
|
@ -41,14 +41,15 @@ void Mirai::loadConfig(const std::string &path)
|
|||
auto &filePath = jsonSources[i];
|
||||
assert(filePath.isObject());
|
||||
const auto name = filePath.asObject().getString("name");
|
||||
const auto color = filePath.asObject().getString("color");
|
||||
const auto path = filePath.asObject().getString("path");
|
||||
std::unique_ptr<DataProvider> file = std::make_unique<MarkdownDataProvider>(path);
|
||||
DataProvider *sourceDataProvider = file.release();
|
||||
sourceDataProvider->load();
|
||||
sources_.push_back(
|
||||
std::make_unique<Source>(
|
||||
SourceConstructor{.name = name, .sourceDataProvider = sourceDataProvider}
|
||||
)
|
||||
std::make_unique<Source>(SourceConstructor{
|
||||
.name = name, .color = color, .sourceDataProvider = sourceDataProvider
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -67,6 +68,7 @@ void Mirai::saveConfig()
|
|||
|
||||
rei::json::JsonObject jsonSource;
|
||||
jsonSource.set("name", source->name());
|
||||
jsonSource.set("color", source->color());
|
||||
auto dataProvider = dynamic_cast<MarkdownDataProvider *>(source->dataProvider());
|
||||
jsonSource.set("path", dataProvider->path());
|
||||
jsonSource.set("type", "FileSystemMarkdown");
|
||||
|
@ -96,10 +98,13 @@ void Mirai::addSource(
|
|||
sourceAdded.emit(nullptr);
|
||||
};
|
||||
|
||||
void Mirai::editSource(int id, const std::string &name, const std::string &path)
|
||||
void Mirai::editSource(
|
||||
int id, const std::string &name, const std::string &color, const std::string &path
|
||||
)
|
||||
{
|
||||
auto source = getSourceById(id);
|
||||
source->setName(name);
|
||||
source->setColor(color);
|
||||
|
||||
DataProvider *sourceDataProvider = source->dataProvider();
|
||||
saveConfig();
|
||||
|
|
13
external/mirai-core/src/Source.cpp
vendored
13
external/mirai-core/src/Source.cpp
vendored
|
@ -52,8 +52,7 @@ std::vector<Day> Source::getDays()
|
|||
auto daysData = data->getDays();
|
||||
std::vector<Day> days;
|
||||
std::transform(
|
||||
daysData.begin(), daysData.end(), std::back_inserter(days),
|
||||
[&](const DayData &dayData) {
|
||||
daysData.begin(), daysData.end(), std::back_inserter(days), [&](const DayData &dayData) {
|
||||
return Day{data, dayData};
|
||||
}
|
||||
);
|
||||
|
@ -148,11 +147,21 @@ std::string Source::name() const
|
|||
return name_;
|
||||
}
|
||||
|
||||
std::string Source::color() const
|
||||
{
|
||||
return color_;
|
||||
}
|
||||
|
||||
void Source::setName(const std::string &name)
|
||||
{
|
||||
name_ = name;
|
||||
}
|
||||
|
||||
void Source::setColor(const std::string &color)
|
||||
{
|
||||
color_ = color;
|
||||
}
|
||||
|
||||
std::string Source::type() const
|
||||
{
|
||||
// There is only 1 type for now
|
||||
|
|
2
external/selenite
vendored
2
external/selenite
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 6ff7dd8ea890bec8f4f61304e64bbfeabd61e7a8
|
||||
Subproject commit 0fa6be0b1abe9534a8a1252496b7c97219c1559e
|
|
@ -1,25 +1,7 @@
|
|||
import { ScrollView, Date, Time } from "std-widgets.slint";
|
||||
import { VCheckBox, VButton, VActionButton, Svg, VTag, VPopupIconMenu, VText, Palette } from "@selenite";
|
||||
import { Utils } from "../shared/Utils.slint";
|
||||
|
||||
export struct CalendarDayEvent {
|
||||
sourceId: int,
|
||||
id: int,
|
||||
title: string,
|
||||
startsAt: Time,
|
||||
endsAt: Time
|
||||
}
|
||||
|
||||
export struct CalendarDay {
|
||||
events: [CalendarDayEvent],
|
||||
date: Date,
|
||||
header: string,
|
||||
}
|
||||
|
||||
export enum CalendarDateDisplayFormat {
|
||||
Relative,
|
||||
Normal
|
||||
}
|
||||
import { AppModels, CalendarDay, CalendarDateDisplayFormat } from "../shared/Models.slint";
|
||||
|
||||
export component Calendar inherits Rectangle {
|
||||
in property<[CalendarDay]> days;
|
||||
|
@ -65,16 +47,23 @@ export component Calendar inherits Rectangle {
|
|||
|
||||
}
|
||||
Rectangle {
|
||||
Rectangle { // Last bar delimiting days
|
||||
x: parent.width - 1px;
|
||||
y: header-height - 32px;
|
||||
width: 1px;
|
||||
height: parent.height - self.y;
|
||||
background: Palette.card-background.brighter(0.3);
|
||||
}
|
||||
min-width: 400px;
|
||||
//background: green;
|
||||
HorizontalLayout {
|
||||
for day[day-index] in root.days: Rectangle {
|
||||
if day-index > 0 : Rectangle {
|
||||
Rectangle { // Bar delimiting days
|
||||
x: 0;
|
||||
y: header-height - 32px;
|
||||
width: 1px;
|
||||
height: parent.height;
|
||||
background: Palette.card-background.brighter(0.5);
|
||||
height: parent.height - self.y;
|
||||
background: Palette.card-background.brighter(0.3);
|
||||
}
|
||||
VerticalLayout {
|
||||
y: 0;
|
||||
|
@ -87,7 +76,7 @@ export component Calendar inherits Rectangle {
|
|||
}
|
||||
}
|
||||
for hour[hour-index] in 24 : Rectangle {
|
||||
background: Palette.card-background.brighter(0.5);
|
||||
background: Palette.card-background.brighter(0.3);
|
||||
x: 0px;
|
||||
width: parent.width;
|
||||
y: day-start-y + hour-spacing * hour-index;
|
||||
|
@ -96,11 +85,18 @@ export component Calendar inherits Rectangle {
|
|||
if day.date == root.current-date : Rectangle {
|
||||
background: Palette.red;
|
||||
x: 0px;
|
||||
width: parent.width;
|
||||
y: day-start-y + hour-spacing * root.current-time.hour + (root.current-time.minute / 60 * hour-spacing);
|
||||
width: parent.width;
|
||||
height: 1px;
|
||||
z: 100;
|
||||
}
|
||||
for event[event-index] in day.events : Rectangle {
|
||||
Rectangle {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: AppModels.get-source-color-from-id-as-color(event.sourceId);
|
||||
opacity: 0.05;
|
||||
}
|
||||
background: Palette.card-background;
|
||||
border-radius: 4px;
|
||||
x: 8px;
|
||||
|
@ -111,7 +107,7 @@ export component Calendar inherits Rectangle {
|
|||
HorizontalLayout {
|
||||
Rectangle {
|
||||
width: 4px;
|
||||
background: Palette.accent;
|
||||
background: AppModels.get-source-color-from-id-as-color(event.sourceId);
|
||||
}
|
||||
VerticalLayout {
|
||||
padding: 16px;
|
||||
|
|
|
@ -58,7 +58,9 @@ export component CreateTaskOrEvent inherits Rectangle {
|
|||
VText { text: "for"; vertical-alignment: bottom;}
|
||||
VerticalLayout {
|
||||
alignment: end;
|
||||
sourceInput := ComboBox {
|
||||
// This ComboBox cause UI lag when loaded first time.
|
||||
// Same thing without the `model` set.
|
||||
sourceInput := ComboBox {
|
||||
model: root.sources;
|
||||
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ import { ToggleButton } from "@selenite";
|
|||
import { VPopupIconMenu, VTag, VText, VButton, VActionButton, VCheckBox, Svg, Palette } from "@selenite";
|
||||
import { TaskEdit } from "./TaskEdit.slint";
|
||||
import { Date } from "std-widgets.slint";
|
||||
import { AppModels } from "../shared/Models.slint";
|
||||
|
||||
export struct TaskLineEditData {
|
||||
title: string,
|
||||
|
@ -13,6 +14,7 @@ export struct TaskLineEditData {
|
|||
export component TaskLine inherits VerticalLayout {
|
||||
in property<string> title;
|
||||
in property<string> source-name;
|
||||
in property<color> source-color;
|
||||
in property<bool> hide-source-name;
|
||||
in property<bool> scheduled;
|
||||
in property<Date> date;
|
||||
|
@ -91,7 +93,7 @@ export component TaskLine inherits VerticalLayout {
|
|||
}
|
||||
}
|
||||
if !hide-source-name : source-name := VTag {
|
||||
text-color: Palette.accent;
|
||||
text-color: root.source-color;
|
||||
text: "\{root.source-name}";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,11 +8,13 @@ import { Modal } from "../../external/selenite/components/Modal.slint";
|
|||
export component EditSourceModal inherits Modal {
|
||||
private property <int> source-id-to-edit: -1;
|
||||
private property <string> name: "";
|
||||
private property <string> color_: ""; // Well, cannot override 'color'
|
||||
private property <string> path: "";
|
||||
|
||||
public function edit(source-id: int) {
|
||||
source-id-to-edit = source-id;
|
||||
root.name = AppModels.get-source-name-from-id(source-id);
|
||||
root.color_ = AppModels.get-source-color-from-id-as-hex(source-id);
|
||||
root.path = AppModels.get-source-path-from-id(source-id);
|
||||
root.show();
|
||||
}
|
||||
|
@ -24,6 +26,10 @@ export component EditSourceModal inherits Modal {
|
|||
label: "Name";
|
||||
text <=> root.name;
|
||||
}
|
||||
colorInput := VTextInput {
|
||||
label: "Color";
|
||||
text <=> root.color_;
|
||||
}
|
||||
pathInput := VTextInput {
|
||||
label: "Path";
|
||||
text <=> root.path;
|
||||
|
@ -31,7 +37,7 @@ export component EditSourceModal inherits Modal {
|
|||
VButton {
|
||||
text: "Save";
|
||||
clicked => {
|
||||
AppActions.edit-source(source-id-to-edit, name, path);
|
||||
AppActions.edit-source(source-id-to-edit, name, color_, path);
|
||||
root.close();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { Date, Time } from "std-widgets.slint";
|
||||
import { CalendarDay } from "../components/Calendar.slint";
|
||||
import { CalendarDay } from "./Models.slint";
|
||||
|
||||
export struct NewTaskData {
|
||||
sourceId: int,
|
||||
|
@ -33,7 +33,7 @@ export global AppActions {
|
|||
callback task-clicked(int, int);
|
||||
callback source-clicked(int);
|
||||
callback add-source(name: string, path: string);
|
||||
callback edit-source(sourceId: int, name: string, path: string);
|
||||
callback edit-source(sourceId: int, name: string, color: string, path: string);
|
||||
|
||||
callback toggle-show-completed-tasks();
|
||||
callback delete-task-clicked(int, int);
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import { Date, Time } from "std-widgets.slint";
|
||||
import { CalendarDay } from "../components/Calendar.slint";
|
||||
|
||||
export struct Source {
|
||||
id: int,
|
||||
|
@ -37,6 +36,25 @@ export struct Day {
|
|||
relativeDaysDiff: int
|
||||
}
|
||||
|
||||
export struct CalendarDayEvent {
|
||||
sourceId: int,
|
||||
id: int,
|
||||
title: string,
|
||||
startsAt: Time,
|
||||
endsAt: Time
|
||||
}
|
||||
|
||||
export struct CalendarDay {
|
||||
events: [CalendarDayEvent],
|
||||
date: Date,
|
||||
header: string,
|
||||
}
|
||||
|
||||
export enum CalendarDateDisplayFormat {
|
||||
Relative,
|
||||
Normal
|
||||
}
|
||||
|
||||
export global AppModels {
|
||||
in-out property<[Source]> sources-selected;
|
||||
in-out property<int> default-source-index;
|
||||
|
@ -48,5 +66,7 @@ export global AppModels {
|
|||
|
||||
callback get-source-id-from-name(string) -> int;
|
||||
pure callback get-source-name-from-id(int) -> string;
|
||||
pure callback get-source-color-from-id-as-color(int) -> color;
|
||||
pure callback get-source-color-from-id-as-hex(int) -> string;
|
||||
pure callback get-source-path-from-id(int) -> string;
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "mirai-core/MarkdownDataProvider.h"
|
||||
#include "mirai-core/Mirai.h"
|
||||
#include "selenite/palette.h"
|
||||
#include "slint_color.h"
|
||||
#include "slint_string.h"
|
||||
#include "ui.h"
|
||||
#include <bits/chrono.h>
|
||||
|
@ -97,6 +98,19 @@ void AppWindow::setupCallbacks()
|
|||
return slint::SharedString(source->name());
|
||||
});
|
||||
|
||||
models().on_get_source_color_from_id_as_hex([&](int sourceId) {
|
||||
auto source = miraiInstance_->getSourceById(sourceId);
|
||||
assert(source);
|
||||
return slint::SharedString(source->color());
|
||||
});
|
||||
|
||||
models().on_get_source_color_from_id_as_color([&](int sourceId) {
|
||||
auto source = miraiInstance_->getSourceById(sourceId);
|
||||
assert(source);
|
||||
auto color = selenite::hexStringToColor(source->color());
|
||||
return slint::Color::from_rgb_uint8(color.r, color.g, color.b);
|
||||
});
|
||||
|
||||
models().on_get_source_path_from_id([&](int sourceId) {
|
||||
auto source = miraiInstance_->getSourceById(sourceId);
|
||||
assert(source);
|
||||
|
@ -150,8 +164,11 @@ void AppWindow::setupCallbacks()
|
|||
miraiInstance_->addSource(std::string(name), "FileSystemMarkdown", std::move(file));
|
||||
});
|
||||
|
||||
actions().on_edit_source([&](int sourceId, slint::SharedString name, slint::SharedString path) {
|
||||
miraiInstance_->editSource(sourceId, std::string(name), std::string(path));
|
||||
actions().on_edit_source([&](int sourceId, slint::SharedString name, slint::SharedString color,
|
||||
slint::SharedString path) {
|
||||
miraiInstance_->editSource(
|
||||
sourceId, std::string(name), std::string(color), std::string(path)
|
||||
);
|
||||
});
|
||||
|
||||
actions().on_delete_task_clicked([&](int sourceId, int taskId) {
|
||||
|
|
|
@ -4,7 +4,7 @@ import { MainView } from "views/TasksView.slint";
|
|||
import { Palette } from "@selenite";
|
||||
import { CalendarView } from "views/CalendarView.slint";
|
||||
import { VButton } from "../../../external/selenite/components/Button.slint";
|
||||
import { ToggleButton } from "../../../external/selenite/components/index.slint";
|
||||
import { ToggleButton, Svg } from "../../../external/selenite/components/index.slint";
|
||||
import { VTextInput } from "../../../external/selenite/components/TextInput.slint";
|
||||
import { AppActions } from "../../shared/Actions.slint";
|
||||
import { SideBar } from "views/SideBar.slint";
|
||||
|
@ -33,12 +33,14 @@ export component AppWindow inherits Window {
|
|||
spacing: 8px;
|
||||
ToggleButton {
|
||||
text: "Calendar";
|
||||
icon-svg: Svg.calendar;
|
||||
active: !show-tasks;
|
||||
clicked => { show-tasks = false }
|
||||
}
|
||||
|
||||
ToggleButton {
|
||||
text: "Tasks";
|
||||
icon-svg: Svg.tasks;
|
||||
active: show-tasks;
|
||||
clicked => { show-tasks = true }
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ export component CalendarView inherits Rectangle {
|
|||
VButton {
|
||||
text: "New event";
|
||||
icon-svg: Svg.plus;
|
||||
icon-colorize: greenyellow;
|
||||
icon-colorize: Palette.green;
|
||||
clicked => {
|
||||
createEventPopup.show();
|
||||
}
|
||||
|
|
|
@ -56,12 +56,7 @@ export component SideBar inherits Rectangle {
|
|||
text-alignment: left;
|
||||
active: item.selected;
|
||||
clicked => { AppActions.source-clicked(item.id) }
|
||||
VActionButton {
|
||||
visible: parent.active;
|
||||
icon-svg: Svg.cog;
|
||||
background: transparent;
|
||||
clicked => { editSourcePopup.edit(item.id) }
|
||||
}
|
||||
right-clicked => { editSourcePopup.edit(item.id) }
|
||||
}
|
||||
}
|
||||
VerticalLayout {
|
||||
|
|
|
@ -93,6 +93,7 @@ export component MainView inherits Rectangle {
|
|||
TaskLine {
|
||||
title: task.title;
|
||||
source-name: AppModels.get-source-name-from-id(task.sourceId);
|
||||
source-color: AppModels.get-source-color-from-id-as-color(task.sourceId);
|
||||
scheduled: task.date.year != 0;
|
||||
date: day.date;
|
||||
checked: task.checked;
|
||||
|
@ -136,6 +137,7 @@ export component MainView inherits Rectangle {
|
|||
TaskLine {
|
||||
title: task.title;
|
||||
source-name: AppModels.get-source-name-from-id(task.sourceId);
|
||||
source-color: AppModels.get-source-color-from-id-as-color(task.sourceId);
|
||||
checked: task.checked;
|
||||
allow-edit-date: true;
|
||||
delete => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue