Compare commits

..

No commits in common. "e815e5b43933946577a9b6e84553b038b3bcc322" and "ca6e12c9e0b147c706a360c860fe642ec4f67a91" have entirely different histories.

8 changed files with 36 additions and 247 deletions

70
Cargo.lock generated
View file

@ -149,11 +149,8 @@ dependencies = [
name = "aliveline"
version = "0.1.0"
dependencies = [
"chrono",
"serde",
"slint",
"slint-build",
"toml 0.9.5",
]
[[package]]
@ -189,6 +186,12 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04"
[[package]]
name = "android-tzdata"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
[[package]]
name = "android_system_properties"
version = "0.1.5"
@ -725,15 +728,16 @@ dependencies = [
[[package]]
name = "chrono"
version = "0.4.42"
version = "0.4.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2"
checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d"
dependencies = [
"android-tzdata",
"iana-time-zone",
"js-sys",
"num-traits",
"wasm-bindgen",
"windows-link 0.2.0",
"windows-link",
]
[[package]]
@ -3835,15 +3839,6 @@ dependencies = [
"serde",
]
[[package]]
name = "serde_spanned"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "40734c41988f7306bb04f0ecf60ec0f3f1caa34290e4e8ea471dcd3346483b83"
dependencies = [
"serde",
]
[[package]]
name = "shlex"
version = "1.3.0"
@ -3904,7 +3899,7 @@ dependencies = [
"regex",
"serde_json",
"tar",
"toml 0.8.23",
"toml",
]
[[package]]
@ -4171,7 +4166,7 @@ dependencies = [
"cfg-expr",
"heck",
"pkg-config",
"toml 0.8.23",
"toml",
"version-compare",
]
@ -4345,26 +4340,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362"
dependencies = [
"serde",
"serde_spanned 0.6.9",
"serde_spanned",
"toml_datetime 0.6.11",
"toml_edit 0.22.27",
]
[[package]]
name = "toml"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75129e1dc5000bfbaa9fee9d1b21f974f9fbad9daec557a521ee6e080825f6e8"
dependencies = [
"indexmap",
"serde",
"serde_spanned 1.0.0",
"toml_datetime 0.7.0",
"toml_parser",
"toml_writer",
"winnow",
]
[[package]]
name = "toml_datetime"
version = "0.6.11"
@ -4391,7 +4371,7 @@ checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a"
dependencies = [
"indexmap",
"serde",
"serde_spanned 0.6.9",
"serde_spanned",
"toml_datetime 0.6.11",
"toml_write",
"winnow",
@ -4949,7 +4929,7 @@ dependencies = [
"windows-collections",
"windows-core 0.61.2",
"windows-future",
"windows-link 0.1.3",
"windows-link",
"windows-numerics",
]
@ -4983,7 +4963,7 @@ checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3"
dependencies = [
"windows-implement 0.60.0",
"windows-interface 0.59.1",
"windows-link 0.1.3",
"windows-link",
"windows-result 0.3.4",
"windows-strings 0.4.2",
]
@ -4995,7 +4975,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e"
dependencies = [
"windows-core 0.61.2",
"windows-link 0.1.3",
"windows-link",
"windows-threading",
]
@ -5049,12 +5029,6 @@ version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a"
[[package]]
name = "windows-link"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65"
[[package]]
name = "windows-numerics"
version = "0.2.0"
@ -5062,7 +5036,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1"
dependencies = [
"windows-core 0.61.2",
"windows-link 0.1.3",
"windows-link",
]
[[package]]
@ -5080,7 +5054,7 @@ version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6"
dependencies = [
"windows-link 0.1.3",
"windows-link",
]
[[package]]
@ -5099,7 +5073,7 @@ version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57"
dependencies = [
"windows-link 0.1.3",
"windows-link",
]
[[package]]
@ -5199,7 +5173,7 @@ version = "0.53.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91"
dependencies = [
"windows-link 0.1.3",
"windows-link",
"windows_aarch64_gnullvm 0.53.0",
"windows_aarch64_msvc 0.53.0",
"windows_i686_gnu 0.53.0",
@ -5216,7 +5190,7 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6"
dependencies = [
"windows-link 0.1.3",
"windows-link",
]
[[package]]

View file

@ -6,10 +6,7 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
chrono = "0.4.42"
serde = "1.0.219"
slint = "1.12.1"
toml = "0.9.5"
[build-dependencies]
slint-build = "1.12.1"

View file

@ -1,20 +0,0 @@
use std::path::PathBuf;
use serde::Deserialize;
#[derive(Deserialize)]
pub struct Config {
pub log_path: PathBuf
}
impl Config {
pub fn new() -> Self {
Config { log_path: PathBuf::from("./logs") }
}
pub fn load(path: PathBuf) -> Self {
if let Ok(toml_string) = std::fs::read_to_string(path) {
return toml::from_str(&toml_string).unwrap_or(Config::new());
}
Config::new()
}
}

View file

@ -1,14 +0,0 @@
use config::Config;
use std::path::PathBuf;
pub mod config;
pub fn load_config() -> Config {
if let Ok(path_str) = std::env::var("XDG_CONFIG_HOME") {
let mut path = PathBuf::from(path_str);
path.push("aliveline");
path.push("config.toml");
return Config::load(path);
}
Config::new()
}

View file

@ -3,82 +3,11 @@
use std::error::Error;
use aliveline::{config::Config, load_config};
use chrono::Timelike;
use slint::{Model, SharedString, VecModel};
slint::include_modules!();
fn main() -> Result<(), Box<dyn Error>> {
let ui = AppWindow::new()?;
let now = chrono::Local::now();
let offset = now.hour() * 3600 + now.minute() * 60 + now.second();
ui.invoke_update_record_offset(offset as i32);
ui.on_update_record_visible_time({
let ui_weak = ui.as_weak();
move |hours_string: SharedString| {
let ui = ui_weak.unwrap();
let hours = hours_string.split(' ')
.next()
.map(|h| h.parse::<i32>().unwrap())
.unwrap();
ui.set_record_visible_time(hours * 3600);
}
});
ui.on_start_new_event({
let ui_weak = ui.as_weak();
move |event_name: SharedString| {
let ui = ui_weak.unwrap();
let events_rc = ui.get_record_events();
let events = events_rc.as_any()
.downcast_ref::<VecModel<TimelineEvent>>()
.unwrap();
let offset = ui.get_record_offset();
events.push(TimelineEvent {
duration: 0,
finished: false,
label: event_name,
start: offset
});
}
});
ui.on_stop_event({
let ui_weak = ui.as_weak();
move || {
let ui = ui_weak.unwrap();
let events_rc = ui.get_record_events();
let events = events_rc.as_any().downcast_ref::<VecModel<TimelineEvent>>().unwrap();
let offset = ui.get_record_offset();
let event_id = events.iter().position(|data| !data.finished).unwrap();
let event = events.row_data(event_id).expect("stop-event called without unfinished events");
let new_event = TimelineEvent {
duration: offset - event.start,
finished: true,
label: event.label,
start: event.start
};
events.set_row_data(event_id, new_event);
}
});
ui.on_chain_event({
let ui_weak = ui.as_weak();
move |event_name: SharedString| {
let ui = ui_weak.unwrap();
ui.invoke_stop_event();
ui.invoke_start_new_event(event_name);
}
});
let config: Config = load_config();
println!("logs path: {}", config.log_path.to_str().unwrap());
ui.run()?;
Ok(())

View file

@ -1,36 +1,16 @@
import { TabWidget } from "std-widgets.slint";
import { RecordWidget } from "record.slint";
import { ReviewWidget } from "review.slint";
import { TimelineEvent } from "timeline.slint";
export component AppWindow inherits Window {
callback update-record-visible-time <=> record.update-visible-time;
callback start-new-event <=> record.start-new-event;
callback stop-event <=> record.stop-event;
callback chain-event <=> record.chain-event;
callback update-record-offset(int);
update-record-offset(new-offset) => {
record.offset = new-offset;
}
in-out property record-events <=> record.events;
in-out property record-offset <=> record.offset;
in-out property<int> record-visible-time <=> record.visible-time;
property<[string]> combo-spans: ["1 Hour", "4 Hours", "8 Hours", "24 Hours"];
title: "Aliveline";
TabWidget {
Tab {
title: "Record";
record := RecordWidget {
combo-spans: combo-spans;
}
RecordWidget {}
}
Tab {
title: "Review";
review := ReviewWidget {}
ReviewWidget {}
}
}
}

View file

@ -2,25 +2,13 @@ import { VerticalBox, LineEdit, Button, ComboBox } from "std-widgets.slint";
import { Timeline } from "timeline.slint";
export component RecordWidget inherits VerticalBox {
callback update-visible-time(string);
callback start-new-event(string);
callback chain-event(string);
callback stop-event;
in-out property visible-time <=> tl.visible-time;
in-out property updating <=> tl.updating;
in-out property offset <=> tl.offset;
in-out property events <=> tl.events;
in property<[string]> combo-spans: [];
property<bool> in-progress: false;
property<string> event-name <=> le.text;
tl := Timeline {
Timeline {
updating: true;
}
GridLayout {
spacing-vertical: 8px;
spacing-horizontal: 16px;
le := LineEdit {
LineEdit {
placeholder-text: "Event name";
text: "Event name";
font-size: 24px;
@ -29,25 +17,9 @@ export component RecordWidget inherits VerticalBox {
row: 0;
}
Button {
text: in-progress ? "Stop" : "Start";
text: "Start";
colspan: 2;
row: 1;
clicked => {
if in-progress {
root.stop-event();
} else {
root.start-new-event(event-name);
}
in-progress = !in-progress;
}
}
Button {
text: "Chain";
enabled: in-progress;
col: 1;
row: 1;
clicked => {
root.chain-event(event-name);
}
}
Text {
text: "Span:";
@ -56,13 +28,10 @@ export component RecordWidget inherits VerticalBox {
horizontal-alignment: right;
}
ComboBox {
model: combo-spans;
model: ["1 Hour", "4 Hours", "8 Hours", "24 Hours"];
current-index: 0;
row: 2;
col: 1;
selected(current-value) => {
root.update-visible-time(current-value);
}
}
}
}

View file

@ -5,30 +5,16 @@ export struct TimelineEvent {
label: string
}
global TimeString {
pure function pad-mh(seconds: int, param: int) -> string {
if seconds / param < 10 {
return "0\{floor(seconds / param)}";
}
return "\{floor(seconds / param)}";
}
pure function pad-s(seconds: int) -> string {
if mod(seconds, 60) < 10 {
return "0\{mod(seconds, 60)}";
}
return "\{mod(seconds, 60)}";
}
public pure function from(seconds: int) -> string {
return "\{pad-mh(seconds, 3600)}:\{pad-mh(mod(seconds, 3600), 60)}:\{pad-s(seconds)}";
}
}
export component Timeline inherits Rectangle {
in-out property<bool> updating: true;
in-out property<[TimelineEvent]> events: [];
in-out property<int> visible-time: 3600;
in-out property<[TimelineEvent]> events: [
{ start: 5, duration: 3, finished: true, label: "Event 1" },
{ start: 10, duration: 15, finished: true, label: "Event 2" },
{ start: 30, duration: 0, finished: false, label: "Event 3" }
];
in-out property<int> visible-time: 60;
property<int> visible-offset: max(offset, visible-time);
in-out property<int> offset: 0;
in-out property<int> offset: 60;
timer := Timer {
interval: 1s;
@ -52,18 +38,6 @@ export component Timeline inherits Rectangle {
background: purple;
}
Text {
x: 0;
y: parent.height - self.height;
text: TimeString.from(visible-offset - visible-time);
}
Text {
x: parent.width - self.width;
y: parent.height - self.height;
text: TimeString.from(visible-offset);
}
for event in events: timeline-event := Rectangle {
property<length> real-x: ((visible-time - (visible-offset - event.start)) / visible-time) * parent.width;
x: max(real-x, 0);