205 lines
6.2 KiB
Plaintext
205 lines
6.2 KiB
Plaintext
import { Theme, SpacingSystem, Typography } from "../theme/theme.slint";
|
|
import { Card } from "../components/card.slint";
|
|
import { Button } from "../components/button.slint";
|
|
import { Badge } from "../components/badge.slint";
|
|
import { Progress } from "../components/progress.slint";
|
|
|
|
export struct ProfileData {
|
|
id: string,
|
|
name: string,
|
|
type: string, // "local" or "remote"
|
|
description: string,
|
|
usage: float, // For remote profiles
|
|
total: float, // For remote profiles
|
|
updated: string,
|
|
}
|
|
|
|
export component ProfilesPage {
|
|
in property <[ProfileData]> profiles: [];
|
|
in property <string> selected-profile-id: "";
|
|
|
|
callback add-profile();
|
|
callback refresh-all();
|
|
callback select-profile(string);
|
|
callback edit-profile(string);
|
|
callback delete-profile(string);
|
|
callback refresh-profile(string);
|
|
|
|
VerticalLayout {
|
|
padding: SpacingSystem.spacing.s4;
|
|
spacing: SpacingSystem.spacing.s4;
|
|
|
|
// Header
|
|
HorizontalLayout {
|
|
spacing: SpacingSystem.spacing.s3;
|
|
alignment: space-between;
|
|
|
|
Text {
|
|
text: "Profiles";
|
|
color: Theme.colors.foreground;
|
|
font-size: Typography.sizes.xl;
|
|
font-weight: Typography.weights.bold;
|
|
vertical-alignment: center;
|
|
}
|
|
|
|
HorizontalLayout {
|
|
spacing: SpacingSystem.spacing.s2;
|
|
|
|
Button {
|
|
text: "+";
|
|
variant: "ghost";
|
|
|
|
clicked => {
|
|
root.add-profile();
|
|
}
|
|
}
|
|
|
|
Button {
|
|
text: "↻";
|
|
variant: "ghost";
|
|
|
|
clicked => {
|
|
root.refresh-all();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Profile Grid
|
|
ScrollView {
|
|
GridLayout {
|
|
spacing: SpacingSystem.spacing.s3;
|
|
|
|
for profile in root.profiles: ProfileItem {
|
|
profile-data: profile;
|
|
selected: profile.id == root.selected-profile-id;
|
|
|
|
clicked => {
|
|
root.select-profile(profile.id);
|
|
}
|
|
|
|
refresh-clicked => {
|
|
root.refresh-profile(profile.id);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
component ProfileItem {
|
|
in property <ProfileData> profile-data;
|
|
in property <bool> selected: false;
|
|
|
|
callback clicked();
|
|
callback refresh-clicked();
|
|
|
|
private property <bool> hovered: false;
|
|
|
|
min-width: 288px; // 18rem
|
|
height: 96px;
|
|
|
|
states [
|
|
selected when root.selected: {
|
|
container.border-color: Theme.colors.primary.transparentize(0.5);
|
|
container.background: Theme.colors.accent.transparentize(0.4);
|
|
}
|
|
]
|
|
|
|
container := Card {
|
|
border-width: 2px;
|
|
|
|
VerticalLa spacing: SpacingSystem.spacing.s2;
|
|
|
|
// Header
|
|
HorizontalLayout {
|
|
spacing: SpacingSystem.spacing.s2;
|
|
alignment: space-between;
|
|
|
|
HorizontalLayout {
|
|
spacing: SpacingSystem.spacing.s2;
|
|
|
|
Text {
|
|
text: root.profile-data.type == "remote" ? "☁" : "📄";
|
|
font-size: Typography.sizes.lg;
|
|
vertical-alignment: center;
|
|
}
|
|
|
|
{
|
|
text: root.profile-data.name;
|
|
color: Theme.colors.foreground;
|
|
font-size: Typography.sizes.base;
|
|
font-weight: Typography.weights.semibold;
|
|
vertical-alignment: center;
|
|
}
|
|
}
|
|
|
|
if root.profile-data.type == "remote": Button {
|
|
width: 24px;
|
|
height: 24px;
|
|
text: "↻";
|
|
variant: "ghost";
|
|
|
|
clicked => {
|
|
root.refresh-clicked();
|
|
}
|
|
}
|
|
}
|
|
|
|
// Description
|
|
Text {
|
|
text: root.profile-data.description;
|
|
color: Theme.colors.muted-foreground;
|
|
font-size: Typography.sizes.xs;
|
|
overflow: elide;
|
|
}
|
|
|
|
// Progress bar for remote profiles
|
|
if root.profile-data.type == "remote": VerticalLayout {
|
|
spacing: SpacingSystem.spacing.s1;
|
|
|
|
Progress {
|
|
value: (root.profile-data.usage / root.profile-data.total) * 100;
|
|
}
|
|
|
|
HorizontalLayout {
|
|
alignment: space-between;
|
|
|
|
Text {
|
|
text: "Updated: " + root.profile-data.updated;
|
|
color: Theme.colors.muted-foreground;
|
|
font-size: 10px;
|
|
}
|
|
|
|
Text {
|
|
text: root.profile-data.usage + " / " + root.profile-data.total + " GB";
|
|
color: Theme.colors.oreground;
|
|
font-size: 10px;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Local profile info
|
|
if root.profile-data.type == "local": HorizontalLayout {
|
|
alignment: space-between;
|
|
|
|
Text {
|
|
text: "Local Profile";
|
|
color: Theme.colors.muted-foreground;
|
|
font-size: 10px;
|
|
}
|
|
}
|
|
}
|
|
|
|
touch := TouchArea {
|
|
clicked => {
|
|
root.clicked();
|
|
}
|
|
|
|
moved => {
|
|
root.hovered = self.has-hover;
|
|
}
|
|
}
|
|
}
|
|
}
|