Merge commit '01a36a5a204a3212d9fe86b7d6059aa35a1280d2' into HEAD
This commit is contained in:
commit
9a8842407a
9 files changed
+44
-24
No files matched your search
@@ -42,6 +42,7 @@ pub(crate) const fn effective_cursor_blink(configured: Option<bool>) -> bool {
|
||||
pub struct Settings {
|
||||
/// 已解析的界面语言。GPUI 组件只读这个内存全局,渲染路径不得重复读盘。
|
||||
pub ui_language: UiLanguage,
|
||||
pub panel_resize: bool,
|
||||
pub font_family: String,
|
||||
pub font_cjk: Option<[gpui::Font; 4]>,
|
||||
pub font_bold_family: String,
|
||||
@@ -117,6 +118,10 @@ pub(crate) fn ui_language(cx: &App) -> UiLanguage {
|
||||
cx.try_global::<Settings>().map(|settings| settings.ui_language).unwrap_or(UiLanguage::EnUs)
|
||||
}
|
||||
|
||||
pub(crate) fn panel_resize(cx: &App) -> bool {
|
||||
cx.try_global::<Settings>().is_some_and(|settings| settings.panel_resize)
|
||||
}
|
||||
|
||||
pub(crate) fn ai_toasts_enabled(cx: &App) -> bool {
|
||||
cx.try_global::<Settings>().is_none_or(|settings| settings.ai_toasts)
|
||||
}
|
||||
@@ -248,6 +253,7 @@ impl Settings {
|
||||
|
||||
Settings {
|
||||
ui_language,
|
||||
panel_resize: runtime.panel_resize,
|
||||
font_bold_family: secondary(&raw.font.bold),
|
||||
font_italic_family: secondary(&raw.font.italic),
|
||||
font_bold_italic_family: secondary(&raw.font.bold_italic),
|
||||
@@ -792,6 +798,25 @@ mod tests {
|
||||
assert_eq!(resolve_ui_language(LanguagePref::EnUs), UiLanguage::EnUs);
|
||||
}
|
||||
|
||||
#[cfg(feature = "gpui-test-support")]
|
||||
#[gpui::test]
|
||||
fn render_preferences_read_current_settings(cx: &mut gpui::TestAppContext) {
|
||||
cx.update(|cx| {
|
||||
for (theme, language, panel_resize) in [
|
||||
(ThemeName::Nord, UiLanguage::ZhCn, false),
|
||||
(ThemeName::Paper, UiLanguage::EnUs, true),
|
||||
] {
|
||||
let mut runtime = RuntimeSettings::from_raw(&RawSettings::default());
|
||||
runtime.panel_resize = panel_resize;
|
||||
let mut settings = Settings::load_with_runtime(theme, runtime);
|
||||
settings.ui_language = language;
|
||||
cx.set_global(settings);
|
||||
assert_eq!(super::ui_language(cx), language);
|
||||
assert_eq!(super::panel_resize(cx), panel_resize);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn system_theme_owns_terminal_background_while_following_system() {
|
||||
let custom = Some([0x0f, 0x11, 0x1a]);
|
||||
|
||||
@@ -72,12 +72,6 @@ mod connection_state_tests {
|
||||
}
|
||||
}
|
||||
|
||||
/// UiLanguage 由设置折算(两壳同源)。
|
||||
pub(super) fn language() -> crate::display::UiLanguage {
|
||||
let runtime = nebula_settings::RuntimeSettings::load();
|
||||
crate::display::LanguagePreference::from(runtime.language).resolved()
|
||||
}
|
||||
|
||||
fn hsla_from_rgba(r: u8, g: u8, b: u8) -> Hsla {
|
||||
let (rf, gf, bf) = (f32::from(r) / 255.0, f32::from(g) / 255.0, f32::from(b) / 255.0);
|
||||
let max = rf.max(gf).max(bf);
|
||||
@@ -288,7 +282,7 @@ pub(super) fn overlay(
|
||||
use gpui::prelude::FluentBuilder as _;
|
||||
|
||||
let theme = cx.theme();
|
||||
let lang = language();
|
||||
let lang = crate::gpui_shell::config::ui_language(cx);
|
||||
// chrome 文本锚定配置字号(旧壳 ui_font 合同),不跟终端缩放。
|
||||
let ui_px = cx
|
||||
.try_global::<crate::gpui_shell::config::Settings>()
|
||||
|
||||
@@ -316,7 +316,7 @@ impl NebulaWorkspace {
|
||||
let editing_path = self.file_tree_path.is_some();
|
||||
let theme = cx.theme();
|
||||
let muted = theme.muted_foreground;
|
||||
let language = super::workspace_ui_language();
|
||||
let language = crate::gpui_shell::config::ui_language(cx);
|
||||
let search_options = self.side_panel.file_search_options();
|
||||
let search_active = !self.side_panel.search.trim().is_empty();
|
||||
let search_pending = self.side_panel.file_search_pending();
|
||||
@@ -428,7 +428,7 @@ impl NebulaWorkspace {
|
||||
});
|
||||
let root_dir = self.side_panel.root().map(std::path::Path::to_path_buf);
|
||||
let row_count = self.side_panel.file_rows().len();
|
||||
let empty = self.file_tree_empty_state();
|
||||
let empty = self.file_tree_empty_state(cx);
|
||||
let scroll_handle = self.file_tree_scroll.clone();
|
||||
|
||||
v_flex()
|
||||
@@ -611,13 +611,13 @@ impl NebulaWorkspace {
|
||||
/// side_panel.rs:3112-3131 同源。判据也照旧壳:`..` 不算内容,只剩它时这个
|
||||
/// 目录仍然是空的;"读不到"和"确实是空的"必须分开说,否则用户没法判断该
|
||||
/// 重试还是该换目录。
|
||||
fn file_tree_empty_state(&self) -> Option<crate::ux::EmptyState> {
|
||||
fn file_tree_empty_state(&self, cx: &gpui::App) -> Option<crate::ux::EmptyState> {
|
||||
if self.side_panel.file_rows().iter().any(|row| !row.is_parent) {
|
||||
return None;
|
||||
}
|
||||
if !self.side_panel.search.trim().is_empty() {
|
||||
use crate::i18n::Message;
|
||||
let language = super::workspace_ui_language();
|
||||
let language = crate::gpui_shell::config::ui_language(cx);
|
||||
return Some(if let Some(error) = self.side_panel.file_search_error() {
|
||||
crate::ux::EmptyState::new(
|
||||
language.text(Message::FilesSearchFailed),
|
||||
|
||||
@@ -210,7 +210,7 @@ impl NebulaWorkspace {
|
||||
if self.file_tree_path.as_ref().is_some_and(|edit| edit.origin != origin) {
|
||||
self.file_tree_path = None;
|
||||
}
|
||||
let language = super::super::workspace_ui_language();
|
||||
let language = crate::gpui_shell::config::ui_language(cx);
|
||||
let Some(edit) = self.file_tree_path.as_ref() else {
|
||||
let value = origin
|
||||
.wsl
|
||||
|
||||
@@ -68,7 +68,7 @@ impl NebulaWorkspace {
|
||||
.get(self.active)
|
||||
.and_then(WorkspaceTab::focused_view)
|
||||
.is_some_and(|view| view.read(cx).working_directory().is_some());
|
||||
let language = workspace_ui_language();
|
||||
let language = crate::gpui_shell::config::ui_language(cx);
|
||||
let rows = self.palette_override.clone().unwrap_or_else(|| {
|
||||
let mut rows: Vec<WorkspacePaletteRow> = crate::display::command_palette::catalog()
|
||||
.iter()
|
||||
@@ -176,7 +176,7 @@ impl NebulaWorkspace {
|
||||
let muted = theme.muted_foreground;
|
||||
let overlay = theme.overlay;
|
||||
let mono_family = theme.mono_font_family.clone();
|
||||
let language = workspace_ui_language();
|
||||
let language = crate::gpui_shell::config::ui_language(cx);
|
||||
let palette_filters = if self.shell_picker_open {
|
||||
Some((
|
||||
WorkspacePaletteFilter::Launcher(self.launcher_filter),
|
||||
|
||||
@@ -458,6 +458,7 @@ impl NebulaWorkspace {
|
||||
let muted = theme.muted_foreground;
|
||||
let foreground = theme.foreground;
|
||||
let drop_highlight = theme.accent.opacity(0.18);
|
||||
let language = crate::gpui_shell::config::ui_language(cx);
|
||||
let rows = self.remote_rows();
|
||||
let row_count = rows.len();
|
||||
let destination = self.remote_browser.destination.clone();
|
||||
@@ -467,7 +468,7 @@ impl NebulaWorkspace {
|
||||
self.remote_browser.path.clone()
|
||||
};
|
||||
let at_root = self.remote_browser.path == "/" || self.remote_browser.path.is_empty();
|
||||
let notice = self.remote_notice();
|
||||
let notice = self.remote_notice(language);
|
||||
|
||||
v_flex()
|
||||
.h_full()
|
||||
@@ -488,7 +489,7 @@ impl NebulaWorkspace {
|
||||
this.drop_upload_paths(vec![file.local_path.clone()], None, window, cx);
|
||||
}))
|
||||
.child(div().px(px(TEXT_INSET)).text_xs().text_color(muted)
|
||||
.child(workspace_ui_language().text(if crate::platform::file_drag::supported() {
|
||||
.child(language.text(if crate::platform::file_drag::supported() {
|
||||
crate::i18n::Message::TransferDragHint
|
||||
} else { crate::i18n::Message::TransferUploadHint })))
|
||||
// 主机名单独一行:远端浏览器最危险的误操作是"以为在另一台机器上",
|
||||
@@ -849,14 +850,12 @@ impl NebulaWorkspace {
|
||||
///
|
||||
/// 三种情况必须分开说。"读不到"和"是空的"混为一谈,用户就不知道该重试
|
||||
/// 还是该换目录——这是空态里最常见也最误导人的一处偷懒。
|
||||
fn remote_notice(&self) -> Option<String> {
|
||||
fn remote_notice(&self, language: crate::display::UiLanguage) -> Option<String> {
|
||||
if let Some(error) = self.remote_browser.error.as_deref() {
|
||||
return Some(format!("{error}(点右上角重新读取)"));
|
||||
}
|
||||
if self.remote_browser.preflighting {
|
||||
return Some(
|
||||
workspace_ui_language().text(crate::i18n::Message::TransferChecking).to_owned(),
|
||||
);
|
||||
return Some(language.text(crate::i18n::Message::TransferChecking).to_owned());
|
||||
}
|
||||
if let Some(snapshot) = self.remote_transfer_snapshot()
|
||||
&& snapshot.phase == SftpPhase::Working
|
||||
@@ -868,7 +867,7 @@ impl NebulaWorkspace {
|
||||
return Some("正在读取远端目录…".to_owned());
|
||||
}
|
||||
if let Some(outcome) = self.remote_browser.last_outcome {
|
||||
return Some(workspace_ui_language().text(outcome).to_owned());
|
||||
return Some(language.text(outcome).to_owned());
|
||||
}
|
||||
self.remote_browser.entries.is_empty().then(|| "此目录为空。".to_owned())
|
||||
}
|
||||
|
||||
@@ -122,7 +122,9 @@ impl NebulaWorkspace {
|
||||
return self.tab_presentation(index, cx, dark);
|
||||
}
|
||||
TabPresentation {
|
||||
title: super::workspace_ui_language().text(crate::i18n::Message::CommonSettings).into(),
|
||||
title: crate::gpui_shell::config::ui_language(cx)
|
||||
.text(crate::i18n::Message::CommonSettings)
|
||||
.into(),
|
||||
tooltip: None,
|
||||
is_settings: true,
|
||||
activity: SidebarActivity::Idle,
|
||||
|
||||
@@ -61,7 +61,7 @@ impl NebulaWorkspace {
|
||||
|| self.settings_open
|
||||
|| self.reader_focus_active(cx)
|
||||
|| self.tabs_position == nebula_settings::TabsPositionName::Top
|
||||
|| !nebula_settings::RuntimeSettings::load().panel_resize
|
||||
|| !crate::gpui_shell::config::panel_resize(cx)
|
||||
{
|
||||
return None;
|
||||
}
|
||||
|
||||
@@ -195,7 +195,7 @@ pub(crate) fn open_update_dialog(
|
||||
|
||||
let dialog_result = result.clone();
|
||||
window.open_dialog(cx, move |dialog, window, cx| {
|
||||
let language = workspace_ui_language();
|
||||
let language = crate::gpui_shell::config::ui_language(cx);
|
||||
let title: SharedString = language.pick("Pebrel 更新", "Pebrel Update").into();
|
||||
let current_label: SharedString = language.pick("当前版本", "Current").into();
|
||||
let latest_label: SharedString = language.pick("最新版本", "Latest").into();
|
||||
|
||||
Reference in new issue
Block a user