Files
Tofu/ui/components/channel-list.slint
T
Inako 5eb47e45ef feat: implement client backend
This includes temporary AI-generated frontend scaffolding, none of this will be used in production. It was just used during development for the backend.
2026-10-09 19:46:02 +01:00

176 lines
5.2 KiB
Plaintext

/// TEMPORARY AI GENERATED FRONTEND \\\
/// NOT TO BE USED IN PRODUCTION \\\
import { ListView } from "std-widgets.slint";
import { Theme } from "../theme.slint";
import { Icons } from "../icons.slint";
import { ChannelItem, ChannelKind } from "../types.slint";
import { Icon } from "icon.slint";
import { Avatar } from "avatar.slint";
import { Badge } from "badge.slint";
component ChannelRow inherits Rectangle {
in property <ChannelItem> c;
in property <bool> selected;
callback clicked();
height: c.kind == ChannelKind.category ? 34px : (c.is-dm ? 44px : 34px);
opacity: c.joined || c.kind == ChannelKind.category ? 1.0 : 0.5;
// --- category heading ("TEXT CHANNELS") ---
if c.kind == ChannelKind.category: Text {
x: 16px;
y: 0px;
width: parent.width - 32px;
height: parent.height - 4px;
text: c.name;
color: Theme.text-muted;
font-size: 12px;
font-weight: 700;
vertical-alignment: bottom;
overflow: elide;
}
// --- text / voice channel ---
if c.kind != ChannelKind.category && !c.is-dm: Rectangle {
x: 8px;
y: 1px;
width: parent.width - 16px;
height: parent.height - 2px;
border-radius: 4px;
background: root.selected ? Theme.selected-bg : (touch.has-hover ? Theme.hover-bg : transparent);
Icon {
source: c.kind == ChannelKind.voice ? Icons.speaker : Icons.hash;
tint: root.selected || c.unread ? Theme.text-header : Theme.text-muted;
icon-size: 18px;
x: 8px;
y: (parent.height - self.height) / 2;
}
Text {
x: 34px;
width: parent.width - 34px - (c.mentions > 0 ? 40px : 8px);
height: parent.height;
text: c.name;
color: root.selected || c.unread || touch.has-hover ? Theme.text-header : Theme.text-muted;
font-weight: c.unread ? 700 : 500;
vertical-alignment: center;
overflow: elide;
}
Badge {
count: c.mentions;
x: parent.width - self.width - 8px;
y: (parent.height - self.height) / 2;
}
}
// --- direct message ---
if c.is-dm && c.kind != ChannelKind.category: Rectangle {
x: 8px;
y: 1px;
width: parent.width - 16px;
height: parent.height - 2px;
border-radius: 4px;
background: root.selected ? Theme.selected-bg : (touch.has-hover ? Theme.hover-bg : transparent);
Avatar {
initial: c.initial;
tint: c.color;
diameter: 32px;
x: 8px;
y: (parent.height - self.height) / 2;
}
Text {
x: 50px;
width: parent.width - 50px - (c.mentions > 0 ? 40px : 8px);
height: parent.height;
text: c.name;
color: root.selected || c.unread || touch.has-hover ? Theme.text-header : Theme.text-muted;
font-weight: c.unread ? 700 : 500;
vertical-alignment: center;
overflow: elide;
}
Badge {
count: c.mentions;
x: parent.width - self.width - 8px;
y: (parent.height - self.height) / 2;
}
}
touch := TouchArea {
enabled: c.kind != ChannelKind.category;
mouse-cursor: pointer;
clicked => {
root.clicked();
}
}
}
export component ChannelList inherits Rectangle {
in property <string> title;
in property <bool> is-home;
in property <[ChannelItem]> channels;
in property <string> selected-id;
callback select(string);
callback open-server-menu();
width: Theme.sidebar-width;
background: Theme.sidebar-bg;
VerticalLayout {
// Header: server name (or "Direct Messages")
Rectangle {
height: Theme.header-height;
background: header-touch.has-hover && !root.is-home ? Theme.hover-bg : transparent;
Text {
x: 16px;
width: parent.width - 52px;
height: parent.height;
text: root.title;
color: Theme.text-header;
font-size: 15px;
font-weight: 700;
vertical-alignment: center;
overflow: elide;
}
if !root.is-home: Icon {
source: Icons.chevron-down;
tint: Theme.text-header;
icon-size: 16px;
x: parent.width - 16px - self.width;
y: (parent.height - self.height) / 2;
}
// bottom hairline
Rectangle {
y: parent.height - 1px;
height: 1px;
background: Theme.rail-bg;
}
header-touch := TouchArea {
enabled: !root.is-home;
clicked => {
root.open-server-menu();
}
}
}
ListView {
for c in root.channels: ChannelRow {
c: c;
selected: c.id == root.selected-id;
clicked => {
root.select(c.id);
}
}
}
}
}