mirror of
https://github.com/kunkundi/crossdesk.git
synced 2026-10-15 00:09:39 +08:00
224 lines
11 KiB
Plaintext
224 lines
11 KiB
Plaintext
import { GalleryStrings } from "device_strings.slint";
|
|
import { CompactButton } from "common.slint";
|
|
import { ScrollView } from "std-widgets.slint";
|
|
|
|
export struct GalleryNetworkDevice {
|
|
name: string,
|
|
id: string,
|
|
mode: string,
|
|
encryption-known: bool,
|
|
encryption-enabled: bool,
|
|
video-latency: string,
|
|
inbound: string,
|
|
outbound: string,
|
|
loss: string,
|
|
resolution: string,
|
|
fps: string,
|
|
}
|
|
|
|
component NetworkRow inherits Rectangle {
|
|
in property <GalleryNetworkDevice> device;
|
|
in property <bool> heading: false;
|
|
// Keep the same column geometry in the header and every row. Grouping
|
|
// related values leaves room for device names even in the 640px window.
|
|
HorizontalLayout {
|
|
x: 0px; y: 0px; width: parent.width; height: parent.height;
|
|
padding-left: 12px; padding-right: 12px; spacing: 10px;
|
|
identity := Rectangle {
|
|
horizontal-stretch: 1;
|
|
device-name := Text {
|
|
y: root.heading ? 0px : 8px; height: root.heading ? parent.height : 20px;
|
|
width: parent.width; text: root.device.name;
|
|
font-size: root.heading ? 11px : 12px; font-weight: 600;
|
|
color: root.heading ? #6b7785 : #293746;
|
|
vertical-alignment: center; overflow: elide;
|
|
}
|
|
name-hover := TouchArea {
|
|
y: 8px; height: 20px; width: parent.width;
|
|
enabled: !root.heading;
|
|
}
|
|
if !root.heading: HorizontalLayout {
|
|
x: 0px; y: 30px; width: parent.width; height: 17px; spacing: 4px;
|
|
id-text := Text {
|
|
text: root.device.id; font-size: 10px; color: #7a8490;
|
|
vertical-alignment: center; overflow: elide;
|
|
}
|
|
Rectangle {
|
|
width: max(0px, min(mode-text.preferred-width + 12px,
|
|
parent.width - id-text.preferred-width - encryption-badge.width - 12px));
|
|
background: #edf2f7; border-radius: 3px;
|
|
mode-text := Text {
|
|
x: 6px; width: parent.width - 12px; height: parent.height;
|
|
text: root.device.mode; font-size: 10px; color: #586f87;
|
|
horizontal-alignment: center; vertical-alignment: center; overflow: elide;
|
|
}
|
|
}
|
|
encryption-badge := Rectangle {
|
|
width: encryption-text.preferred-width + 12px;
|
|
background: !root.device.encryption-known ? #f0f2f5
|
|
: root.device.encryption-enabled ? #e8f5ec : #fff3df;
|
|
border-radius: 3px;
|
|
encryption-text := Text {
|
|
x: 6px; width: parent.width - 12px; height: parent.height;
|
|
text: !root.device.encryption-known
|
|
? GalleryStrings.tr("待确认", "Unknown", "Неизвестно")
|
|
: root.device.encryption-enabled
|
|
? GalleryStrings.tr("已加密", "Encrypted", "Защищено")
|
|
: GalleryStrings.tr("未加密", "Unencrypted", "Без шифр.");
|
|
color: !root.device.encryption-known ? #7a8490
|
|
: root.device.encryption-enabled ? #18794e : #8a6428;
|
|
font-size: 10px; horizontal-alignment: center;
|
|
vertical-alignment: center; overflow: elide;
|
|
}
|
|
}
|
|
Rectangle { horizontal-stretch: 1; }
|
|
}
|
|
}
|
|
Rectangle {
|
|
width: max(108px, root.width * 0.19);
|
|
Text {
|
|
y: root.heading ? 0px : 8px; height: root.heading ? parent.height : 20px;
|
|
width: parent.width;
|
|
text: root.heading ? GalleryStrings.tr("画面", "Video", "Видео") : root.device.resolution;
|
|
font-size: root.heading ? 11px : 12px; font-weight: root.heading ? 600 : 400;
|
|
color: root.heading ? #6b7785 : #293746;
|
|
vertical-alignment: center; overflow: elide;
|
|
}
|
|
if !root.heading: Text {
|
|
y: 30px; height: 17px; width: parent.width;
|
|
text: root.device.fps; font-size: 11px; color: #7a8490;
|
|
vertical-alignment: center; overflow: elide;
|
|
}
|
|
}
|
|
Rectangle {
|
|
width: max(100px, root.width * 0.18);
|
|
if root.heading: Text {
|
|
x: 0px; width: parent.width;
|
|
text: GalleryStrings.tr("收发速率", "Transfer rate", "Скорость");
|
|
font-size: 11px; font-weight: 600; color: #6b7785;
|
|
vertical-alignment: center; overflow: elide;
|
|
}
|
|
if !root.heading: Text {
|
|
x: 0px; y: 8px; height: 20px; width: 14px;
|
|
text: "↓"; color: #2676b9; font-size: 12px; vertical-alignment: center;
|
|
}
|
|
if !root.heading: Text {
|
|
x: 17px; y: 8px; height: 20px; width: parent.width - 17px;
|
|
text: root.device.inbound; color: #293746; font-size: 12px;
|
|
vertical-alignment: center; overflow: elide;
|
|
}
|
|
if !root.heading: Text {
|
|
x: 0px; y: 30px; height: 17px; width: 14px;
|
|
text: "↑"; color: #7a8490; font-size: 11px; vertical-alignment: center;
|
|
}
|
|
if !root.heading: Text {
|
|
x: 17px; y: 30px; height: 17px; width: parent.width - 17px;
|
|
text: root.device.outbound; color: #7a8490; font-size: 11px;
|
|
vertical-alignment: center; overflow: elide;
|
|
}
|
|
}
|
|
Rectangle {
|
|
width: max(94px, root.width * 0.16);
|
|
Text {
|
|
y: root.heading ? 0px : 8px; height: root.heading ? parent.height : 20px;
|
|
width: parent.width;
|
|
text: root.heading ? GalleryStrings.tr("视频延时", "Video latency", "Задержка видео") : root.device.video-latency;
|
|
font-size: root.heading ? 11px : 12px; font-weight: root.heading ? 600 : 400;
|
|
color: root.heading ? #6b7785 : #293746;
|
|
vertical-alignment: center; overflow: elide;
|
|
}
|
|
if !root.heading: Text {
|
|
y: 30px; height: 17px; width: parent.width;
|
|
text: GalleryStrings.tr("丢包 ", "Loss ", "Потери ") + root.device.loss;
|
|
font-size: 11px; color: #7a8490;
|
|
vertical-alignment: center; overflow: elide;
|
|
}
|
|
}
|
|
}
|
|
if !root.heading && name-hover.has-hover && device-name.preferred-width > identity.width: Rectangle {
|
|
x: 12px; y: 32px; width: min(name-tip.preferred-width + 20px, root.width - 24px);
|
|
height: 26px; background: #293746; border-radius: 4px; z: 10;
|
|
name-tip := Text {
|
|
x: 10px; width: parent.width - 20px; height: parent.height;
|
|
text: root.device.name; font-size: 11px; color: white;
|
|
vertical-alignment: center; overflow: elide;
|
|
}
|
|
}
|
|
}
|
|
|
|
component NetworkEmptyState inherits Rectangle {
|
|
VerticalLayout {
|
|
alignment: center; spacing: 8px;
|
|
Text {
|
|
text: GalleryStrings.tr("暂无已连接设备", "No connected devices", "Нет подключённых устройств");
|
|
font-size: 13px; color: #596878; horizontal-alignment: center;
|
|
}
|
|
Text {
|
|
text: GalleryStrings.tr("建立连接后,网络和画面信息将在此显示", "Network and video details appear here once connected", "После подключения здесь появятся данные сети и видео");
|
|
font-size: 11px; color: #8a95a1; horizontal-alignment: center;
|
|
}
|
|
}
|
|
}
|
|
|
|
export component GalleryNetworkDialog inherits Rectangle {
|
|
in property <[GalleryNetworkDevice]> devices;
|
|
private property <length> row-height: 56px;
|
|
private property <length> list-height: max(2, min(root.devices.length, 6)) * root.row-height;
|
|
callback close();
|
|
background: #00000042;
|
|
TouchArea { clicked => { root.close(); } }
|
|
Rectangle {
|
|
x: (parent.width - self.width) / 2;
|
|
y: (parent.height - self.height) / 2;
|
|
width: min(760px, parent.width - 32px);
|
|
height: min(120px + root.list-height, parent.height - 32px);
|
|
background: white; border-radius: 8px;
|
|
border-width: 1px; border-color: #c6cdd5;
|
|
TouchArea {}
|
|
FocusScope {
|
|
init => { self.focus(); }
|
|
key-pressed(event) => {
|
|
if event.text == Key.Escape { root.close(); }
|
|
accept
|
|
}
|
|
}
|
|
Text {
|
|
x: 20px; y: 17px; width: parent.width - 120px; height: 24px;
|
|
text: GalleryStrings.tr("设备网络状态", "Device network status", "Сеть устройств");
|
|
font-size: 17px; font-weight: 600; color: #293746;
|
|
}
|
|
CompactButton {
|
|
x: parent.width - 80px; y: 17px; width: 60px; height: 26px;
|
|
text: GalleryStrings.tr("关闭", "Close", "Закрыть"); clicked => { root.close(); }
|
|
}
|
|
Text {
|
|
x: 20px; y: 48px; width: parent.width - 40px; height: 18px;
|
|
text: GalleryStrings.tr("已连接设备 ", "Connected devices ", "Подключённые устройства ") + root.devices.length
|
|
+ GalleryStrings.tr(" 台", "", "");
|
|
font-size: 11px; color: #7a8490; overflow: elide;
|
|
}
|
|
NetworkRow {
|
|
x: 12px; y: 78px; width: parent.width - 38px; height: 30px;
|
|
heading: true; background: #f3f5f8; border-radius: 4px;
|
|
device: {
|
|
name: GalleryStrings.tr("设备 / ID", "Device / ID", "Устройство / ID"),
|
|
};
|
|
}
|
|
list := ScrollView {
|
|
x: 12px; y: 108px; width: parent.width - 24px;
|
|
height: parent.height - self.y - 12px;
|
|
viewport-width: self.width - 14px;
|
|
viewport-height: max(self.height, root.devices.length * root.row-height);
|
|
horizontal-scrollbar-policy: always-off;
|
|
for device[index] in root.devices: NetworkRow {
|
|
y: index * root.row-height; width: list.viewport-width; height: root.row-height;
|
|
device: device; background: mod(index, 2) == 0 ? white : #f8fafc;
|
|
Rectangle { y: parent.height - 1px; height: 1px; background: #edf0f4; }
|
|
}
|
|
}
|
|
if root.devices.length == 0: NetworkEmptyState {
|
|
x: list.x; y: list.y; width: list.width; height: list.height;
|
|
}
|
|
}
|
|
}
|