2024-11-21 11:59:39 +01:00
|
|
|
import { State, ListSource } from "./state.slint";
|
2024-11-22 18:05:29 +01:00
|
|
|
import { VText, VTextInput , VButton, ToggleButton, VActionButton, VPopupIconMenu, Svg, Palette } from "@selenite";
|
2024-11-19 16:57:32 +01:00
|
|
|
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 {
|
2024-11-20 11:48:49 +01:00
|
|
|
model: ["Anilist", "Local"];
|
2024-11-19 16:57:32 +01:00
|
|
|
}
|
|
|
|
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
|
|
|
|
});
|
2024-11-20 11:48:49 +01:00
|
|
|
} else if list-type.current-value == "Local" {
|
|
|
|
State.add-local-list({
|
|
|
|
name: parent.name,
|
|
|
|
});
|
2024-11-19 16:57:32 +01:00
|
|
|
}
|
|
|
|
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;
|
|
|
|
}
|
2024-11-21 11:59:39 +01:00
|
|
|
|
|
|
|
HorizontalLayout {
|
|
|
|
alignment: start;
|
2024-11-25 15:32:02 +01:00
|
|
|
spacing: 8px;
|
2024-11-21 11:59:39 +01:00
|
|
|
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 {
|
2024-11-25 15:32:02 +01:00
|
|
|
icon-svg: Svg.refresh;
|
2024-11-21 11:59:39 +01:00
|
|
|
text: "Sync";
|
|
|
|
clicked => { State.sync-list() }
|
|
|
|
}
|
2024-11-25 15:32:02 +01:00
|
|
|
VButton {
|
|
|
|
text: "Settings";
|
|
|
|
icon-svg: Svg.cog;
|
|
|
|
clicked => { State.open-edit-list-window(State.current-list.index) }
|
|
|
|
}
|
2024-11-21 11:59:39 +01:00
|
|
|
}
|
2024-11-25 15:32:02 +01:00
|
|
|
}
|
2024-11-19 16:57:32 +01:00
|
|
|
|
|
|
|
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;
|
|
|
|
|
2024-11-22 18:05:29 +01:00
|
|
|
private property <length> item-min-width: 256px;
|
2024-11-19 16:57:32 +01:00
|
|
|
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;
|
|
|
|
}
|
2024-11-22 18:05:29 +01:00
|
|
|
popup := VPopupIconMenu {
|
|
|
|
VActionButton {
|
|
|
|
icon-svg: Svg.trash;
|
2024-11-25 15:32:02 +01:00
|
|
|
icon-colorize: Palette.red;
|
2024-11-22 18:05:29 +01:00
|
|
|
icon-size: 1.5rem;
|
|
|
|
border-radius: 0;
|
|
|
|
clicked => {
|
2024-11-22 18:11:58 +01:00
|
|
|
State.remove-anime(index)
|
2024-11-22 18:05:29 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
TouchArea {
|
|
|
|
pointer-event(e) => {
|
|
|
|
if (e.button == PointerEventButton.right && e.kind == PointerEventKind.up) {
|
|
|
|
popup.show(self.mouse-x, self.mouse-y);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-11-19 16:57:32 +01:00
|
|
|
}
|
|
|
|
animeTitle := VText {
|
|
|
|
text: anime.title;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|