First commit
This commit is contained in:
commit
8585f5741f
13 changed files with 505 additions and 0 deletions
54
ui/app-window.slint
Normal file
54
ui/app-window.slint
Normal file
|
@ -0,0 +1,54 @@
|
|||
import { State, SessionStep, CountdownStatus } from "./state.slint";
|
||||
import { VText, VButton, VActionButton, Svg, Palette } from "@selenite";
|
||||
import { CountdownView } from "./countdown-view.slint";
|
||||
import { SettingsView } from "settings-view.slint";
|
||||
|
||||
enum CurrentView {
|
||||
Countdown,
|
||||
Settings
|
||||
}
|
||||
|
||||
export component AppWindow inherits Window {
|
||||
title: "Focus";
|
||||
callback start-stop;
|
||||
property <CurrentView> current-view: CurrentView.Countdown;
|
||||
|
||||
background: Palette.background;
|
||||
default-font-size: 16px;
|
||||
padding: 0px;
|
||||
|
||||
VerticalLayout {
|
||||
width: parent.width;
|
||||
height: parent.height;
|
||||
|
||||
HorizontalLayout {
|
||||
padding: 8px;
|
||||
vertical-stretch: 0;
|
||||
alignment: start;
|
||||
settingsButtons := VActionButton {
|
||||
icon-svg: Svg.burger;
|
||||
background: Palette.background.transparentize(1);
|
||||
clicked => {
|
||||
if (current-view == CurrentView.Countdown) {
|
||||
current-view = CurrentView.Settings;
|
||||
} else if (current-view == CurrentView.Settings) {
|
||||
current-view = CurrentView.Countdown;
|
||||
State.config-changed();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if current-view == CurrentView.Countdown : countdown-view := CountdownView {
|
||||
start-stop => { root.start-stop() }
|
||||
vertical-stretch: 1;
|
||||
padding: 32px;
|
||||
padding-top: 0px;
|
||||
}
|
||||
if current-view == CurrentView.Settings : settings-view := SettingsView {
|
||||
vertical-stretch: 1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export { State }
|
68
ui/countdown-view.slint
Normal file
68
ui/countdown-view.slint
Normal file
|
@ -0,0 +1,68 @@
|
|||
import { State, SessionStep, CountdownStatus } from "./state.slint";
|
||||
import { VText, VButton, VActionButton, Svg, Palette } from "@selenite";
|
||||
import { Utils } from "utils.slint";
|
||||
|
||||
export component CountdownView inherits VerticalLayout {
|
||||
callback start-stop <=> startStopButton.clicked;
|
||||
|
||||
pure function format-session-step(session-step: SessionStep) -> string {
|
||||
if (session-step == SessionStep.Setup) {
|
||||
return "Setup";
|
||||
}
|
||||
if (session-step == SessionStep.Focus) {
|
||||
return "Focus";
|
||||
}
|
||||
if (session-step == SessionStep.Break) {
|
||||
return "Break";
|
||||
}
|
||||
if (session-step == SessionStep.Finished) {
|
||||
return "Finished";
|
||||
}
|
||||
return "Not implemented";
|
||||
}
|
||||
|
||||
VerticalLayout {
|
||||
|
||||
spacing: 32px;
|
||||
alignment: center;
|
||||
|
||||
VerticalLayout {
|
||||
VText {
|
||||
font-size: 3rem;
|
||||
letter-spacing: 0.2rem;
|
||||
font-weight: 600;
|
||||
text: "\{Utils.format-countdown(State.countdown)}";
|
||||
horizontal-alignment: center;
|
||||
}
|
||||
VText {
|
||||
color: Palette.foreground-hint;
|
||||
text: format-session-step(State.sessions-step);
|
||||
horizontal-alignment: center;
|
||||
}
|
||||
}
|
||||
HorizontalLayout {
|
||||
alignment: space-between;
|
||||
spacing: 8px;
|
||||
for step[step-index] in State.max-session-count: Rectangle {
|
||||
preferred-width: 16px;
|
||||
preferred-height: 16px;
|
||||
border-radius: 32px;
|
||||
background: step-index + 1 == State.current-session
|
||||
? Palette.accent.transparentize(0.5)
|
||||
: step-index + 1 < State.current-session ? Palette.accent
|
||||
: Palette.control-background;
|
||||
animate background {
|
||||
duration: 0.5s;
|
||||
}
|
||||
}
|
||||
}
|
||||
HorizontalLayout {
|
||||
alignment: center;
|
||||
startStopButton := VActionButton {
|
||||
background: Palette.foreground.transparentize(1);
|
||||
icon-size: 2rem;
|
||||
icon-svg: State.countdown-status != CountdownStatus.Running ? Svg.play : Svg.pause;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
44
ui/settings-view.slint
Normal file
44
ui/settings-view.slint
Normal file
|
@ -0,0 +1,44 @@
|
|||
import { State, SessionStep, CountdownStatus } from "./state.slint";
|
||||
import { VText, VButton, VSlider, Palette } from "@selenite";
|
||||
import { Utils } from "utils.slint";
|
||||
|
||||
export component SettingsView inherits Rectangle {
|
||||
VerticalLayout {
|
||||
padding: 32px;
|
||||
spacing: 32px;
|
||||
alignment: center;
|
||||
VSlider {
|
||||
label: "Session duration";
|
||||
label-size: 1.25rem;
|
||||
label-alignment: TextHorizontalAlignment.center;
|
||||
no-background: true;
|
||||
minimum: 1;
|
||||
maximum: 60 * 60;
|
||||
value: State.focus-countdown-duration;
|
||||
format-value(value) => { return Utils.format-countdown(value); }
|
||||
released(value) => { State.focus-countdown-duration = value; }
|
||||
}
|
||||
VSlider {
|
||||
label: "Break duration";
|
||||
label-size: 1.25rem;
|
||||
label-alignment: TextHorizontalAlignment.center;
|
||||
no-background: true;
|
||||
minimum: 1;
|
||||
maximum: 60 * 60;
|
||||
value: State.break-countdown-duration;
|
||||
format-value(value) => { return Utils.format-countdown(value); }
|
||||
released(value) => { State.break-countdown-duration = value; }
|
||||
}
|
||||
VSlider {
|
||||
label: "Number of session";
|
||||
label-size: 1.25rem;
|
||||
label-alignment: TextHorizontalAlignment.center;
|
||||
no-background: true;
|
||||
minimum: 1;
|
||||
maximum: 8;
|
||||
value: State.max-session-count;
|
||||
format-value(value) => { return Math.round(value); }
|
||||
released(value) => { State.max-session-count = Math.round(value); }
|
||||
}
|
||||
}
|
||||
}
|
24
ui/state.slint
Normal file
24
ui/state.slint
Normal file
|
@ -0,0 +1,24 @@
|
|||
export enum SessionStep {
|
||||
Setup,
|
||||
Focus,
|
||||
Break,
|
||||
Finished,
|
||||
}
|
||||
|
||||
export enum CountdownStatus {
|
||||
Running,
|
||||
Paused,
|
||||
NotStarted
|
||||
}
|
||||
|
||||
export global State {
|
||||
in-out property <int> countdown;
|
||||
in-out property <int> focus-countdown-duration;
|
||||
in-out property <int> break-countdown-duration;
|
||||
in-out property <SessionStep> sessions-step;
|
||||
in-out property <CountdownStatus> countdown-status;
|
||||
in-out property <int> current-session;
|
||||
in-out property <int> max-session-count;
|
||||
|
||||
callback config-changed();
|
||||
}
|
12
ui/utils.slint
Normal file
12
ui/utils.slint
Normal file
|
@ -0,0 +1,12 @@
|
|||
export global Utils {
|
||||
public pure function format-zero-padding(number: int) -> string {
|
||||
if (number < 10) {
|
||||
return "0\{number}";
|
||||
}
|
||||
return number;
|
||||
}
|
||||
|
||||
public pure function format-countdown(countdown: int) -> string {
|
||||
return "\{format-zero-padding(countdown / 60)}:\{format-zero-padding(Math.mod(countdown, 60))}";
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue