import { Palette, Button, VerticalBox, HorizontalBox, ScrollView, ListView, StandardListView } from "std-widgets.slint";
export struct ChangeData {
hash: string,
// TODO display all authors
// authors: [string],
author: string,
timestamp: string,
message: string,
}
export struct ChannelsData {
names: [string],
active: int,
}
component DeltasList {
in property <string> delta;
VerticalBox {
Text {
vertical-stretch: 0;
text: "change";
}
ScrollView {
vertical-stretch: 1;
viewport-width <=> text.width;
viewport-height <=> text.height;
text := Text {
width: 100%;
text: delta;
}
}
}
}
component DiffEntry inherits Rectangle {
in property <int> files-count;
VerticalBox {
label := Text {
text: "\{files-count} files changed";
}
}
in-out property <bool> is-selected: false;
in property <bool> has-hover;
states [
selected when root.is-selected: {
root.background: Palette.selection-background;
label.color: Palette.selection-foreground;
}
lowlighted when root.has-hover: {
root.background: Palette.alternate-background;
label.color: Palette.alternate-foreground;
}
]
}
component ChangeEntry inherits Rectangle {
in-out property <string> hash;
in-out property <string> author;
in-out property <string> timestamp;
in-out property <string> message;
// Each text element is given default text, in case it's empty
// 1) it looks nicer
// 2) it makes empty entries the same height as filled entries
// -> uniform-height entries are more performant in a ListView
VerticalBox {
spacing: 5px;
msg-text := Text {
text: message == "" ? "(no message)" : "\{root.message}";
overflow: elide;
font-italic: message == "";
}
author-text := Text {
text: author == "" ? "(no author)" : "\{root.author}";
overflow: elide;
font-italic: true;
}
}
in-out property <bool> is-selected: false;
in property <bool> has-hover;
states [
selected when root.is-selected: {
root.background: Palette.selection-background;
msg-text.color: Palette.selection-foreground;
author-text.color: Palette.selection-foreground;
}
lowlighted when root.has-hover: {
root.background: Palette.alternate-background;
msg-text.color: Palette.alternate-foreground;
author-text.color: Palette.alternate-foreground;
}
]
}
component Changelog inherits Rectangle {
in-out property <int> count-files-changed;
in-out property <[ChangeData]> changes_log: [];
in-out property <int> selected: -2;
public function deselect() {
root.selected = -1;
}
callback selection-changed(/*new selection*/ int);
VerticalBox {
Text {
vertical-stretch: 0;
text: "log";
}
diff-entry := DiffEntry {
files-count: count-files-changed;
is-selected: root.selected == -1;
has-hover: touch0.has-hover;
touch0 := TouchArea {
clicked => {
root.selected = -1;
root.selection-changed(-1);
}
}
}
// TODO convert to a StandardListView?
ListView {
// preferred-width: 400px;
for change[index] in root.changes_log: ce := ChangeEntry {
hash: change.hash;
author: change.author;
timestamp: change.timestamp;
message: change.message;
is-selected: root.selected == index;
has-hover: touch.has-hover;
touch := TouchArea {
clicked => {
root.selected = index;
root.selection-changed(index);
}
}
}
}
}
}
component ChannelsList {
in-out property <[string]> channels;
in-out property <int> active;
VerticalBox {
alignment: start;
spacing: 0;
preferred-width: 150px;
Text {
text: "channels";
for ch in channels: Text {
text: "\{ch}";
}
}
}
}
component ChannelEntry inherits Rectangle {
in property <string> name;
in property <bool> active;
HorizontalBox {
alignment: start;
spacing: 5px;
padding: 0;
active-marker := Rectangle {
width: 10px;
height: 100%;
border-radius: 5px;
visible: root.active;
background: Palette.accent-background;
}
label-backdrop := Rectangle {
label := Text {
text: "\{name}";
}
}
}
in property <bool> is-selected: false;
in property <bool> has-hover: false;
states [
selected when is-selected: {
label-backdrop.background: Palette.selection-background;
label.color: Palette.selection-foreground;
}
lowlighted when has-hover: {
label-backdrop.background: Palette.alternate-background;
label.color: Palette.alternate-foreground;
}
off when true: {
label-backdrop.background: Palette.background;
label.color: Palette.foreground;
}
]
}
component ChannelsList {
in-out property <ChannelsData> data;
in-out property <int> selected: -1;
public function deselect() {
root.selected = -1;
}
callback selection-changed(/*new selection*/ int);
VerticalBox {
Text {
vertical-stretch: 0;
text: "channels";
}
// TODO convert to a StandardListView?
ListView {
for ch[index] in data.names: ChannelEntry {
name: ch;
active: data.active == index;
is-selected: selected == index;
has-hover: touch.has-hover;
touch := TouchArea {
clicked => {
root.selected = index;
root.selection-changed(index);
}
}
}
}
}
}
export component AppWindow inherits Window {
in-out property <[string]> channels <=> chs.channels;
in-out property <int> active-channel <=> chs.active;
preferred-width: 960px;
preferred-height: 720px;
in property <string> exe_path;
in property <string> repo_path;
in-out property <ChannelsData> channels <=> chs.data;
in-out property <[ChangeData]> changes_log <=> log.changes_log;
in-out property <int> count-files-changed <=> log.count-files-changed;
in-out property <string> delta <=> deltas.delta;
callback request-channel-list();
callback request-change-delta(string);
callback request-diff-summary(string);
callback request-diff-delta(string);
function fill-chs() {
chs.deselect();
root.request-channel-list();
}
function fill-log() {
log.deselect();
root.request-changes-log(chs.data.names[chs.selected]);
root.request-diff-summary(chs.data.names[chs.selected]);
}
function fill-diff-view() {
if log.selected >= 0 && log.selected < log.changes_log.length {
} else {
}
}
VerticalBox {
Button {
vertical-stretch: 0;
text: "Refresh";
clicked => {
fill-chs();
fill-log();
fill-diff-view();
}
}
HorizontalBox {
vertical-stretch: 1;
chs := ChannelsList {
channels: [];
active: 0;
preferred-width: 500px;
chs := ChannelsList {
horizontal-stretch: 0;
selection-changed => {
fill-log();
fill-diff-view();
}
}
log := Changelog {
horizontal-stretch: 2;
selection-changed => {
fill-diff-view();
}
}
deltas := DeltasList {
horizontal-stretch: 3;
}
}
}
}