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.
This commit is contained in:
@@ -0,0 +1,149 @@
|
||||
/// TEMPORARY AI GENERATED FRONTEND \\\
|
||||
/// NOT TO BE USED IN PRODUCTION \\\
|
||||
|
||||
import { ScrollView } from "std-widgets.slint";
|
||||
import { Theme } from "../theme.slint";
|
||||
import { Icons } from "../icons.slint";
|
||||
import { ServerItem } from "../types.slint";
|
||||
import { Icon } from "icon.slint";
|
||||
import { Badge } from "badge.slint";
|
||||
|
||||
// One round button on the rail. Morphs from circle to rounded square on hover
|
||||
// or selection, with a white "pill" on the left edge.
|
||||
component RailButton inherits Rectangle {
|
||||
in property <bool> selected;
|
||||
in property <bool> unread;
|
||||
in property <int> mentions;
|
||||
in property <color> idle-color: Theme.chat-bg;
|
||||
in property <color> active-color: Theme.accent;
|
||||
callback clicked();
|
||||
|
||||
height: 56px;
|
||||
|
||||
// Left-edge pill: tall = selected, medium = hovered, dot = unread.
|
||||
Rectangle {
|
||||
x: 0px;
|
||||
width: 4px;
|
||||
height: root.selected ? 40px : (touch.has-hover ? 20px : (root.unread ? 8px : 0px));
|
||||
y: (parent.height - self.height) / 2;
|
||||
border-top-right-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
background: Theme.text-header;
|
||||
animate height { duration: 120ms; }
|
||||
}
|
||||
|
||||
body := Rectangle {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
x: (parent.width - self.width) / 2;
|
||||
y: (parent.height - self.height) / 2;
|
||||
clip: true;
|
||||
border-radius: root.selected || touch.has-hover ? 16px : 24px;
|
||||
background: root.selected || touch.has-hover ? root.active-color : root.idle-color;
|
||||
animate border-radius { duration: 120ms; }
|
||||
@children
|
||||
}
|
||||
|
||||
Badge {
|
||||
count: root.mentions;
|
||||
x: body.x + body.width - self.width + 4px;
|
||||
y: body.y + body.height - self.height + 4px;
|
||||
}
|
||||
|
||||
touch := TouchArea {
|
||||
mouse-cursor: pointer;
|
||||
clicked => {
|
||||
root.clicked();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export component ServerRail inherits Rectangle {
|
||||
in property <[ServerItem]> servers;
|
||||
in property <string> selected-id; // "" = Home (direct messages)
|
||||
in property <bool> home-unread;
|
||||
in property <int> home-mentions;
|
||||
callback select(string);
|
||||
callback add-server();
|
||||
|
||||
width: Theme.rail-width;
|
||||
background: Theme.rail-bg;
|
||||
|
||||
ScrollView {
|
||||
vertical-scrollbar-policy: always-off;
|
||||
horizontal-scrollbar-policy: always-off;
|
||||
|
||||
VerticalLayout {
|
||||
padding-top: 8px;
|
||||
padding-bottom: 8px;
|
||||
alignment: start;
|
||||
|
||||
RailButton {
|
||||
selected: root.selected-id == "";
|
||||
unread: root.home-unread;
|
||||
mentions: root.home-mentions;
|
||||
clicked => {
|
||||
root.select("");
|
||||
}
|
||||
Icon {
|
||||
source: Icons.chat;
|
||||
tint: white;
|
||||
icon-size: 26px;
|
||||
// `parent` here is the rail layout (children are projected into RailButton),
|
||||
// so centre against the button's fixed 48px body instead.
|
||||
x: (48px - self.width) / 2;
|
||||
y: (48px - self.height) / 2;
|
||||
}
|
||||
}
|
||||
|
||||
// separator
|
||||
Rectangle {
|
||||
height: 10px;
|
||||
Rectangle {
|
||||
width: 32px;
|
||||
height: 2px;
|
||||
x: (parent.width - self.width) / 2;
|
||||
y: 4px;
|
||||
border-radius: 1px;
|
||||
background: Theme.divider;
|
||||
}
|
||||
}
|
||||
|
||||
for s in root.servers: RailButton {
|
||||
selected: root.selected-id == s.id;
|
||||
unread: s.unread;
|
||||
mentions: s.mentions;
|
||||
idle-color: s.color;
|
||||
active-color: s.color;
|
||||
clicked => {
|
||||
root.select(s.id);
|
||||
}
|
||||
Text {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
text: s.initial;
|
||||
color: white;
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
horizontal-alignment: center;
|
||||
vertical-alignment: center;
|
||||
}
|
||||
}
|
||||
|
||||
RailButton {
|
||||
idle-color: Theme.chat-bg;
|
||||
active-color: Theme.success;
|
||||
clicked => {
|
||||
root.add-server();
|
||||
}
|
||||
Icon {
|
||||
source: Icons.plus;
|
||||
tint: Theme.success;
|
||||
icon-size: 24px;
|
||||
x: (48px - self.width) / 2;
|
||||
y: (48px - self.height) / 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user