mirror of
https://github.com/kunkundi/crossdesk.git
synced 2026-10-26 07:14:33 +08:00
[feat] add DeskHub stream controls and network status
This commit is contained in:
@@ -29,6 +29,8 @@ export struct GalleryActionDevice {
|
||||
}
|
||||
export component GalleryView inherits Rectangle {
|
||||
in property <bool> controlling: false;
|
||||
in property <bool> simplified: false;
|
||||
private property <length> grid-gap: root.simplified ? 6px : 12px;
|
||||
// Pointer mapping must use the exact image viewport, including its inset.
|
||||
out property <float> video-width: video.width / 1px;
|
||||
out property <float> video-height: video.height / 1px;
|
||||
@@ -63,6 +65,8 @@ export component GalleryView inherits Rectangle {
|
||||
in property <int> count: 0;
|
||||
in property <int> connected-count: 0;
|
||||
in property <int> selected-count: 0;
|
||||
in property <bool> selected-audio-available: false;
|
||||
in property <bool> selected-audio-muted: false;
|
||||
in property <int> hidden-selected: 0;
|
||||
in property <string> notice;
|
||||
in property <GalleryTile> focused;
|
||||
@@ -91,7 +95,7 @@ export component GalleryView inherits Rectangle {
|
||||
}
|
||||
toolbar := HorizontalLayout {
|
||||
x: 29px; y: 12px; width: parent.width - 58px; height: 24px;
|
||||
visible: root.focused.id == "";
|
||||
visible: root.focused.id == "" && !root.simplified;
|
||||
spacing: 8px;
|
||||
GroupFilter { width: 155px; height: 24px; system-count: 1; model: root.groups; current-index <=> root.group-index;
|
||||
selected(index) => { root.action("group", index); }
|
||||
@@ -102,30 +106,35 @@ export component GalleryView inherits Rectangle {
|
||||
CompactButton { width: 90px; primary: true; text: GalleryStrings.tr("添加设备", "Add device", "Добавить"); clicked => { root.action("add-open", ""); root.adding = true; } }
|
||||
}
|
||||
grid := Rectangle {
|
||||
x: toolbar.x; y: toolbar.y + toolbar.height + 12px; width: toolbar.width;
|
||||
height: footer.y - 12px - self.y;
|
||||
x: root.simplified ? 12px : toolbar.x;
|
||||
y: root.simplified ? 12px : toolbar.y + toolbar.height + 12px;
|
||||
width: parent.width - self.x * 2;
|
||||
height: (root.simplified && root.pages <= 1 ? parent.height - 12px : footer.y - 12px) - self.y;
|
||||
visible: root.focused.id == "";
|
||||
for tile[index] in root.tiles: Rectangle {
|
||||
x: mod(index, root.columns) * (grid.width + 12px) / root.columns;
|
||||
y: floor(index / root.columns) * (grid.height + 12px) / root.rows;
|
||||
width: (grid.width - (root.columns - 1) * 12px) / root.columns;
|
||||
height: (grid.height - (root.rows - 1) * 12px) / root.rows;
|
||||
border-radius: 6px; background: tile.selected ? #eaf3ff : #eff0f2;
|
||||
border-width: tile.selected ? 2px : 1px;
|
||||
x: mod(index, root.columns) * (grid.width + root.grid-gap) / root.columns;
|
||||
y: floor(index / root.columns) * (grid.height + root.grid-gap) / root.rows;
|
||||
width: (grid.width - (root.columns - 1) * root.grid-gap) / root.columns;
|
||||
height: (grid.height - (root.rows - 1) * root.grid-gap) / root.rows;
|
||||
border-radius: root.simplified ? 0px : 6px;
|
||||
background: root.simplified ? #24272d : tile.selected ? #eaf3ff : #eff0f2;
|
||||
border-width: root.simplified ? 0px : tile.selected ? 2px : 1px;
|
||||
border-color: tile.selected ? #76aeea : root.batch && tile-touch.has-hover ? #94bdeb : #c9cdd2;
|
||||
Rectangle {
|
||||
x: 6px; y: 6px; width: parent.width - 12px; height: parent.height - 36px;
|
||||
x: root.simplified ? 0px : 6px; y: self.x;
|
||||
width: parent.width - self.x * 2;
|
||||
height: root.simplified ? parent.height : parent.height - 36px;
|
||||
background: #24272d;
|
||||
if tile.has-frame: Image { x: 0px; y: 0px; width: parent.width; height: parent.height; source: tile.frame; image-fit: contain; opacity: tile.stale ? 0.45 : 1; }
|
||||
if !tile.has-frame || !tile.connected || tile.stale: Text {
|
||||
if !root.simplified && (!tile.has-frame || !tile.connected || tile.stale): Text {
|
||||
text: tile.status; color: #ffffff; font-size: 12px;
|
||||
horizontal-alignment: center; vertical-alignment: center;
|
||||
wrap: word-wrap;
|
||||
}
|
||||
}
|
||||
Text { x: 9px; y: parent.height - 28px; width: (tile-touch.has-hover && !root.batch ? parent.width - DeviceCardStyle.toolbar-width - 6px : presence-badge.x) - 17px; height: 28px; text: tile.name; color: #24272d; font-size: 12px; overflow: elide; vertical-alignment: center; }
|
||||
Text { visible: !root.simplified; x: 9px; y: parent.height - 28px; width: (tile-touch.has-hover && !root.batch ? parent.width - DeviceCardStyle.toolbar-width - 6px : presence-badge.x) - 17px; height: 28px; text: tile.name; color: #24272d; font-size: 12px; overflow: elide; vertical-alignment: center; }
|
||||
presence-badge := Rectangle {
|
||||
visible: root.batch || !tile-touch.has-hover;
|
||||
visible: !root.simplified && (root.batch || !tile-touch.has-hover);
|
||||
x: parent.width - (root.batch ? 35px : 9px) - self.width; y: parent.height - 23px;
|
||||
width: presence-label.preferred-width + 12px; height: 18px;
|
||||
border-radius: 9px; background: tile.online ? #eaf6ee : #e2e5e9;
|
||||
@@ -135,7 +144,7 @@ export component GalleryView inherits Rectangle {
|
||||
color: tile.online ? #17854c : #62666d; font-size: 10px; vertical-alignment: center;
|
||||
}
|
||||
}
|
||||
if root.batch: Rectangle {
|
||||
if root.batch && !root.simplified: Rectangle {
|
||||
x: parent.width - 27px; y: parent.height - 23px;
|
||||
width: 18px; height: 18px; border-radius: 5px; border-width: 1px;
|
||||
background: tile.selected ? (tile-touch.pressed ? #5c9fdf : tile-touch.has-hover ? #659fe0 : #6dabea) : tile-touch.has-hover ? #f3f8fe : white;
|
||||
@@ -148,8 +157,8 @@ export component GalleryView inherits Rectangle {
|
||||
}
|
||||
}
|
||||
tile-touch := TouchArea {
|
||||
clicked => { root.action(root.batch ? "select" : "focus", tile.id); }
|
||||
if tile-touch.has-hover && !root.batch: DeviceCardActions {
|
||||
clicked => { root.action(root.batch && !root.simplified ? "select" : "focus", tile.id); }
|
||||
if tile-touch.has-hover && !root.batch && !root.simplified: DeviceCardActions {
|
||||
x: parent.width - self.width - 6px; y: parent.height - 26px;
|
||||
remove-label: GalleryStrings.tr("从桌面墙移除", "Remove from DeskHub", "Убрать из DeskHub");
|
||||
connected: tile.connected;
|
||||
@@ -162,14 +171,16 @@ export component GalleryView inherits Rectangle {
|
||||
}
|
||||
}
|
||||
if root.count == 0: Text {
|
||||
text: GalleryStrings.tr("添加设备,建立你的桌面墙", "Add devices to build your DeskHub", "Добавьте устройства в DeskHub");
|
||||
text: root.simplified
|
||||
? GalleryStrings.tr("暂无设备,退出精简模式后可添加", "No devices. Exit compact mode to add devices", "Нет устройств. Выйдите из компактного режима, чтобы добавить их")
|
||||
: GalleryStrings.tr("添加设备,建立你的桌面墙", "Add devices to build your DeskHub", "Добавьте устройства в DeskHub");
|
||||
color: #808080; horizontal-alignment: center; vertical-alignment: center;
|
||||
}
|
||||
}
|
||||
focus-view := Rectangle {
|
||||
visible: root.focused.id != "";
|
||||
x: 29px; y: 7px; width: parent.width - 58px;
|
||||
height: parent.height - 51px;
|
||||
height: parent.height - (root.simplified && root.pages <= 1 ? 19px : 51px);
|
||||
HorizontalLayout {
|
||||
x: 0px; y: 0px; width: parent.width; height: 28px; spacing: 8px;
|
||||
CompactButton { width: 52px; text: GalleryStrings.tr("返回", "Back", "Назад"); clicked => { root.action("focus", ""); } }
|
||||
@@ -256,20 +267,21 @@ export component GalleryView inherits Rectangle {
|
||||
border-width: tile.id == root.focused.id ? 2px : 1px;
|
||||
border-color: tile.id == root.focused.id ? #76aeea : #d5dbe3;
|
||||
Rectangle {
|
||||
x: 5px; y: 5px; width: 126px; height: 52px; background: #24272d;
|
||||
x: 5px; y: 5px; width: 126px; height: root.simplified ? 82px : 52px; background: #24272d;
|
||||
if tile.has-frame: Image { width: parent.width; height: parent.height; source: tile.frame; image-fit: contain; opacity: tile.stale || !tile.connected ? 0.4 : 1; }
|
||||
if !tile.has-frame || tile.stale || !tile.connected: Text {
|
||||
if !root.simplified && (!tile.has-frame || tile.stale || !tile.connected): Text {
|
||||
text: tile.status; color: #e2e6ed; font-size: 10px; overflow: elide;
|
||||
horizontal-alignment: center; vertical-alignment: center;
|
||||
}
|
||||
}
|
||||
Text { x: 7px; y: 61px; width: 122px; height: 16px; text: tile.name; color: #303943; font-size: 11px; overflow: elide; }
|
||||
Text { visible: !root.simplified; x: 7px; y: 61px; width: 122px; height: 16px; text: tile.name; color: #303943; font-size: 11px; overflow: elide; }
|
||||
Text {
|
||||
visible: !root.simplified;
|
||||
x: 7px; y: 78px; width: 86px; height: 12px; font-size: 9px;
|
||||
text: tile.online ? GalleryStrings.tr("在线", "Online", "В сети") : tile.presence-known ? GalleryStrings.tr("离线", "Offline", "Не в сети") : GalleryStrings.tr("未知", "Unknown", "Неизвестно");
|
||||
color: tile.online ? #17854c : #7a828d; overflow: elide;
|
||||
}
|
||||
if tile.id == root.focused.id: Text {
|
||||
if !root.simplified && tile.id == root.focused.id: Text {
|
||||
x: 99px; y: 78px; width: 30px; height: 12px;
|
||||
text: GalleryStrings.tr("当前", "Current", "Выбрано"); color: #4d83bd; font-size: 9px; horizontal-alignment: right; overflow: elide;
|
||||
}
|
||||
@@ -280,8 +292,9 @@ export component GalleryView inherits Rectangle {
|
||||
// Reuse the footer for selection actions so entering batch mode never
|
||||
// changes card geometry or moves a device beneath the pointer.
|
||||
footer := HorizontalLayout {
|
||||
x: toolbar.x; y: parent.height - 36px; width: toolbar.width; height: 24px; spacing: 12px;
|
||||
if root.batch: CompactButton {
|
||||
x: toolbar.x; y: parent.height - 36px; width: toolbar.width; height: 24px; spacing: root.batch ? 8px : 12px;
|
||||
visible: !root.simplified || root.pages > 1;
|
||||
if root.batch && !root.simplified: CompactButton {
|
||||
width: 90px; enabled: root.count > 0;
|
||||
text: root.count > 0 && root.selected-count == root.count
|
||||
? GalleryStrings.tr("取消全选", "Deselect all", "Снять выбор")
|
||||
@@ -291,20 +304,28 @@ export component GalleryView inherits Rectangle {
|
||||
Rectangle {
|
||||
horizontal-stretch: 1; min-width: 0px;
|
||||
Text {
|
||||
visible: !root.simplified;
|
||||
y: 0px; width: parent.width; height: root.batch && root.hidden-selected > 0 ? 13px : parent.height;
|
||||
text: root.batch ? GalleryStrings.tr("已选 ", "Selected ", "Выбрано ") + root.selected-count : root.connected-count + " / " + root.count + GalleryStrings.tr(" 台已连接", " connected", " подключено");
|
||||
color: #62666d; vertical-alignment: center; font-size: 12px; overflow: elide;
|
||||
}
|
||||
if root.batch && root.hidden-selected > 0: Text {
|
||||
if root.batch && !root.simplified && root.hidden-selected > 0: Text {
|
||||
y: 14px; width: parent.width; height: 10px;
|
||||
text: GalleryStrings.tr("跨页 ", "Other pages ", "Другие страницы ") + root.hidden-selected;
|
||||
text: GalleryStrings.tr("跨页 ", "Other pages ", "Вне страницы ") + root.hidden-selected;
|
||||
color: #80858d; font-size: 10px; overflow: elide;
|
||||
}
|
||||
}
|
||||
if root.batch: HorizontalLayout {
|
||||
width: 214px; spacing: 8px;
|
||||
if root.batch && !root.simplified: HorizontalLayout {
|
||||
width: 280px; spacing: 8px;
|
||||
CompactButton { width: 58px; enabled: root.selected-count > 0; text: GalleryStrings.tr("连接", "Connect", "Связь"); clicked => { root.action("connect", ""); } }
|
||||
CompactButton { width: 62px; enabled: root.selected-count > 0; text: GalleryStrings.tr("断开", "Close", "Отключить"); clicked => { root.confirm-action("disconnect", self.text); } }
|
||||
CompactButton {
|
||||
width: 58px; enabled: root.selected-audio-available;
|
||||
text: root.selected-audio-muted
|
||||
? GalleryStrings.tr("取消静音", "Unmute", "Со звуком")
|
||||
: GalleryStrings.tr("静音", "Mute", "Без звука");
|
||||
clicked => { root.action(root.selected-audio-muted ? "unmute" : "mute", ""); }
|
||||
}
|
||||
CompactButton { width: 78px; enabled: root.selected-count > 0; text: GalleryStrings.tr("分发文件", "Send file", "Файл"); clicked => { root.confirm-action("file", self.text); } }
|
||||
}
|
||||
HorizontalLayout {
|
||||
|
||||
Reference in New Issue
Block a user