Add basic album list

This commit is contained in:
2026-06-05 17:31:18 +02:00
parent e1a5a733c1
commit 493a689d75
8 changed files with 201 additions and 43 deletions

71
ui/albums.slint Normal file
View File

@@ -0,0 +1,71 @@
import { AlbumCover } from "types.slint";
import { Global } from "global.slint";
import { ScrollView, HorizontalBox, Palette } from "std-widgets.slint";
import { ImagePreview } from "timeline.slint";
component AlbumCover {
in property <AlbumCover> album;
states [
pressed when touch.pressed: {
click-effect.opacity: 0.2;
}
default: {
click-effect.opacity: 0;
}
]
Rectangle {
background: Palette.alternate-background;
border-radius: 24px;
clip: true;
HorizontalLayout {
spacing: 20px;
ImagePreview {
preview: album.thumbnail;
size: 100px;
}
Text {
text: album.name;
horizontal-alignment: left;
vertical-alignment: center;
font-size: 20px;
}
}
click_effect := Rectangle {
background: Palette.accent-foreground;
opacity: 0;
}
touch := TouchArea {}
}
}
export component Albums {
private property <[AlbumCover]> albums: Global.albums;
property <length> min-image-size: Global.min-image-size;
property <length> min-size-with-margin: min-image-size + Global.image-margin;
ScrollView {
mouse-drag-pan-enabled: true;
HorizontalLayout {
alignment: center;
VerticalLayout {
min-width: min-image-size;
alignment: start;
spacing: 10px;
for album[i] in albums : AlbumCover {
album: album;
}
}
}
}
}

View File

@@ -6,6 +6,7 @@ import { Header } from "header.slint";
import { Footer, FooterButton } from "footer.slint";
import { Global } from "global.slint";
import { Albums } from "albums.slint";
export { Global }
enum View {
@@ -32,6 +33,7 @@ export component AppWindow inherits Window {
if !Global.logged-in: LoginView {}
if Global.logged-in && view == View.Timeline: Timeline {}
if Global.logged-in && view == View.Albums: Albums {}
Footer {
FooterButton {
@@ -46,7 +48,10 @@ export component AppWindow inherits Window {
FooterButton {
title: "Album";
icon: @image-url("../assets/album.svg");
clicked => { view = View.Albums}
clicked => {
view = View.Albums;
Global.load-albums();
}
}
FooterButton {
title: "Library";

View File

@@ -7,10 +7,10 @@ export component FooterButton inherits Rectangle {
states [
pressed when touch.pressed: {
background: #0000ff30;
background: #0000ff30; // TODO: palette
}
hovered when touch.has-hover: {
background: #0000ff15;
background: #0000ff15; // TODO: palette
}
default: {
background: #0000;
@@ -30,7 +30,7 @@ export component FooterButton inherits Rectangle {
padding-right: 20px;
Image {
source: icon;
colorize: #accbfa;
colorize: Palette.accent-background;
}
Text {
text: title;

View File

@@ -1,10 +1,11 @@
import { ImageBucket, ImagePreview } from "types.slint";
import { ImageBucket, ImagePreview, AlbumCover } from "types.slint";
export global Global {
in-out property <bool> logged-in: false;
in-out property <length> min-image-size: 88px;
in-out property <length> image-margin: 2px;
in-out property <ImagePreview> viewed-image;
in-out property <[AlbumCover]> albums;
in-out property <[ImageBucket]> image-buckets: [
{ key: "2026-02-01", title: "Feb 1, 2026", count: 12 },
{ key: "2026-02-02", title: "Feb 2, 2026", count: 12 },
@@ -17,4 +18,5 @@ export global Global {
callback set-timeline-width(length);
callback timeline-scrolled(length);
callback view-image(string);
callback load-albums();
}

View File

@@ -1,10 +1,12 @@
import { ScrollView } from "std-widgets.slint";
import { ScrollView, Palette } from "std-widgets.slint";
import { Global } from "global.slint";
import { ImageBucket, Visibility, ImagePreview } from "types.slint";
component ImagePreview inherits Rectangle {
export component ImagePreview inherits Rectangle {
in property <ImagePreview> preview;
in property <length> size: 32px;
callback clicked <=> touch.clicked;
width: size;
height: size;
clip: true;
@@ -15,12 +17,7 @@ component ImagePreview inherits Rectangle {
source: preview.image;
}
touch := TouchArea {
clicked => {
Global.viewed-image = root.preview;
Global.view-image(root.preview.asset-id);
}
}
touch := TouchArea {}
}
component TimelineBlock inherits VerticalLayout {
@@ -62,14 +59,15 @@ component TimelineBlock inherits VerticalLayout {
if !checked : Image {
source: @image-url("../assets/unchecked.svg");
colorize: #aaa;
colorize: Palette.foreground;
opacity: 0.8;
height: title.height;
width: self.height;
}
if checked : Image {
source: @image-url("../assets/checked.svg");
colorize: #accbfa;
colorize: Palette.accent-background;
height: title.height;
width: self.height;
}
@@ -91,6 +89,10 @@ component TimelineBlock inherits VerticalLayout {
size: image-size;
x: Global.image-margin / 2 + Math.mod(i, count-x) * (Global.image-margin + image-size);
y: Math.floor(i / count-x) * (image-size + Global.image-margin);
clicked => {
Global.viewed-image = preview;
Global.view-image(preview.asset-id);
}
}
}
}

View File

@@ -33,3 +33,11 @@ export struct ImageBucket {
visibility: Visibility,
}
export struct AlbumCover {
id: string,
name: string,
description: string,
thumbnail: ImagePreview,
asset_count: int,
}