mirror of
https://github.com/kunkundi/crossdesk.git
synced 2026-10-19 18:33:00 +08:00
[feat] add standalone DeskHub window and resizable device table
This commit is contained in:
@@ -265,19 +265,20 @@ component PasswordInput inherits Rectangle {
|
||||
}
|
||||
|
||||
export component MainWindow inherits Window {
|
||||
title: "CrossDesk";
|
||||
title: root.gallery-mode ? "CrossDesk · " + GalleryStrings.tr("桌面墙", "DeskHub", "DeskHub") : "CrossDesk";
|
||||
icon: @image-url("../../../resources/linux/crossdesk_256x256.png");
|
||||
preferred-width: 640px;
|
||||
preferred-height: 486px + root.titlebar-height;
|
||||
preferred-height: root.minimum-window-height;
|
||||
min-width: 640px;
|
||||
max-width: root.gallery-mode ? 16384px : 640px;
|
||||
min-height: 486px + root.titlebar-height;
|
||||
max-height: root.gallery-mode ? 16384px : 486px + root.titlebar-height;
|
||||
min-height: root.minimum-window-height;
|
||||
max-height: root.gallery-mode ? 16384px : root.minimum-window-height;
|
||||
no-frame: root.custom-titlebar;
|
||||
background: root.wayland-titlebar ? transparent : white;
|
||||
default-font-size: ImGuiFontStyle.base;
|
||||
|
||||
in-out property <bool> gallery-mode: false;
|
||||
// Fixed role for this window instance; opening DeskHub creates another window.
|
||||
in property <bool> gallery-mode: false;
|
||||
in-out property <bool> gallery-simplified: false;
|
||||
changed gallery-simplified => {
|
||||
root.reset-gallery-transient();
|
||||
@@ -316,8 +317,10 @@ export component MainWindow inherits Window {
|
||||
in property <[GalleryTile]> gallery-tiles;
|
||||
in property <[string]> gallery-groups;
|
||||
in-out property <int> gallery-group-index: 0;
|
||||
in property <int> gallery-columns: 3;
|
||||
in property <int> gallery-rows: 2;
|
||||
out property <int> gallery-columns: gallery.columns;
|
||||
out property <int> gallery-rows: gallery.rows;
|
||||
in-out property <float> gallery-tile-width: 216;
|
||||
out property <bool> gallery-resizing: gallery.resizing;
|
||||
in property <int> gallery-page: 0;
|
||||
in property <int> gallery-pages: 1;
|
||||
in property <int> gallery-count: 0;
|
||||
@@ -335,11 +338,10 @@ export component MainWindow inherits Window {
|
||||
in property <[GalleryRecentDevice]> gallery-recent-devices;
|
||||
in property <int> gallery-recent-selected: 0;
|
||||
in property <string> gallery-import-group;
|
||||
out property <float> gallery-width: root.width / 1px;
|
||||
out property <float> gallery-height: gallery.height / 1px;
|
||||
callback change-mode(bool);
|
||||
callback open-gallery();
|
||||
callback toggle-gallery-fullscreen();
|
||||
callback gallery-action(string, string);
|
||||
callback gallery-swap(string, string) -> bool;
|
||||
callback gallery-add-device(string, string, string, bool) -> bool;
|
||||
callback gallery-import-recent(string) -> bool;
|
||||
in-out property <bool> device-group-open: false;
|
||||
@@ -367,7 +369,9 @@ export component MainWindow inherits Window {
|
||||
in property <bool> window-active: true;
|
||||
private property <length> titlebar-height:
|
||||
root.custom-titlebar && !root.gallery-fullscreen ? (root.wayland-titlebar ? 32px : 31px) : 0px;
|
||||
private property <length> content-header-height: 38px;
|
||||
private property <length> content-header-height: root.gallery-mode ? 38px : 0px;
|
||||
out property <length> minimum-window-height:
|
||||
448px + root.content-header-height + root.titlebar-height;
|
||||
private property <length> wayland-corner-radius: 12px;
|
||||
in property <string> local-id: "";
|
||||
in property <string> local-password: "";
|
||||
@@ -585,7 +589,7 @@ export component MainWindow inherits Window {
|
||||
x: 80px;
|
||||
width: parent.width - 160px;
|
||||
height: parent.height;
|
||||
text: "CrossDesk";
|
||||
text: root.title;
|
||||
color: root.window-active ? #3d3d3d : #747474;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
@@ -686,7 +690,7 @@ export component MainWindow inherits Window {
|
||||
x: 30px;
|
||||
width: parent.width - 122px;
|
||||
height: parent.height;
|
||||
text: "CrossDesk";
|
||||
text: root.title;
|
||||
color: #202124;
|
||||
font-size: 12px;
|
||||
vertical-alignment: center;
|
||||
@@ -804,15 +808,19 @@ export component MainWindow inherits Window {
|
||||
z: 7;
|
||||
}
|
||||
|
||||
// App actions live in the content header; window controls and dragging
|
||||
// remain in the native or Windows-specific title bar above it.
|
||||
// The connection page shares its section heading row with the menu.
|
||||
// Only DeskHub needs a separate toolbar above its content.
|
||||
menu-button := IconButton {
|
||||
x: parent.width - mode-switch.x - self.width;
|
||||
y: mode-switch.y;
|
||||
width: mode-switch.height;
|
||||
height: mode-switch.height;
|
||||
visible: !root.gallery-mode;
|
||||
x: parent.width - 29px - self.width;
|
||||
y: 10.5px;
|
||||
width: 28px;
|
||||
height: self.width;
|
||||
icon: FontAwesomeIcons.bars;
|
||||
icon-size: 14px;
|
||||
border-width: 1px;
|
||||
border-color: #c9cdd2;
|
||||
border-radius: 4px;
|
||||
hover-background: #e1e5eb;
|
||||
pressed-background: #cbd1d9;
|
||||
tooltip: root.announcement-unread > 0
|
||||
@@ -822,7 +830,7 @@ export component MainWindow inherits Window {
|
||||
clicked => { root.gallery-action("release", ""); root.menu-open = !root.menu-open; }
|
||||
}
|
||||
// Unread messages take precedence so the menu has only one indicator.
|
||||
if root.update-available && root.announcement-unread <= 0: Rectangle {
|
||||
if !root.gallery-mode && root.update-available && root.announcement-unread <= 0: Rectangle {
|
||||
x: menu-button.x + menu-button.width - self.width + 4px;
|
||||
y: menu-button.y - 1px;
|
||||
width: 16px;
|
||||
@@ -863,7 +871,7 @@ export component MainWindow inherits Window {
|
||||
clicked => { root.gallery-action("release", ""); root.menu-open = !root.menu-open; }
|
||||
}
|
||||
}
|
||||
if root.announcement-unread > 0: Rectangle {
|
||||
if !root.gallery-mode && root.announcement-unread > 0: Rectangle {
|
||||
x: menu-button.x + menu-button.width - self.width + 4px;
|
||||
y: menu-button.y - 1px;
|
||||
width: max(16px, unread-badge-label.preferred-width + 8px);
|
||||
@@ -891,41 +899,23 @@ export component MainWindow inherits Window {
|
||||
}
|
||||
}
|
||||
|
||||
mode-switch := Rectangle {
|
||||
if root.gallery-mode: Text {
|
||||
x: 29px; y: root.content-header-height - self.height; width: 164px; height: 24px;
|
||||
background: #e2e4e7;
|
||||
border-width: 1px; border-color: #c8cbd0; border-radius: 3px;
|
||||
Rectangle {
|
||||
x: root.gallery-mode ? 82px : 2px;
|
||||
y: 2px; width: 80px; height: parent.height - 4px;
|
||||
background: #a8d0fa;
|
||||
border-width: 1px; border-color: #9bc3ed; border-radius: 3px;
|
||||
animate x { duration: 160ms; easing: ease-out; }
|
||||
}
|
||||
for label[index] in [GalleryStrings.tr("连接", "Connect", "Связь"), GalleryStrings.tr("桌面墙", "DeskHub", "DeskHub")]: Rectangle {
|
||||
x: 2px + index * 80px; y: 2px; width: 80px; height: parent.height - 4px;
|
||||
Text {
|
||||
text: label;
|
||||
color: #24272d;
|
||||
font-weight: (index == 1) == root.gallery-mode ? 600 : 400;
|
||||
horizontal-alignment: center; vertical-alignment: center; font-size: 12px;
|
||||
}
|
||||
TouchArea {
|
||||
clicked => { root.change-mode(index == 1); }
|
||||
}
|
||||
}
|
||||
text: GalleryStrings.tr("桌面墙", "DeskHub", "DeskHub");
|
||||
color: #24272d; font-weight: 600; font-size: 12px;
|
||||
vertical-alignment: center;
|
||||
}
|
||||
if root.gallery-mode: CompactButton {
|
||||
x: menu-button.x - 24px - 16px - self.width;
|
||||
y: mode-switch.y; width: 94px; height: mode-switch.height;
|
||||
x: parent.width - 29px - 24px - 8px - self.width;
|
||||
y: root.content-header-height - self.height; width: 94px; height: 24px;
|
||||
primary: root.gallery-simplified;
|
||||
text: root.gallery-simplified ? GalleryStrings.tr("退出精简", "Exit compact", "Обычный вид")
|
||||
: GalleryStrings.tr("精简模式", "Compact", "Компактно");
|
||||
clicked => { root.gallery-simplified = !root.gallery-simplified; }
|
||||
}
|
||||
if root.gallery-mode: IconButton {
|
||||
x: menu-button.x - self.width - 8px;
|
||||
y: mode-switch.y; width: 24px; height: mode-switch.height;
|
||||
x: parent.width - 29px - self.width;
|
||||
y: root.content-header-height - self.height; width: 24px; height: 24px;
|
||||
icon: root.gallery-fullscreen ? FontAwesomeIcons.compress : FontAwesomeIcons.expand;
|
||||
tooltip: root.gallery-fullscreen ? GalleryStrings.tr("退出全屏", "Exit fullscreen", "Выйти из полноэкранного режима") : GalleryStrings.tr("全屏", "Fullscreen", "На весь экран");
|
||||
clicked => { root.toggle-gallery-fullscreen(); }
|
||||
@@ -1058,7 +1048,7 @@ export component MainWindow inherits Window {
|
||||
|
||||
Rectangle { x: parent.width / 2; y: 18px; width: 1px; height: 206px; background: ImGuiLineStyle.border; }
|
||||
|
||||
SectionTitle { x: 356px; y: 9px; width: 256px; height: 31px; text: UiStrings.remote-desktop; }
|
||||
SectionTitle { x: 356px; y: 9px; width: menu-button.x - self.x - 8px; height: 31px; text: UiStrings.remote-desktop; }
|
||||
Rectangle {
|
||||
x: 356px;
|
||||
y: 42px;
|
||||
@@ -1125,8 +1115,23 @@ export component MainWindow inherits Window {
|
||||
|
||||
Rectangle { y: 0px; height: 1px; background: ImGuiLineStyle.border; }
|
||||
|
||||
SectionTitle { x: 29px; y: 7px; height: 28px; text: UiStrings.recent-connections; }
|
||||
GroupFilter {
|
||||
SectionTitle { x: 29px; y: 7px; width: open-gallery-button.x - self.x - 12px; height: 28px; text: UiStrings.recent-connections; }
|
||||
open-gallery-button := SecondaryButton {
|
||||
x: recent-group-filter.x - self.width - 8px;
|
||||
y: recent-group-filter.y;
|
||||
min-width: 60px;
|
||||
width: root.compact-language ? 60px : 72px;
|
||||
height: recent-group-filter.height;
|
||||
text-size: ImGuiFontStyle.base;
|
||||
border-color: #c9cdd2;
|
||||
border-radius: 4px;
|
||||
text: GalleryStrings.tr("桌面墙", "DeskHub", "DeskHub");
|
||||
accessible-role: button;
|
||||
accessible-label: self.text;
|
||||
accessible-action-default => { root.open-gallery(); }
|
||||
clicked => { root.open-gallery(); }
|
||||
}
|
||||
recent-group-filter := GroupFilter {
|
||||
x: parent.width - self.width - 29px; y: 8px;
|
||||
width: 155px; height: 28px;
|
||||
model: root.recent-groups;
|
||||
@@ -1338,9 +1343,11 @@ export component MainWindow inherits Window {
|
||||
}
|
||||
gallery := GalleryView {
|
||||
y: root.content-header-height; width: parent.width;
|
||||
height: parent.height - self.y - 24px;
|
||||
height: parent.height - self.y;
|
||||
visible: root.gallery-mode;
|
||||
simplified: root.gallery-simplified;
|
||||
window-active: root.window-active;
|
||||
tile-width <=> root.gallery-tile-width;
|
||||
network-open => { root.gallery-network-open = true; }
|
||||
controlling: root.gallery-controlling;
|
||||
pointer-input(button, kind, x, y) => { root.gallery-pointer(button, kind, x, y); }
|
||||
@@ -1348,7 +1355,6 @@ export component MainWindow inherits Window {
|
||||
key-input(text, pressed, ctrl, alt, shift, meta) => { root.gallery-key(text, pressed, ctrl, alt, shift, meta); }
|
||||
tiles: root.gallery-tiles; groups: root.gallery-groups;
|
||||
group-index <=> root.gallery-group-index;
|
||||
columns: root.gallery-columns; rows: root.gallery-rows;
|
||||
page: root.gallery-page; pages: root.gallery-pages; count: root.gallery-count;
|
||||
connected-count: root.gallery-connected; selected-count: root.gallery-selected;
|
||||
selected-audio-available: root.gallery-selected-audio-available;
|
||||
@@ -1359,6 +1365,7 @@ export component MainWindow inherits Window {
|
||||
importing <=> root.gallery-importing; recent-devices: root.gallery-recent-devices;
|
||||
recent-selected: root.gallery-recent-selected; import-group: root.gallery-import-group;
|
||||
action(code, value) => { root.gallery-action(code, value); }
|
||||
swap-devices(source, target) => { root.gallery-swap(source, target) }
|
||||
add-device(id, password, group, remember) => { root.gallery-add-device(id, password, group, remember) }
|
||||
import-recent(group) => { root.gallery-import-recent(group) }
|
||||
edit-alias(id, name) => {
|
||||
@@ -1369,8 +1376,8 @@ export component MainWindow inherits Window {
|
||||
root.delete-remote-id = id; root.delete-from-gallery = true; root.delete-open = true;
|
||||
}
|
||||
}
|
||||
// Shared server status bar stays visible in every connection and DeskHub view.
|
||||
Rectangle {
|
||||
// Server status and reconnect actions belong to the connection window.
|
||||
if !root.gallery-mode: Rectangle {
|
||||
y: parent.height - 24px;
|
||||
height: 24px;
|
||||
background: #fafbfc;
|
||||
@@ -1481,7 +1488,7 @@ export component MainWindow inherits Window {
|
||||
}
|
||||
|
||||
// Dismiss the title menu when clicking anywhere outside of it.
|
||||
if root.menu-open: TouchArea {
|
||||
if !root.gallery-mode && root.menu-open: TouchArea {
|
||||
x: 0px;
|
||||
y: 0px;
|
||||
width: parent.width;
|
||||
@@ -1494,7 +1501,7 @@ export component MainWindow inherits Window {
|
||||
}
|
||||
|
||||
// Title menu.
|
||||
if root.menu-open: Rectangle {
|
||||
if !root.gallery-mode && root.menu-open: Rectangle {
|
||||
x: menu-button.x + menu-button.width - self.width;
|
||||
y: menu-button.y + menu-button.height + 2px;
|
||||
width: max(80px, max(menu-settings-label.preferred-width,
|
||||
@@ -1953,19 +1960,14 @@ export component MainWindow inherits Window {
|
||||
DialogSurface {
|
||||
x: (parent.width - self.width) / 2;
|
||||
y: (parent.height - self.height) / 2;
|
||||
width: min(400px, parent.width - 40px); height: 446px;
|
||||
width: min(400px, parent.width - 40px); height: min(446px, parent.height - 16px);
|
||||
background: #f8fafc; border-radius: 14px; border-color: #e1e7ef;
|
||||
drop-shadow-color: #14294424; drop-shadow-blur: 24px; drop-shadow-offset-y: 8px;
|
||||
TouchArea { clicked => { focus-sink.focus(); } }
|
||||
Text {
|
||||
x: 18px; y: 18px; width: parent.width - 80px; height: 27px;
|
||||
x: 18px; y: 18px; width: parent.width - 36px; height: 27px;
|
||||
text: UiStrings.settings; font-size: 20px; font-weight: 600; color: #22324a;
|
||||
}
|
||||
SettingsButton {
|
||||
x: parent.width - 90px; y: 18px; width: 76px; height: 28px; quiet: true;
|
||||
text: GalleryStrings.tr("关闭", "Close", "Закрыть");
|
||||
clicked => { root.cancel-settings(); root.settings-open = false; root.self-host-settings-open = false; }
|
||||
}
|
||||
Rectangle {
|
||||
x: 18px; y: 56px; width: parent.width - 36px; height: 40px;
|
||||
background: #eaf0f6; border-radius: 9px;
|
||||
@@ -1995,7 +1997,7 @@ export component MainWindow inherits Window {
|
||||
}
|
||||
}
|
||||
if root.settings-tab == 0: settings-scroll := ScrollView {
|
||||
x: 18px; y: 108px; width: parent.width - 28px; height: 272px;
|
||||
x: 18px; y: 108px; width: parent.width - 28px; height: parent.height - 174px;
|
||||
viewport-y <=> root.settings-scroll-y;
|
||||
VerticalLayout {
|
||||
width: settings-scroll.width - 12px;
|
||||
@@ -2049,15 +2051,15 @@ export component MainWindow inherits Window {
|
||||
}
|
||||
}
|
||||
if root.settings-tab == 1: GallerySettings {
|
||||
x: 18px; y: 108px; width: parent.width - 36px; height: 272px;
|
||||
x: 18px; y: 108px; width: parent.width - 36px; height: parent.height - 174px;
|
||||
resolution-index <=> root.gallery-resolution-draft;
|
||||
frame-rate-index <=> root.gallery-frame-rate-draft;
|
||||
bandwidth-index <=> root.gallery-bandwidth-draft;
|
||||
error: root.gallery-settings-error;
|
||||
}
|
||||
Rectangle { x: 18px; y: 382px; width: parent.width - 36px; height: 1px; background: #e6ebf2; }
|
||||
Rectangle { x: 18px; y: parent.height - 64px; width: parent.width - 36px; height: 1px; background: #e6ebf2; }
|
||||
HorizontalLayout {
|
||||
x: 18px; y: 396px; width: parent.width - 36px; height: 32px; spacing: 10px;
|
||||
x: 18px; y: parent.height - 50px; width: parent.width - 36px; height: 32px; spacing: 10px;
|
||||
if root.settings-tab == 1: SettingsButton {
|
||||
width: 110px; quiet: true;
|
||||
text: GalleryStrings.tr("恢复默认", "Reset defaults", "По умолчанию");
|
||||
|
||||
Reference in New Issue
Block a user