From 57d2a6775eb8686a4e99a6a58eaf8b835fdea291 Mon Sep 17 00:00:00 2001 From: guyverino Date: Fri, 4 Sep 2026 00:11:36 +0200 Subject: [PATCH] feat(brand): swap in the MoonTerminal lockup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The header and the empty-chart placeholder drew the Moonbot wordmark. Both now draw the MoonTerminal one, shipped as two cuts under assets/brand — dark and light — so the scheme picks a FILE instead of patching a fill, and a custom palette can no longer repaint the brand. MoonWindowFrame hardcodes MoonUI's own lockup and has no variant for a foreign one, so the main header assembles its brand cluster from the frame's drag handle plus design::header_logo. The geometry matches brand_cluster; the rule is the terminal's own chrome_divider rather than MoonUI's fainter border copy of it, since the terminal now owns that seam. docs/WINDOWING.md records the exception and its exit condition, and the windowing contract test names both the helper and the asset path so no other screen can follow. Every lockup size is ported through one LOGO_PORT_SCALE factor: the new artwork is 283.23 wide against 199, and the port keeps the ICON at its drawn size rather than the box it sat in, so only the wordmark gets longer. The header buys its room in width (86 -> 122.4) because its strip is height-constrained; the chart placeholder keeps its share of the pane, floor and ceiling scaled alike. Both surfaces now take their image from a two-entry LazyLock table instead of building one per frame: the colour scheme is the document's only input, so the header stopped copying and hashing 6.9KB of asset on every frame and the glow stopped re-composing 7.5KB per empty pane. --- assets/brand/moonbot-logo.svg | 19 -- assets/brand/moonterminal-logo-blue-dark.svg | 9 + assets/brand/moonterminal-logo-blue-light.svg | 9 + .../moon-ui-gpui/src/chart_tabs/add_stack.rs | 5 +- .../moon-ui-gpui/src/chart_tabs/main_stack.rs | 5 +- .../src/chrome/terminal_chrome.rs | 32 ++- crates/moon-ui-gpui/src/design.rs | 188 +++++++++++++----- crates/moon-ui-gpui/src/design/tests.rs | 52 ++++- .../moon-ui-gpui/src/panels/chart/render.rs | 9 +- .../tests/theme_contract/windowing.rs | 12 +- docs/WINDOWING.md | 20 +- docs/tour/index.html | 16 +- tools/tour/content/zones.yml | 20 +- 13 files changed, 286 insertions(+), 110 deletions(-) delete mode 100644 assets/brand/moonbot-logo.svg create mode 100644 assets/brand/moonterminal-logo-blue-dark.svg create mode 100644 assets/brand/moonterminal-logo-blue-light.svg diff --git a/assets/brand/moonbot-logo.svg b/assets/brand/moonbot-logo.svg deleted file mode 100644 index 151dc60b..00000000 --- a/assets/brand/moonbot-logo.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/assets/brand/moonterminal-logo-blue-dark.svg b/assets/brand/moonterminal-logo-blue-dark.svg new file mode 100644 index 00000000..d375f93c --- /dev/null +++ b/assets/brand/moonterminal-logo-blue-dark.svg @@ -0,0 +1,9 @@ + + MoonTerminal + + + + + + + diff --git a/assets/brand/moonterminal-logo-blue-light.svg b/assets/brand/moonterminal-logo-blue-light.svg new file mode 100644 index 00000000..190ecff1 --- /dev/null +++ b/assets/brand/moonterminal-logo-blue-light.svg @@ -0,0 +1,9 @@ + + MoonTerminal + + + + + + + diff --git a/crates/moon-ui-gpui/src/chart_tabs/add_stack.rs b/crates/moon-ui-gpui/src/chart_tabs/add_stack.rs index a37ca888..3bbf8040 100644 --- a/crates/moon-ui-gpui/src/chart_tabs/add_stack.rs +++ b/crates/moon-ui-gpui/src/chart_tabs/add_stack.rs @@ -1130,7 +1130,10 @@ impl Render for AddChartStack { .flex() .items_center() .justify_center() - .child(crate::design::logo_glow_sized(cx, 220.0)) + .child(crate::design::logo_glow_sized( + cx, + crate::design::EMPTY_STACK_LOGO_W, + )) .into_any_element(); // Measured here too: a window resized while the tab holds no charts would otherwise // leave a stale size behind, and the first frame WITH charts would divide by it. diff --git a/crates/moon-ui-gpui/src/chart_tabs/main_stack.rs b/crates/moon-ui-gpui/src/chart_tabs/main_stack.rs index fcd88f31..2645db64 100644 --- a/crates/moon-ui-gpui/src/chart_tabs/main_stack.rs +++ b/crates/moon-ui-gpui/src/chart_tabs/main_stack.rs @@ -1621,7 +1621,10 @@ impl Render for MainChartStack { .flex() .items_center() .justify_center() - .child(crate::design::logo_glow_sized(cx, 220.0)) + .child(crate::design::logo_glow_sized( + cx, + crate::design::EMPTY_STACK_LOGO_W, + )) .into_any_element(); // Measured here too, for the reason the fullscreen branch keeps its probe: a resize // taken while the stack is empty must not leave a size the first divided frame uses. diff --git a/crates/moon-ui-gpui/src/chrome/terminal_chrome.rs b/crates/moon-ui-gpui/src/chrome/terminal_chrome.rs index 2c41b416..8515898d 100644 --- a/crates/moon-ui-gpui/src/chrome/terminal_chrome.rs +++ b/crates/moon-ui-gpui/src/chrome/terminal_chrome.rs @@ -9,7 +9,7 @@ use gpui::*; use moon_ui::{ MoonButton, MoonButtonIconSlot, MoonButtonSize, MoonButtonVariant, MoonDropdown, MoonMenuItem, MoonMenuSize, MoonPalette, MoonPopover, MoonPopoverPlacement, MoonPopupMenu, MoonRect, - MoonSelectorPill, MoonSelectorSegment, MoonTag, MoonWindowFrame, MoonWindowFrameBrand, h_flex, + MoonSelectorPill, MoonSelectorSegment, MoonTag, MoonWindowFrame, h_flex, }; use rust_i18n::t; @@ -136,19 +136,29 @@ pub fn header( // internally, so the seams line up. .gap(design::ui_px(cx, design::CHROME_GAP)) .bg(rgb(p.shell_high)) - // Brand draws its OWN trailing separator (MoonWindowFrame::brand_cluster), so the - // groups below add only the seams after them. It is also the FIRST thing this row gives - // up on a narrow window (`design::header_brand_visible`): dropping the mark to `None` - // keeps the drag region and takes the rule with it, so the space goes to the readouts - // that carry information instead. + // The brand carries its OWN trailing separator, so the groups below add only the seams + // after them. It is also the FIRST thing this row gives up on a narrow window + // (`design::header_brand_visible`): dropping the mark keeps the drag region and takes the + // rule with it, so the space goes to the readouts that carry information instead. + // + // The cluster is assembled here rather than through `MoonWindowFrame::brand_cluster`, + // which draws MoonUI's own Moonbot lockup: the terminal ships the MoonTerminal one from + // `assets/brand`. Only the drag handle comes from the frame — that region is what makes + // the titlebar grabbable, and `brand_cluster` is nothing more than that handle plus the + // two children added below, at the same `CHROME_GAP` and the same rule height. The rule + // itself is `chrome_divider`, not MoonUI's fainter `border` copy of it: owning the cluster + // means this seam answers to the same contrast rule as every other seam in the row. .child( MoonWindowFrame::main("terminal-header-brand-drag", 0.0) - .brand(if design::header_brand_visible(cx, chrome_width) { - MoonWindowFrameBrand::Default - } else { - MoonWindowFrameBrand::None + .drag_handle() + .flex() + .items_center() + .gap(design::ui_px(cx, design::CHROME_GAP)) + .when(design::header_brand_visible(cx, chrome_width), |cluster| { + cluster + .child(design::header_logo(cx)) + .child(design::chrome_divider(cx, p)) }) - .brand_cluster(cx) .flex_none() .h_full(), ) diff --git a/crates/moon-ui-gpui/src/design.rs b/crates/moon-ui-gpui/src/design.rs index f2cdadd9..99b092fa 100644 --- a/crates/moon-ui-gpui/src/design.rs +++ b/crates/moon-ui-gpui/src/design.rs @@ -7,7 +7,7 @@ use gpui::*; use moon_core::util::fmt::DeltaSign; use moon_ui::{MoonMetrics, MoonPalette, MoonTheme, MoonTone, rgba_from}; use std::collections::HashMap; -use std::sync::Arc; +use std::sync::{Arc, LazyLock}; const M: MoonMetrics = MoonMetrics::TERMINAL; @@ -191,6 +191,11 @@ pub const HEADER_LABEL_MAX_W: f32 = 260.0; /// readouts would disappear at the same width and the priority above would be a comment rather /// than a behaviour. Usable only because [`HEADER_LABEL_MAX_W`] bounds the clusters that would /// otherwise grow without limit. +/// +/// These are TUNED window widths, not values derived from what the row holds, so the brand's own +/// width does not enter them: the MoonTerminal lockup is 36px wider than the Moonbot one these +/// were set against, and the `flex_1` drag spacer absorbs the difference. Re-tune them by looking +/// at the row, not by arithmetic on the mark. const HEADER_BRAND_MIN_W: f32 = 1400.0; const TICKER_DELTAS_MIN_W: f32 = 1200.0; const TICKER_MIN_W: f32 = 1000.0; @@ -252,11 +257,52 @@ pub fn platform_window_decorations() -> Option { } } -const LOGO_GLOW_SVG_RAW: &str = include_str!("../../../assets/brand/moonbot-logo.svg"); -const LOGO_SRC_W: f32 = 199.0; +/// The MoonTerminal lockup, one cut per colour scheme. +/// +/// Each file already carries its own wordmark colour — `#E7E7E7` in the dark cut, `#17202A` in the +/// light one, with the blue "Terminal" shared — so the terminal PICKS a file instead of patching a +/// fill the way the old single-cut Moonbot asset needed. A custom palette therefore no longer +/// recolours the brand, which is the point of a brand asset. +const LOGO_SVG_DARK: &str = include_str!("../../../assets/brand/moonterminal-logo-blue-dark.svg"); +const LOGO_SVG_LIGHT: &str = include_str!("../../../assets/brand/moonterminal-logo-blue-light.svg"); +const LOGO_SRC_W: f32 = 283.23; const LOGO_SRC_H: f32 = 43.0; -const LOGO_GLOW_VIEW_W: f32 = LOGO_SRC_W * 1.2; -const LOGO_GLOW_VIEW_H: f32 = LOGO_SRC_W * 1.2; +/// Factor carrying every lockup size across the brand swap, from the 199px-wide Moonbot mark the +/// sizes below were tuned against to the 283.23px-wide MoonTerminal one. +/// +/// The port keeps the ICON's drawn size rather than the box it sat in: only the wordmark got +/// longer, and holding a width tuned for the shorter mark would shrink the whole lockup by a third +/// and read as a different, smaller logo. Spelling the factor ONCE is the load-bearing part — +/// these five sizes live in two files, and hand-multiplying each one is how four of them stay +/// right while the fifth quietly does not. +const LOGO_PORT_SCALE: f32 = LOGO_SRC_W / 199.0; + +/// Width of the placeholder lockup a chart stack draws while it holds no charts. +pub const EMPTY_STACK_LOGO_W: f32 = 220.0 * LOGO_PORT_SCALE; + +/// Share of a chart slot's width the same placeholder covers, bounded by [`CHART_LOGO_MIN_W`] and +/// [`CHART_LOGO_MAX_W`] — a floor so it stays legible in a small pane, a ceiling so it stays a +/// watermark in a large one. +/// +/// The floor is ported like everything else: leaving it where it was would have kept exactly the +/// small panes — the ones that need it — drawing an icon a third smaller than before. It buys that +/// at the far end: a pane narrower than the floor itself now clips the LOCKUP, where the shorter +/// mark still fitted. That pane is under 256 logical px wide — narrower than the placeholder it +/// would be showing — and between there and 643 px, where the share takes over, the floor is what +/// keeps the icon at its designed size. The glow frame is [`LOGO_GLOW_SCALE`] times these widths +/// and overhangs sooner, which costs nothing visible: its aura reaches zero opacity at that edge. +pub const CHART_LOGO_SLOT_SHARE: f32 = 0.28 * LOGO_PORT_SCALE; +pub const CHART_LOGO_MIN_W: f32 = 180.0 * LOGO_PORT_SCALE; +pub const CHART_LOGO_MAX_W: f32 = 280.0 * LOGO_PORT_SCALE; + +/// Header lockup width: the header strip is height-constrained, so the longer wordmark has to buy +/// its room in width, or the mark shrinks inside a row whose height cannot follow it. +const HEADER_LOGO_W: f32 = 86.0 * LOGO_PORT_SCALE; + +/// How much wider than the lockup the glow canvas is; the aura fills the difference. +const LOGO_GLOW_SCALE: f32 = 1.2; +/// The glow canvas is SQUARE, so the aura reads as a disc rather than a flat ellipse. +const LOGO_GLOW_VIEW: f32 = LOGO_SRC_W * LOGO_GLOW_SCALE; pub fn solid(hex: u32) -> Rgba { rgb(hex) @@ -1056,32 +1102,72 @@ pub fn r_container(cx: &App) -> Pixels { ui_px(cx, R_CONTAINER_BASE) } -/// Brand-book navy for the Moonbot wordmark in the light theme. +/// Return the lockup cut that belongs to a colour scheme. /// -/// Navy lacks contrast in the dark theme, where the wordmark uses `p.text` instead. -const LOGO_WORDMARK_NAVY: u32 = 0x0C2C4A; +/// Each file carries its own wordmark colour, so the scheme picks a FILE; nothing recolours the +/// brand at runtime, and a custom palette therefore cannot repaint it. +fn logo_svg(light: bool) -> &'static str { + if light { LOGO_SVG_LIGHT } else { LOGO_SVG_DARK } +} -pub fn logo_glow_sized(cx: &App, width: f32) -> impl IntoElement { - let p = MoonPalette::active(cx); - let text = if p.is_light() { - LOGO_WORDMARK_NAVY - } else { - p.text - }; - let text_fill = format!("#{text:06X}"); - let logo = - LOGO_GLOW_SVG_RAW.replace(r##"fill="#E7E7E7""##, &format!(r##"fill="{text_fill}""##)); - let paths = logo - .split_once(r#""#) - .and_then(|(_, rest)| rest.split_once("")) - .map(|(paths, _)| paths) - .unwrap_or(""); - let cx = LOGO_GLOW_VIEW_W * 0.5; - let cy = LOGO_GLOW_VIEW_H * 0.5; - let r = LOGO_GLOW_VIEW_W * 0.5; - let logo_x = (LOGO_GLOW_VIEW_W - LOGO_SRC_W) * 0.5; - let logo_y = (LOGO_GLOW_VIEW_H - LOGO_SRC_H) * 0.5; - let (aura_0_color, aura_1_color, aura_2_color, aura_0, aura_1, aura_2) = if p.is_light() { +/// Return everything the lockup's root `` wraps, for embedding in a composed document. +/// +/// The cut is the root tag itself, not the first ``: an export is free to wrap its paths in +/// a `` or to declare a ``/`` ahead of them, and starting at the first path +/// would drop those opening tags while keeping their closing ones — unbalanced markup usvg rejects +/// outright, which paints NOTHING and looks exactly like a decode failure. Whatever the file +/// carries travels as-is; a `` among it is inert inside a rasterized document. +/// +/// Returns an empty string if the file has no root tag to cut at, which the asset test catches. +fn logo_paths(svg: &str) -> &str { + svg.split_once("')) + .and_then(|(_, inner)| inner.rsplit_once("")) + .map_or("", |(inner, _)| inner) +} + +/// Wrap SVG source in the GPUI image every element builder here takes. +fn svg_image(svg: impl Into>) -> Arc { + Arc::new(Image::from_bytes(ImageFormat::Svg, svg.into())) +} + +/// The brand cuts as decoded images, indexed by `is_light()`. +/// +/// Built once because there are only ever two of them. GPUI keys its raster cache on a hash of the +/// bytes, so consecutive frames already shared one texture; what repeated per frame was the 6.9KB +/// copy and the hash upstream of that cache, inside the header's own render. +static LOGO_IMAGES: LazyLock<[Arc; 2]> = + LazyLock::new(|| [svg_image(logo_svg(false)), svg_image(logo_svg(true))]); + +/// The composed glow documents, indexed by `is_light()`. +/// +/// Two, for the reason [`LOGO_IMAGES`] gives: the colour scheme is the document's ONLY input. The +/// caller's `width` never enters it — that sizes the element afterwards — so re-composing this +/// ~7.5KB string per empty pane per frame produced the same two documents forever. +static GLOW_IMAGES: LazyLock<[Arc; 2]> = + LazyLock::new(|| [svg_image(glow_svg(false)), svg_image(glow_svg(true))]); + +/// The header lockup: the brand at the left end of the main window's titlebar. +/// +/// Sized off [`HEADER_LOGO_W`] through `ui()` — the UI-scale track MoonUI's own brand used — so the +/// mark follows the interface scale but NOT the font slider, matching the separator beside it. +/// +/// The asset is decoded whole, unlike in [`glow_svg`], which has to splice it into a document of +/// its own: here the file IS the document, so there is nothing to rewrite. +pub fn header_logo(cx: &App) -> impl IntoElement { + let width = ui_value(cx, HEADER_LOGO_W); + img(LOGO_IMAGES[usize::from(MoonPalette::active(cx).is_light())].clone()) + .w(px(width)) + .h(px(width * (LOGO_SRC_H / LOGO_SRC_W))) +} + +/// Compose the glow document for one colour scheme: the aura disc with the lockup centred on it. +fn glow_svg(light: bool) -> String { + let paths = logo_paths(logo_svg(light)); + let centre = LOGO_GLOW_VIEW * 0.5; + let logo_x = (LOGO_GLOW_VIEW - LOGO_SRC_W) * 0.5; + let logo_y = (LOGO_GLOW_VIEW - LOGO_SRC_H) * 0.5; + let (aura_0_color, aura_1_color, aura_2_color, aura_0, aura_1, aura_2) = if light { ( "#BFF5C9", "#AEEFC1", @@ -1093,41 +1179,33 @@ pub fn logo_glow_sized(cx: &App, width: f32) -> impl IntoElement { } else { ("#00BCFF", "#1A76FF", "#0A5CFF", 0.30, 0.19, 0.07) }; - let svg = format!( - r##" + format!( + r##" - + - + {paths} "##, - view_w = LOGO_GLOW_VIEW_W, - view_h = LOGO_GLOW_VIEW_H, - cx = cx, - cy = cy, - r = r, - logo_x = logo_x, - logo_y = logo_y, - aura_0_color = aura_0_color, - aura_1_color = aura_1_color, - aura_2_color = aura_2_color, - aura_0 = aura_0, - aura_1 = aura_1, - aura_2 = aura_2, - paths = paths, - ); - let frame_w = width * (LOGO_GLOW_VIEW_W / 199.0); - img(Arc::new(Image::from_bytes( - ImageFormat::Svg, - svg.into_bytes(), - ))) - .w(px(frame_w)) - .h(px(frame_w * (LOGO_GLOW_VIEW_H / LOGO_GLOW_VIEW_W))) + view = LOGO_GLOW_VIEW, + ) +} + +/// The glowing placeholder an empty chart surface draws; `width` is the lockup's own width. +/// +/// The element is the square glow canvas around it, hence the [`LOGO_GLOW_SCALE`] factor: taking +/// the LOCKUP width keeps every caller's number comparable to the artwork rather than to a frame +/// whose size the aura decides. +pub fn logo_glow_sized(cx: &App, width: f32) -> impl IntoElement { + let frame_w = width * LOGO_GLOW_SCALE; + img(GLOW_IMAGES[usize::from(MoonPalette::active(cx).is_light())].clone()) + .w(px(frame_w)) + .h(px(frame_w)) } /// Vertical 1px group separator. diff --git a/crates/moon-ui-gpui/src/design/tests.rs b/crates/moon-ui-gpui/src/design/tests.rs index 404e4c1c..d9a80325 100644 --- a/crates/moon-ui-gpui/src/design/tests.rs +++ b/crates/moon-ui-gpui/src/design/tests.rs @@ -1,4 +1,4 @@ -//! Regression coverage for exact batched text measurement. +//! Regression coverage for exact batched text measurement and for the brand assets. use super::{FontId, FontWeight, MonoGlyphWidthCache, wrap_text}; use std::collections::HashMap; @@ -105,3 +105,53 @@ fn an_unbreakable_word_is_cut_rather_than_looped() { // And zero lines is a legitimate ask: it prints nothing rather than looping. assert!(wrap_text("anything", 10.0, 0, measure).is_empty()); } + +/// The brand cuts: scheme name, asset source, and the wordmark colour that cut must carry. +const BRAND_CUTS: [(&str, &str, &str); 2] = [ + ("dark", super::LOGO_SVG_DARK, "#E7E7E7"), + ("light", super::LOGO_SVG_LIGHT, "#17202A"), +]; + +/// Both cuts must survive [`super::logo_paths`], which splices them into the glow document. +/// +/// The extraction is string surgery on an asset nobody rebuilds when they re-export it, and its +/// failure is SILENT at runtime: an empty result draws an aura with no mark, indistinguishable +/// from a decode failure. So the check belongs here rather than in a bug report. +#[test] +fn brand_cuts_survive_the_glow_extraction() { + for (name, svg, _) in BRAND_CUTS { + let inner = super::logo_paths(svg); + assert!(inner.contains(" small mark; - `Popup` -> no logo. +Единственное исключение — full logo главного окна: `MoonWindowFrame` рисует свой +Moonbot-lockup, зашитый в компонент, а продукт называется MoonTerminal. Поэтому +header главного окна собирает бренд-кластер сам (`chrome/terminal_chrome.rs`): +drag-зону по-прежнему даёт `MoonWindowFrame::drag_handle()`, а лого и разделитель — +`design::header_logo` над ассетами `assets/brand/`. Геометрия кластера та же, что у +`brand_cluster` (`CHROME_GAP`, линейка 16px), но линейку рисует `design::chrome_divider`: +раз кластер собирает терминал, шов подчиняется тому же контрасту, что и остальные швы +строки, а не более бледному `border` из MoonUI. Вернуть `brand_cluster` следует ровно +тогда, когда `MoonWindowFrame` научится принимать чужой lockup. Для mark-окон и popup-ов +правило ниже действует без изменений. + Для titlebar-зоны использовать: - `MoonWindowFrame::brand_cluster(cx)` - brand + separator без title; @@ -247,6 +258,10 @@ MoonTerminal использует три визуальных класса ок Если в экране хочется "просто поставить логотип" или "просто нарисовать x", это значит, что в MoonUI не хватает нужного `MoonWindowFrameKind` или helper в `MoonWindowFrame`. Исправлять надо MoonUI-контракт, а не конкретный экран. +Единственное записанное исключение — брендовый lockup главного окна выше: пока в +`MoonWindowFrame` нет варианта под чужой логотип, его рисует `design::header_logo` +из `chrome/terminal_chrome.rs`. Оно записано здесь и закреплено тестом, а не +заведено по месту, — второго такого исключения быть не должно. Прямые использования в terminal UI запрещены: @@ -256,6 +271,9 @@ MoonTerminal использует три визуальных класса ок - `start_window_move`; - `titlebar_double_click`; - `logo_sized` / `logo_mark` вне самого brand/helper слоя; +- `design::header_logo` вне `chrome/terminal_chrome.rs` и открытие файла по пути + `assets/brand/` вне `design.rs` (назвать папку в комментарии можно) — логотип + берется у `MoonWindowFrame`, а единственное исключение описано выше; - `WindowOptions { ... }` вне `windowing.rs`. Запрет закреплен тестом `terminal_windows_use_closed_window_frame_api` в diff --git a/docs/tour/index.html b/docs/tour/index.html index 71b53b33..2521e869 100644 --- a/docs/tour/index.html +++ b/docs/tour/index.html @@ -890,7 +890,7 @@

Наведите или кликните

MANUAL режим

    -
  1. Бренд и перетаскивание — Логотип Moonbot и зона захвата окна: за неё окно таскается по экрану. Правее логотипа MoonUI сам рисует разделитель — поэтому второго терминал не добавляет.
  2. +
  3. Бренд и перетаскивание — Логотип MoonTerminal и зона захвата окна: за неё окно таскается по экрану. Логотип и разделитель правее него терминал рисует сам — рамка MoonUI знает только свой Moonbot.
  4. Режим воркспейса — Переключает рабочее пространство группы. В режиме AUTO терминал сам держит на графике монету активного ядра.
  5. Активное ядро и его шестерёнка — Выбор ядра, к которому относятся баланс, торговые кнопки и график. Шестерёнка открывает настройки именно этого ядра — блэклист, плечо, режим позиции.
  6. Баланс ядра — Свободный и общий USDT активного торгового ядра, как их отдаёт сервер. Если число устарело или курс посчитать не удалось, терминал показывает это, а не выдаёт старую цифру за живую.
  7. @@ -912,7 +912,7 @@

    MANUAL режим

AUTO режим

    -
  1. Бренд и перетаскивание — Логотип Moonbot и зона захвата окна: за неё окно таскается по экрану. Правее логотипа MoonUI сам рисует разделитель — поэтому второго терминал не добавляет.
  2. +
  3. Бренд и перетаскивание — Логотип MoonTerminal и зона захвата окна: за неё окно таскается по экрану. Логотип и разделитель правее него терминал рисует сам — рамка MoonUI знает только свой Moonbot.
  4. Режим воркспейса — Рабочее пространство для автоторговли; раскладка общая для всех серверов, открепление окон выключено
  5. Индикатор ядра, закреплённый рейкой — В режиме AUTO пилюля в шапке отключена и без меню: она только показывает выбранное на левой рейке ядро или «Полную сводку». Шестерёнка по-прежнему открывает настройки этого ядра. Баланс в шапке скрыт, пока выбрана сводка, — иначе рядом с подписью «вся группа» оказалась бы цифра одного случайного сервера.
  6. Тикер курса — Курс и дельты за 1ч / 24ч. Клик — открыть график, двойной — выбрать монету и ядро
  7. @@ -1284,13 +1284,13 @@

    AUTO режим

    "n": 1, "ru": [ "Бренд и перетаскивание", - "Логотип Moonbot и зона захвата окна: за неё окно таскается по экрану. Правее логотипа MoonUI сам рисует разделитель — поэтому второго терминал не добавляет." + "Логотип MoonTerminal и зона захвата окна: за неё окно таскается по экрану. Логотип и разделитель правее него терминал рисует сам — рамка MoonUI знает только свой Moonbot." ], "en": [ "Brand and window drag", - "The Moonbot logo doubles as the window's drag handle. MoonUI draws its own separator right of it, which is why the terminal never adds a second one." + "The MoonTerminal logo doubles as the window's drag handle. The terminal draws both the mark and the separator right of it itself — the MoonUI frame only knows its own Moonbot lockup." ], - "src": "chrome/terminal_chrome.rs — brand_cluster" + "src": "chrome/terminal_chrome.rs — header brand cluster" }, "ws": { "n": 2, @@ -1549,13 +1549,13 @@

    AUTO режим

    "n": 1, "ru": [ "Бренд и перетаскивание", - "Логотип Moonbot и зона захвата окна: за неё окно таскается по экрану. Правее логотипа MoonUI сам рисует разделитель — поэтому второго терминал не добавляет." + "Логотип MoonTerminal и зона захвата окна: за неё окно таскается по экрану. Логотип и разделитель правее него терминал рисует сам — рамка MoonUI знает только свой Moonbot." ], "en": [ "Brand and window drag", - "The Moonbot logo doubles as the window's drag handle. MoonUI draws its own separator right of it, which is why the terminal never adds a second one." + "The MoonTerminal logo doubles as the window's drag handle. The terminal draws both the mark and the separator right of it itself — the MoonUI frame only knows its own Moonbot lockup." ], - "src": "chrome/terminal_chrome.rs — brand_cluster" + "src": "chrome/terminal_chrome.rs — header brand cluster" }, "ws": { "n": 2, diff --git a/tools/tour/content/zones.yml b/tools/tour/content/zones.yml index 88a433fc..70600b51 100644 --- a/tools/tour/content/zones.yml +++ b/tools/tour/content/zones.yml @@ -14,12 +14,12 @@ maps: ru: Бренд и перетаскивание en: Brand and window drag body: - ru: 'Логотип Moonbot и зона захвата окна: за неё окно таскается по экрану. Правее логотипа MoonUI - сам рисует разделитель — поэтому второго терминал не добавляет.' - en: The Moonbot logo doubles as the window's drag handle. MoonUI draws its own separator right of - it, which is why the terminal never adds a second one. + ru: 'Логотип MoonTerminal и зона захвата окна: за неё окно таскается по экрану. Логотип и + разделитель правее него терминал рисует сам — рамка MoonUI знает только свой Moonbot.' + en: The MoonTerminal logo doubles as the window's drag handle. The terminal draws both the mark + and the separator right of it itself — the MoonUI frame only knows its own Moonbot lockup. src: - code: chrome/terminal_chrome.rs — brand_cluster + code: chrome/terminal_chrome.rs — header brand cluster - id: ws n: 2 title: @@ -229,12 +229,12 @@ maps: ru: Бренд и перетаскивание en: Brand and window drag body: - ru: 'Логотип Moonbot и зона захвата окна: за неё окно таскается по экрану. Правее логотипа MoonUI - сам рисует разделитель — поэтому второго терминал не добавляет.' - en: The Moonbot logo doubles as the window's drag handle. MoonUI draws its own separator right of - it, which is why the terminal never adds a second one. + ru: 'Логотип MoonTerminal и зона захвата окна: за неё окно таскается по экрану. Логотип и + разделитель правее него терминал рисует сам — рамка MoonUI знает только свой Moonbot.' + en: The MoonTerminal logo doubles as the window's drag handle. The terminal draws both the mark + and the separator right of it itself — the MoonUI frame only knows its own Moonbot lockup. src: - code: chrome/terminal_chrome.rs — brand_cluster + code: chrome/terminal_chrome.rs — header brand cluster - id: ws n: 2 title: