lali/src/AppWindow.slint

208 lines
5.3 KiB
Text

import { State, ListSource } from "./state.slint";
import { VText, VTextInput , VButton, ToggleButton, VActionButton, VPopupIconMenu, Svg, Palette } from "@selenite";
import { ComboBox } from "std-widgets.slint";
export component AppWindow inherits Window {
title: "Lali";
background: Palette.background;
default-font-size: 16px;
padding: 0px;
private property <bool> show-add-list-form: false;
HorizontalLayout {
width: parent.width;
height: parent.height;
sidebar := Rectangle {
horizontal-stretch: 0;
background: Palette.pane;
VerticalLayout {
alignment: start;
padding: 16px;
spacing: 8px;
HorizontalLayout {
alignment: space-between;
spacing: 64px;
VText {
text: "Lists";
font-size: 1.5rem;
}
VActionButton {
icon-svg: Svg.plus;
icon-colorize: Palette.green;
background: transparent;
clicked => { show-add-list-form = true }
}
}
if show-add-list-form : Rectangle {
horizontal-stretch: 0;
border-color: show-add-list-form ? Palette.card-background : transparent;
border-width: show-add-list-form ? 4px : 0px;
border-radius: show-add-list-form ? 8px : 0px;
VerticalLayout {
alignment: start;
padding: 16px;
spacing: 16px;
in-out property <string> name;
in-out property <string> anilist-user-name;
in-out property <string> anilist-list-name;
list-type := ComboBox {
model: ["Anilist", "Local"];
}
VTextInput {
label: "List name";
edited => { parent.name = self.text }
}
if list-type.current-value == "Anilist" : VTextInput {
label: "Anilist Username";
edited => { parent.anilist-user-name = self.text }
}
if list-type.current-value == "Anilist" : VTextInput {
label: "Anilist list name";
edited => { parent.anilist-list-name = self.text }
}
VButton {
text: "Add";
clicked => {
if list-type.current-value == "Anilist" {
State.add-anilist-list({
name: parent.name,
anilist-user-name: parent.anilist-user-name,
anilist-list-name: parent.anilist-list-name
});
} else if list-type.current-value == "Local" {
State.add-local-list({
name: parent.name,
});
}
show-add-list-form = false;
}
}
}
}
for list[index] in State.lists : ToggleButton {
text: list.name;
text-alignment: left;
active: list.selected;
clicked => {
State.select-list(index)
}
}
}
}
animes-view := VerticalLayout {
horizontal-stretch: 1;
spacing: 16px;
padding: 16px;
VerticalLayout {
spacing: 8px;
VText {
text: State.current-list.name;
font-size: 1.5rem;
}
VText {
text: "\{State.current-list.animes.length} animes";
font-size: 1rem;
}
HorizontalLayout {
alignment: start;
spacing: 8px;
if State.current-list.source == ListSource.Local : VButton {
icon-svg: Svg.plus;
text: "Add";
clicked => { State.open-add-anime-window() }
}
if State.current-list.source == ListSource.Anilist : VButton {
icon-svg: Svg.refresh;
text: "Sync";
clicked => { State.sync-list() }
}
VButton {
text: "Settings";
icon-svg: Svg.cog;
clicked => { State.open-edit-list-window(State.current-list.index) }
}
}
}
animes-grid-background := Rectangle {
//background: #111111;
animes-grid := Flickable {
private property <int> number-of-items: State.current-list.animes.length;
private property <length> grid-spacing: 16px;
private property <length> item-min-width: 256px;
private property <int> item-per-row: floor(self.viewport-width / (item-min-width + grid-spacing));
private property <length> item-width: (parent.width - ((item-per-row - 1) * grid-spacing)) / item-per-row;
private property <length> item-height: 512px;
viewport-height: ceil(number-of-items / item-per-row) * (item-height + grid-spacing);
viewport-width: parent.width;
for anime[index] in State.current-list.animes : Rectangle {
x: mod(index, item-per-row) * (item-width + grid-spacing);
y: floor(index / item-per-row) * (item-height + grid-spacing);
width: item-width;
height: item-height;
//background: #444444;
VerticalLayout {
height: parent.height;
width: parent.width;
spacing: 8px;
animeImage := Rectangle {
vertical-stretch: 1;
clip: true;
border-radius: 8px;
Image {
height: parent.height;
width: parent.width;
source: anime.image;
image-fit: ImageFit.cover;
}
popup := VPopupIconMenu {
VActionButton {
icon-svg: Svg.trash;
icon-colorize: Palette.red;
icon-size: 1.5rem;
border-radius: 0;
clicked => {
State.remove-anime(index)
}
}
}
TouchArea {
pointer-event(e) => {
if (e.button == PointerEventButton.right && e.kind == PointerEventKind.up) {
popup.show(self.mouse-x, self.mouse-y);
}
}
}
}
animeTitle := VText {
text: anime.title;
}
}
}
}
}
}
}
}