import "../assets/fonts/NotoSansSC-Regular.subset.otf"; import "../assets/fonts/NotoSansSC-Bold.subset.otf"; import { Palette } from "std-widgets.slint"; import { Theme } from "theme.slint"; import { Sidebar, AppPage } from "sidebar.slint"; import { LaunchPage } from "pages/launch.slint"; import { TunnelPage, TunnelRow } from "pages/tunnel.slint"; import { ConfigPage } from "pages/config.slint"; import { LoggerPage, LogLine } from "pages/logger.slint"; import { AboutPage } from "pages/about_page.slint"; import { AboutDialog } from "pages/about.slint"; import { ToastHost } from "toast.slint"; import { Tr } from "i18n.slint"; import { AppMeta } from "version.slint"; import { OrbienTray } from "tray.slint"; export { AppPage, TunnelRow, LogLine, Tr, AboutDialog, AppMeta, Theme, OrbienTray } export component AppWindow inherits Window { title: "Orbien Desktop"; default-font-family: "Noto Sans SC"; default-font-size: 13px; icon: @image-url("../assets/app-icons/128x128.png"); preferred-width: 960px; preferred-height: 640px; min-width: 800px; min-height: 600px; background: Theme.chrome; MenuBar { Menu { title: Tr.menu-preferences; Menu { title: Tr.menu-language; MenuItem { title: (root.locale-index == 0 ? "✓ " : " ") + Tr.menu-lang-zh; activated => { if root.locale-index == 0 { return; } root.locale-index = 0; Tr.locale-index = 0; root.locale-changed(0); } } MenuItem { title: (root.locale-index == 1 ? "✓ " : " ") + Tr.menu-lang-en; activated => { if root.locale-index == 1 { return; } root.locale-index = 1; Tr.locale-index = 1; root.locale-changed(1); } } } Menu { title: Tr.menu-appearance; MenuItem { title: (root.theme-index == 0 ? "✓ " : " ") + Tr.menu-theme-light; activated => { if root.theme-index == 0 { return; } root.theme-index = 0; root.theme-changed(0); } } MenuItem { title: (root.theme-index == 1 ? "✓ " : " ") + Tr.menu-theme-dark; activated => { if root.theme-index == 1 { return; } root.theme-index = 1; root.theme-changed(1); } } } } Menu { title: Tr.menu-help; MenuItem { title: Tr.menu-about; activated => { root.show-about(); } } } } // navigation in-out property page: AppPage.launch; in-out property locale-index: 0; /// 0 = light (default), 1 = dark in-out property theme-index: 0; in-out property sidebar-cpu: "—"; in-out property sidebar-mem: "—"; // launch in-out property running: false; in-out property running-label: "—"; in-out property busy: false; in-out property <[TunnelRow]> tunnels; in-out property tunnel-editor-open: false; in-out property tunnel-editing-index: -1; in-out property tunnel-edit-name: ""; in-out property tunnel-edit-local-ip: "127.0.0.1"; in-out property tunnel-edit-local-port: "8080"; in-out property tunnel-edit-remote-port: "9000"; in-out property tunnel-edit-domains: ""; in-out property tunnel-edit-locations: ""; in-out property tunnel-edit-basic-auth-user: ""; in-out property tunnel-edit-basic-auth-password: ""; in-out property tunnel-edit-host-header-rewrite: ""; in-out property tunnel-edit-bandwidth-limit: ""; in-out property tunnel-edit-bandwidth-side-index: 0; in-out property tunnel-edit-proxy-protocol-index: 0; in-out property tunnel-edit-plugin-tls-term: false; in-out property tunnel-edit-plugin-local-addr: "127.0.0.1:80"; in-out property tunnel-edit-plugin-cert-file: ""; in-out property tunnel-edit-plugin-key-file: ""; in-out property tunnel-edit-plugin-host-rewrite: ""; in-out property tunnel-edit-plugin-username: ""; in-out property tunnel-edit-plugin-password: ""; in-out property tunnel-edit-type-index: 0; in-out property tunnel-show-advanced: false; // config in-out property server-addr: "127.0.0.1"; in-out property server-port: "9527"; in-out property token: ""; in-out property user: ""; in-out property protocol-index: 0; in-out property pool-count: "1"; in-out property ws-path: ""; in-out property tcp-mux: true; in-out property tls-enable: true; in-out property config-show-advanced: false; in-out property config-mux-keepalive: "30"; in-out property config-heartbeat-interval: ""; in-out property config-heartbeat-timeout: ""; in-out property config-udp-packet-size: "1500"; in-out property config-tls-server-name: ""; in-out property config-tls-ca: ""; in-out property config-tls-cert: ""; in-out property config-tls-key: ""; in-out property config-quic-keepalive: "10"; in-out property config-quic-idle: "30"; in-out property config-quic-streams: "100000"; in-out property config-file-path: ""; // Global toast in-out property toast-visible: false; in-out property toast-text: ""; /// 0 = success, 1 = error in-out property toast-kind: 0; in-out property toast-token: 0; // logger in-out property log-query: ""; in-out property log-auto-scroll: false; in-out property <[LogLine]> log-lines; in-out property log-scroll-gen: 0; callback locale-changed(int); callback theme-changed(int); callback show-about(); callback open-url(string); callback toggle-client(); callback open-logger(); callback page-changed(AppPage); callback tunnel-add(); callback tunnel-save(); callback tunnel-cancel(); callback tunnel-edit(int); callback tunnel-delete(int); callback tunnel-copy-remote(string); callback config-save(); callback config-reset(); callback pick-file(string); callback logs-clear(); callback log-query-edited(string); changed locale-index => { Tr.locale-index = root.locale-index; } changed theme-index => { Theme.mode = root.theme-index; Palette.color-scheme = root.theme-index == 1 ? ColorScheme.dark : ColorScheme.light; } init => { Theme.mode = root.theme-index; Palette.color-scheme = root.theme-index == 1 ? ColorScheme.dark : ColorScheme.light; } changed page => { root.page-changed(root.page); } HorizontalLayout { spacing: 0; Sidebar { page <=> root.page; cpu-usage: root.sidebar-cpu; mem-usage: root.sidebar-mem; } Rectangle { background: Theme.bg; horizontal-stretch: 1; vertical-stretch: 1; min-height: Theme.page-min-height + Theme.page-pad * 2; clip: true; private property content-x: Theme.page-pad; private property content-y: Theme.page-pad; private property content-w: self.width - Theme.page-pad * 2; private property content-h: self.height - Theme.page-pad * 2; LaunchPage { x: parent.content-x; y: parent.content-y; width: parent.content-w; height: parent.content-h; visible: root.page == AppPage.launch; running <=> root.running; running-label: root.running-label; busy: root.busy; toggle-clicked => { root.toggle-client(); } view-log-clicked => { root.open-logger(); } } TunnelPage { x: parent.content-x; y: parent.content-y; width: parent.content-w; height: parent.content-h; visible: root.page == AppPage.tunnel; tunnels: root.tunnels; editing-index: root.tunnel-editing-index; editor-open <=> root.tunnel-editor-open; edit-name <=> root.tunnel-edit-name; edit-local-ip <=> root.tunnel-edit-local-ip; edit-local-port <=> root.tunnel-edit-local-port; edit-remote-port <=> root.tunnel-edit-remote-port; edit-domains <=> root.tunnel-edit-domains; edit-locations <=> root.tunnel-edit-locations; edit-basic-auth-user <=> root.tunnel-edit-basic-auth-user; edit-basic-auth-password <=> root.tunnel-edit-basic-auth-password; edit-host-header-rewrite <=> root.tunnel-edit-host-header-rewrite; edit-bandwidth-limit <=> root.tunnel-edit-bandwidth-limit; edit-bandwidth-side-index <=> root.tunnel-edit-bandwidth-side-index; edit-proxy-protocol-index <=> root.tunnel-edit-proxy-protocol-index; edit-plugin-tls-term <=> root.tunnel-edit-plugin-tls-term; edit-plugin-local-addr <=> root.tunnel-edit-plugin-local-addr; edit-plugin-cert-file <=> root.tunnel-edit-plugin-cert-file; edit-plugin-key-file <=> root.tunnel-edit-plugin-key-file; edit-plugin-host-rewrite <=> root.tunnel-edit-plugin-host-rewrite; edit-plugin-username <=> root.tunnel-edit-plugin-username; edit-plugin-password <=> root.tunnel-edit-plugin-password; edit-type-index <=> root.tunnel-edit-type-index; show-advanced <=> root.tunnel-show-advanced; add-clicked => { root.tunnel-add(); } save-clicked => { root.tunnel-save(); } cancel-clicked => { root.tunnel-cancel(); } edit-row(i) => { root.tunnel-edit(i); } delete-row(i) => { root.tunnel-delete(i); } copy-remote(text) => { root.tunnel-copy-remote(text); } pick-file(target) => { root.pick-file(target); } } ConfigPage { x: parent.content-x; y: parent.content-y; width: parent.content-w; height: parent.content-h; visible: root.page == AppPage.config; server-addr <=> root.server-addr; server-port <=> root.server-port; token <=> root.token; user <=> root.user; protocol-index <=> root.protocol-index; pool-count <=> root.pool-count; ws-path <=> root.ws-path; tcp-mux <=> root.tcp-mux; tls-enable <=> root.tls-enable; show-advanced <=> root.config-show-advanced; mux-keepalive <=> root.config-mux-keepalive; heartbeat-interval <=> root.config-heartbeat-interval; heartbeat-timeout <=> root.config-heartbeat-timeout; udp-packet-size <=> root.config-udp-packet-size; tls-server-name <=> root.config-tls-server-name; tls-ca <=> root.config-tls-ca; tls-cert <=> root.config-tls-cert; tls-key <=> root.config-tls-key; quic-keepalive <=> root.config-quic-keepalive; quic-idle <=> root.config-quic-idle; quic-streams <=> root.config-quic-streams; config-file-path <=> root.config-file-path; save-clicked => { root.config-save(); } reset-clicked => { root.config-reset(); } pick-file(target) => { root.pick-file(target); } } if root.page == AppPage.logger: LoggerPage { x: parent.content-x; y: parent.content-y; width: parent.content-w; height: parent.content-h; query <=> root.log-query; auto-scroll <=> root.log-auto-scroll; lines: root.log-lines; scroll-gen: root.log-scroll-gen; clear-clicked => { root.logs-clear(); } query-edited(q) => { root.log-query-edited(q); } } AboutPage { x: parent.content-x; y: parent.content-y; width: parent.content-w; height: parent.content-h; visible: root.page == AppPage.about; open-github => { root.open-url("https://github.com/orbien-org/orbien"); } open-docs => { root.open-url("https://orbien-org.github.io/orbien/"); } open-feedback => { root.open-url("https://github.com/orbien-org/orbien/issues"); } open-slint-about => { root.show-about(); } } } } toast := ToastHost { x: (root.width - self.width) / 2; y: root.height - self.height - 28px; width: min(420px, root.width - 48px); visible: root.toast-visible; visible-toast <=> root.toast-visible; text <=> root.toast-text; kind <=> root.toast-kind; token <=> root.toast-token; } }