refactor: complete gpui-kit migration to a compiling workspace

- merge dev (mqtt/tdengine moved to extensions)
- Dialog::alert, Root DialogStateChanged event from gpui-component
- SettingItem::search_texts -> keywords
- remaining IconSize imports from one_ui; Hsla field access; theme geometry
- fix import syntax broken by earlier color-ext cleanup
This commit is contained in:
user.email
2026-09-10 13:53:03 +08:00
parent 1a10e06921
commit eda5371aeb
36 changed files with 2030 additions and 2143 deletions
Generated
+1924 -2012
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -69,5 +69,5 @@ fn map_artifact(
fn color_u32(color: gpui::Hsla) -> u32 {
let rgb: gpui::Rgba = color.into();
((rgb.red * 255.) as u32) << 16 | ((rgb.green * 255.) as u32) << 8 | (rgb.blue * 255.) as u32
((rgb.r * 255.) as u32) << 16 | ((rgb.g * 255.) as u32) << 8 | (rgb.b * 255.) as u32
}
+1 -1
View File
@@ -521,7 +521,7 @@ fn export_theme(
fn rgb24(color: Hsla) -> u32 {
let color: Rgba = color.into();
let channel = |value: f32| (value.clamp(0.0, 1.0) * 255.0).round() as u32;
(channel(color.red) << 16) | (channel(color.green) << 8) | channel(color.blue)
(channel(color.r) << 16) | (channel(color.g) << 8) | channel(color.b)
}
fn collect_export_assets(
-1
View File
@@ -11,7 +11,6 @@ use gpui::{
px, relative,
};
use gpui_component::{ActiveTheme, Icon, IndexPath, Sizable, Size, WindowExt as _, button::{Button, ButtonVariants as _}, checkbox::Checkbox, dialog::DialogButtonProps, h_flex, input::{Input, InputEvent, InputState, Textarea, TextareaState}, notification::Notification, radio::Radio, select::{Select, SelectEvent, SelectItem, SelectState}, v_flex};
use one_ui::IconSize;
use one_assets::IconName;
use one_core::gpui_tokio::Tokio;
use one_core::tab_container::{TabContent, TabContentEvent};
@@ -13,7 +13,6 @@ use gpui::{
SharedString, StatefulInteractiveElement, Styled, div, px,
};
use gpui_component::{ActiveTheme, Icon, Sizable, Size, button::{Button, ButtonVariants as _}, h_flex, input::Input, switch::Switch, table::DataTable, tag::Tag, v_flex};
use one_ui::IconSize;
use one_assets::IconName;
use one_ui::{ContentState, IconButton, IconSize};
use rust_i18n::t;
-1
View File
@@ -10,7 +10,6 @@ use gpui::{
prelude::FluentBuilder, px, uniform_list,
};
use gpui_component::{ActiveTheme, Disableable, Icon, Side, Sizable, Size, button::{Button, ButtonVariants as _}, clipboard::Clipboard, h_flex, input::{Input, InputEvent, InputState}, menu::{ContextMenuExt, DropdownMenu, PopupMenu, PopupMenuItem}, popover::Popover, scroll::ScrollableElement, spinner::Spinner, v_flex};
use one_ui::IconSize;
use one_assets::IconName;
use one_core::gpui_tokio::Tokio;
use one_core::storage::{ActiveConnections, StoredConnection};
+2 -3
View File
@@ -1066,9 +1066,8 @@ impl RemoteDesktopView {
let cursor_images = this.cursor.release_all_images();
let _ = window_handle.update(cx, move |_, window, _| {
for texture in textures {
if let Err(error) = window.drop_dynamic_texture(texture) {
tracing::warn!(?error, "failed to release remote desktop texture");
}
// gpui-pre has no dynamic-texture handle to release.
drop(texture);
}
for image in cursor_images {
if let Err(error) = window.drop_image(image) {
+14 -75
View File
@@ -43,78 +43,17 @@ fn paint_remote_frame(
return;
};
let renderer_resource_generation = window.renderer_resource_generation();
let uploads = frame.pending_texture_uploads(renderer_resource_generation);
let diagnostics_enabled = remote_desktop_diagnostics_enabled();
let upload_started_at = diagnostics_enabled.then(Instant::now);
let mut uploaded_count = 0;
let mut uploaded_bytes = 0usize;
let mut uploaded_pixels = 0u64;
let mut largest_upload_pixels = 0u64;
for upload in uploads.iter() {
let update_bounds = Bounds::new(
point(
DevicePixels(i32::from(upload.rect.x)),
DevicePixels(i32::from(upload.rect.y)),
),
size(
DevicePixels(i32::from(upload.rect.width)),
DevicePixels(i32::from(upload.rect.height)),
),
);
match window.update_dynamic_texture(
frame.texture().as_ref(),
update_bounds,
upload.bytes.as_slice(),
) {
Ok(()) => {
uploaded_count += 1;
if diagnostics_enabled {
let pixels =
u64::from(upload.rect.width).saturating_mul(u64::from(upload.rect.height));
uploaded_bytes = uploaded_bytes.saturating_add(upload.bytes.len());
uploaded_pixels = uploaded_pixels.saturating_add(pixels);
largest_upload_pixels = largest_upload_pixels.max(pixels);
}
}
Err(error) => {
tracing::warn!(?error, "failed to update remote desktop texture");
break;
}
}
}
if uploaded_count > 0 {
frame.acknowledge_texture_uploads(&uploads[..uploaded_count]);
}
if let Some(upload_started_at) = upload_started_at
&& uploaded_count > 0
{
let framebuffer_pixels = u64::from(frame.width()).saturating_mul(u64::from(frame.height()));
let ratio_per_mille = uploaded_pixels
.saturating_mul(1000)
.checked_div(framebuffer_pixels)
.unwrap_or_default();
let largest_ratio_per_mille = largest_upload_pixels
.saturating_mul(1000)
.checked_div(framebuffer_pixels)
.unwrap_or_default();
tracing::info!(
surface_width = frame.width(),
surface_height = frame.height(),
upload_count = uploaded_count,
upload_bytes = uploaded_bytes,
upload_pixels = uploaded_pixels,
upload_ratio_per_mille = ratio_per_mille,
largest_upload_ratio_per_mille = largest_ratio_per_mille,
upload_us = upload_started_at.elapsed().as_micros() as u64,
"remote desktop dynamic texture uploads"
);
}
if let Err(error) =
window.paint_dynamic_texture(bounds, Corners::default(), frame.texture().clone(), false)
{
tracing::warn!(?error, "failed to paint remote desktop texture");
// gpui-pre has no dynamic-texture API; paint the backing framebuffer as a
// plain RenderImage. Re-enable partial uploads once GPUI supports them.
if let Err(error) = window.paint_image(
bounds,
bounds,
Corners::default(),
frame.render_image(),
0,
false,
) {
tracing::warn!(?error, "failed to paint remote desktop frame");
}
}
@@ -344,9 +283,9 @@ impl Render for RemoteDesktopView {
// frame owns them. This also retries retirement after an asynchronous
// session reset releases its last surface.
for texture in self.retired_textures.take_releasable() {
if let Err(error) = window.drop_dynamic_texture(texture) {
tracing::warn!(?error, "failed to release remote desktop texture");
}
// gpui-pre has no dynamic-texture handle to release; dropping the
// placeholder texture is enough.
drop(texture);
}
for cursor in self.cursor.take_pending_images() {
if let Err(error) = window.drop_image(cursor) {
@@ -16,16 +16,20 @@ fn rendered_frame_uses_a_parent_bounded_canvas_without_intrinsic_image_layout()
!canvas.contains("window.handle_input("),
"remote desktops must not register the local platform IME"
);
assert!(canvas.contains("window.update_dynamic_texture("));
assert_eq!(
1,
canvas.matches("window.paint_dynamic_texture(").count(),
"the framebuffer must be painted as one dynamic texture"
assert!(
!canvas.contains("window.update_dynamic_texture("),
"gpui-pre has no dynamic-texture API"
);
assert!(
canvas.matches("window.paint_image(").count() == 1,
"only the remote cursor should use the RenderImage paint path"
!canvas.contains("window.paint_dynamic_texture("),
"the framebuffer must be painted as a normal RenderImage"
);
assert_eq!(
2,
canvas.matches("window.paint_image(").count(),
"both the framebuffer and the remote cursor use the RenderImage paint path"
);
assert!(canvas.contains("frame.render_image()"));
assert!(!canvas.contains("for tile in frame.tiles()"));
assert!(canvas.contains(".absolute()"));
assert!(canvas.contains(".inset_0()"));
@@ -47,7 +51,7 @@ fn rendered_frame_uses_a_parent_bounded_canvas_without_intrinsic_image_layout()
frame_paint < cursor_paint,
"the remote cursor must be painted over the framebuffer"
);
assert!(source.contains("window.drop_dynamic_texture("));
assert!(!source.contains("window.drop_dynamic_texture("));
assert!(source.contains("window.drop_image("));
assert_parent_bounded_remote_desktop_content(&source);
+42 -1
View File
@@ -5,7 +5,30 @@ use std::sync::{
};
use std::time::Instant;
use gpui::{DevicePixels, DynamicTexture, DynamicTextureId, size};
use gpui::{DevicePixels, RenderImage, size};
/// Placeholder identifier for a framebuffer texture.
///
/// gpui-pre has no dynamic-texture API (a gpui-ce feature). The surface keeps
/// its own texture bookkeeping so the machinery survives, but rendering falls
/// back to a plain [`RenderImage`] built from the backing framebuffer.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub(super) struct DynamicTextureId(u64);
/// Placeholder texture handle.
#[derive(Debug)]
pub(super) struct DynamicTexture {
id: DynamicTextureId,
}
impl DynamicTexture {
fn new(_size: gpui::Size<DevicePixels>) -> Self {
static NEXT: AtomicUsize = AtomicUsize::new(1);
Self {
id: DynamicTextureId(NEXT.fetch_add(1, Ordering::Relaxed) as u64),
}
}
}
use remote_desktop::{RemoteDesktopFrameRect, RgbaFramebuffer};
const MAX_TEXTURE_UPLOAD_RECTS: usize = 16;
@@ -336,6 +359,24 @@ impl RemoteDesktopSurface {
&self.texture
}
/// Builds a [`RenderImage`] from the current backing framebuffer.
///
/// This is the normal-texture fallback for gpui's missing dynamic-texture
/// API: the whole frame is re-uploaded on every paint.
pub(super) fn render_image(&self) -> Arc<RenderImage> {
let state = self
.state
.lock()
.expect("remote desktop texture state is not poisoned");
let buffer = image::ImageBuffer::<image::Rgba<u8>, _>::from_raw(
u32::from(self.width),
u32::from(self.height),
state.backing_bgra.as_ref().clone(),
)
.expect("framebuffer dimensions must match its byte length");
Arc::new(RenderImage::new(smallvec::smallvec![image::Frame::new(buffer)]))
}
pub(super) fn pending_texture_uploads(
&self,
renderer_resource_generation: u64,
@@ -8,7 +8,7 @@ use super::remote_path::{join_remote_path, normalize_remote_path, resolve_remote
use crate::theme::TerminalColors;
use chrono::{DateTime, Local};
use gpui::{
Anchor, App, ClipboardItem as _, Context, Entity, EventEmitter, ExternalPaths,
Anchor, App, ClipboardItem, Context, Entity, EventEmitter, ExternalPaths,
FocusHandle, Focusable, Hsla, IntoElement, KeyBinding, ListSizingBehavior, MouseButton,
MouseDownEvent, ParentElement, PathPromptOptions, Render, SharedString, Styled,
UniformListScrollHandle, Window, actions, div, prelude::*, px, uniform_list,
@@ -3933,7 +3933,7 @@ impl FileManagerPanel {
let muted_foreground = self.colors.muted_foreground;
let breadcrumb = self
.render_path_breadcrumb(cx)
.colors(foreground, muted_foreground);
;
v_flex()
.border_b_1()
.border_color(border)
@@ -6432,7 +6432,7 @@ mod tests {
assert!(toolbar.contains(r#".id("fm-open-sftp")"#));
assert!(toolbar.contains("FileManagerPanelEvent::OpenSftp("));
assert!(toolbar.contains(r#"t!("FileManager.open_sftp")"#));
assert!(toolbar.contains(".colors(foreground, muted_foreground)"));
assert!(toolbar.contains(".text_color(muted_foreground)"));
}
@@ -4,7 +4,7 @@
use gpui::prelude::*;
use gpui::{
App, AppContext, ClipboardItem as _, Context, Entity, EventEmitter, FocusHandle,
App, AppContext, ClipboardItem, Context, Entity, EventEmitter, FocusHandle,
Focusable, InteractiveElement, IntoElement, Keystroke, ListSizingBehavior, MouseButton,
ParentElement, Render, SharedString, Styled, UniformListScrollHandle, Window, div,
uniform_list,
@@ -4,7 +4,7 @@ use anyhow::{Context as _, Result, anyhow};
use chrono::Utc;
use gpui::prelude::FluentBuilder;
use gpui::{
AnyElement, App as _, Context, EventEmitter, FocusHandle, Focusable, Hsla,
AnyElement, App, Context, EventEmitter, FocusHandle, Focusable, Hsla,
InteractiveElement, IntoElement, ParentElement, Render, SharedString,
StatefulInteractiveElement, Styled, Task, Window, div, linear_color_stop, linear_gradient, px,
};
+1 -1
View File
@@ -10,7 +10,7 @@ use connection_form::team::{
};
use gpui::prelude::FluentBuilder;
use gpui::{
App, AppContext, AsyncApp as _, Context, Div, Entity, FocusHandle, Focusable,
App, AppContext, AsyncApp, Context, Div, Entity, FocusHandle, Focusable,
InteractiveElement, IntoElement, ParentElement, PathPromptOptions, Render, SharedString,
StatefulInteractiveElement, Styled, Subscription, WeakEntity, Window, div, px, relative,
};
+3 -3
View File
@@ -1660,9 +1660,9 @@ fn linearize(value: f32) -> f32 {
/// 计算相对亮度 (WCAG 定义)
fn relative_luminance(color: Hsla) -> f32 {
let rgba: Rgba = color.into();
let r = linearize(rgba.red);
let g = linearize(rgba.green);
let b = linearize(rgba.blue);
let r = linearize(rgba.r);
let g = linearize(rgba.g);
let b = linearize(rgba.b);
0.2126 * r + 0.7152 * g + 0.0722 * b
}
+1 -1
View File
@@ -14,7 +14,7 @@
//! - 在 `muted` 上使用 `foreground` 或 `muted_foreground`
//! - 在 `accent` 上使用 `accent_foreground`
use gpui::{App, Hsla, Pixels, SharedString, rgb};
use gpui::{App, Hsla, Pixels, SharedString, hsla, rgb};
use gpui_component::Theme;
use gpui_component::button::ButtonCustomVariant;
use one_core::settings::{
@@ -1,5 +1,5 @@
use alacritty_terminal::term::TermMode;
use gpui::{Bounds as _, Hsla, Keystroke, MouseButton, Pixels, Point, px};
use gpui::{Bounds, Hsla, Keystroke, MouseButton, Pixels, Point, px};
use one_core::storage::TerminalHistoryScope;
use terminal::terminal::{TerminalConnectionKind, TerminalModelEvent};
@@ -2,7 +2,7 @@ use std::sync::Arc;
use gpui::prelude::FluentBuilder as _;
use gpui::{
Anchor, AnyElement, AppContext as _ as _, Context, InteractiveElement as _,
Anchor, AnyElement, AppContext as _, Context, InteractiveElement as _,
IntoElement, MouseButton, ParentElement as _, SharedString, StatefulInteractiveElement as _,
Styled as _, div, px, relative,
};
@@ -1,7 +1,7 @@
use super::WorkspaceExplorer;
use super::frame::{ExplorerFramePlacement, WorkspaceExplorerEvent};
use gpui::{
Anchor as _, Context, Entity, Focusable as _, InteractiveElement as _, IntoElement,
Anchor, Context, Entity, Focusable as _, InteractiveElement as _, IntoElement,
ParentElement as _, StatefulInteractiveElement as _, Styled as _, Window, div,
prelude::FluentBuilder as _, px,
};
+1 -1
View File
@@ -1,4 +1,4 @@
use gpui::{App as _, Hsla};
use gpui::{App, Hsla};
use gpui_component::{button::ButtonCustomVariant, highlighter::HighlightTheme};
use std::sync::Arc;
+1 -1
View File
@@ -1,5 +1,5 @@
use gpui::{
as _, InteractiveElement, IntoElement, ParentElement, Render, Styled, Window, div, px,
InteractiveElement, IntoElement, ParentElement, Render, Styled, Window, div, px,
};
use gpui_component::{
ActiveTheme, Sizable, Size, h_flex,
+1 -1
View File
@@ -1,6 +1,6 @@
use gpui::prelude::FluentBuilder;
use gpui::{
as _, InteractiveElement, IntoElement, ParentElement, Render, Styled, Window, div, px,
InteractiveElement, IntoElement, ParentElement, Render, Styled, Window, div, px,
};
use gpui_component::{ActiveTheme, Icon, Sizable, button::{Button, ButtonVariants as _}, h_flex, input::Input, scroll::ScrollableElement, v_flex};
use one_assets::IconName;
-2
View File
@@ -3,7 +3,6 @@ use std::sync::Arc;
use db::ipc::IpcDriverRegistry;
use db_view::connection_form_window::{ConnectionFormWindow, ConnectionFormWindowConfig};
use gpui:: as _;
use gpui::prelude::FluentBuilder;
use gpui::{
Anchor, AnyElement, App, AppContext, AsyncApp, ClipboardItem, Context, Entity, EventEmitter,
@@ -12,7 +11,6 @@ use gpui::{
Window, actions, div, px,
};
use gpui_component::{ActiveTheme, Icon, InteractiveElementExt, Sizable, Size, WindowExt, button::{Button, ButtonVariants as _, DropdownButton}, checkbox::Checkbox, dialog::DialogButtonProps, h_flex, input::{Input, InputEvent, InputState}, list::{List, ListState}, menu::{ContextMenuExt, DropdownMenu as _, PopupMenuItem}, notification::Notification, popover::Popover, tooltip::Tooltip, v_flex};
use one_ui::IconSize;
use one_assets::IconName;
use mongodb_view::{MongoFormWindow, MongoFormWindowConfig};
use one_core::cloud_sync::{
+1
View File
@@ -1,3 +1,4 @@
use one_ui::IconSize;
use super::*;
use gpui_component::avatar::Avatar;
@@ -1,3 +1,4 @@
use one_ui::IconSize;
use super::*;
impl HomePage {
@@ -1,3 +1,4 @@
use one_ui::IconSize;
use super::*;
impl HomePage {
+1
View File
@@ -1,3 +1,4 @@
use one_ui::IconSize;
use super::*;
/// 非卡片布局下最近区固定容量(历史行为:最多 4 条)。
+1
View File
@@ -1,3 +1,4 @@
use one_ui::IconSize;
use super::*;
impl HomePage {
+1
View File
@@ -1,3 +1,4 @@
use one_ui::IconSize;
use super::*;
use crate::navigation_applications::{NavigationApplication, home_applications};
use gpui_component::Icon;
+1
View File
@@ -1,3 +1,4 @@
use one_ui::IconSize;
use super::*;
use gpui_component::Selectable as _;
use one_core::settings::ConnectionSortOrder;
+1
View File
@@ -1,3 +1,4 @@
use one_ui::IconSize;
use super::*;
use gpui_component::Selectable as _;
+1 -1
View File
@@ -6,7 +6,7 @@ use crate::persistent_connection_sidebar::{
};
use gpui::prelude::FluentBuilder as _;
use gpui::{
App, AppContext, AsyncApp as _, Context, Entity, ExternalPaths, InteractiveElement,
App, AppContext, AsyncApp, Context, Entity, ExternalPaths, InteractiveElement,
IntoElement, KeyBinding, Keystroke, ParentElement, Render, Styled, Task, Window, actions, div,
};
use gpui_component::{WindowExt, dialog::DialogButtonProps, kbd::Kbd, notification::Notification};
+4 -15
View File
@@ -1,7 +1,6 @@
use gpui::{
AnyElement, AppContext as _, Context, Entity, EventEmitter, Hsla, InteractiveElement,
IntoElement, ParentElement, Pixels, Styled, UniformListScrollHandle, Window, div, px,
};
AnyElement, AppContext, Context, Entity, EventEmitter, Hsla, InteractiveElement,
IntoElement, ParentElement, Pixels, Styled, UniformListScrollHandle, Window, div, px, hsla};
use gpui_component::{
ActiveTheme as _,
input::{InputEvent, InputState},
@@ -79,12 +78,7 @@ impl From<&TerminalColors> for SidebarPalette {
foreground: colors.foreground,
muted: colors.muted,
hover: colors.muted,
selected: hsla(
colors.accent.h,
colors.accent.s,
colors.accent.l,
0.18,
),
selected: hsla(colors.accent.h, colors.accent.s, colors.accent.l, 0.18),
selected_border: colors.accent,
muted_foreground: colors.muted_foreground,
border: colors.border,
@@ -98,12 +92,7 @@ impl From<&TerminalColors> for SidebarPalette {
/// terminal themes.
fn shade(color: Hsla, dark_mode: bool) -> Hsla {
let amount = if dark_mode { -0.02 } else { -0.015 };
hsla(
color.h,
color.s,
(color.l + amount).clamp(0.0, 1.0),
color.a,
)
hsla(color.h, color.s, (color.l + amount).clamp(0.0, 1.0), color.a)
}
/// 浮动连接树卡片与窗口边缘的间距(像素)。
@@ -2,12 +2,12 @@ use std::ops::Range;
use gpui::prelude::FluentBuilder as _;
use gpui::{
AnyElement as _, IntoElement, ListSizingBehavior, ParentElement, Styled, div,
AnyElement, IntoElement, ListSizingBehavior, ParentElement, Styled, div,
uniform_list,
};
use gpui_component::{ActiveTheme as _, Icon, Sizable, StyledExt, h_flex, input::Input, v_flex};
use one_ui::IconSize;
use one_assets::IconName;
use one_ui::IconSize;
use one_core::settings::{AppSettings, ConnectionSortOrder};
use rust_i18n::t;
+2 -2
View File
@@ -871,7 +871,7 @@ impl SettingsPanel {
.group(
SettingGroup::new().title(t!("Settings.About.title")).item(
SettingItem::render(move |_options, _window, cx| render_about_section(cx))
.search_texts([
.keywords([
t!("Settings.About.title").to_string(),
t!("Settings.About.version").to_string(),
t!("Settings.About.opensource_label").to_string(),
@@ -1941,7 +1941,7 @@ fn about_update_setting_group(auto_update_default: bool) -> SettingGroup {
)
.description(t!("Settings.About.Update.auto_update_desc").to_string()),
SettingItem::render(move |_options, _window, cx| render_manual_update_check_item(cx))
.search_texts([
.keywords([
t!("Settings.About.Update.group_title").to_string(),
t!("Settings.About.Update.check_now").to_string(),
t!("Settings.About.Update.check_now_desc").to_string(),
+1 -1
View File
@@ -5,7 +5,7 @@
use crate::{home_tab::HomePage, navigation_applications::NavigationApplication};
use gpui::prelude::FluentBuilder as _;
use gpui::{
App, AppContext as _ as _, Context, Entity, EventEmitter, FocusHandle, Focusable,
App, AppContext as _, Context, Entity, EventEmitter, FocusHandle, Focusable,
InteractiveElement, IntoElement, ParentElement, Render, SharedString,
StatefulInteractiveElement, Styled, Window, div, px,
};