refactor(desktop): isolate presentation imports

This commit is contained in:
Kang
2026-07-28 18:45:06 +08:00
parent 44701a3324
commit a117fe91e2
19 changed files with 154 additions and 62 deletions
@@ -1,4 +1,17 @@
use super::*;
use std::path::PathBuf;
use std::time::{SystemTime, UNIX_EPOCH};
use gpui::rgb;
use nyaterm_core::{
AppSettingsSummary, CloudSyncError, CloudSyncHistoryEntry, CloudSyncSettings, RiskLevel,
TunnelConfig,
};
use nyaterm_transport::{
SessionKind, SshSessionConfig, SshTunnelMode, TelnetEnterMode, safe_recording_name,
};
use crate::features::AiAgentStepStatus;
use crate::theme::ThemePalette;
pub(in crate::features) fn ai_agent_step_status_style(
status: AiAgentStepStatus,
@@ -394,7 +394,10 @@ pub(in crate::features) fn parse_markdown_blocks(content: &str) -> Vec<MarkdownB
#[cfg(test)]
mod markdown_tests {
use super::*;
use super::{
InlineMdStyle, MarkdownBlock, extract_think_content, parse_inline_markdown,
parse_markdown_blocks,
};
#[test]
fn parse_table_and_inline() {
@@ -1,26 +1,27 @@
use crate::theme::ThemePalette;
use gpui::rgb;
use nyaterm_core::{
AppSettingsSummary, CloudSyncError, CloudSyncHistoryEntry, CloudSyncSettings, RiskLevel,
TunnelConfig,
};
use nyaterm_transport::{
SessionKind, SshSessionConfig, SshTunnelMode, TelnetEnterMode, safe_recording_name,
};
use std::path::PathBuf;
use std::time::{SystemTime, UNIX_EPOCH};
use super::{AiAgentStepStatus, NyaTermApp};
use super::NyaTermApp;
mod labels;
pub(in crate::features) use labels::*;
pub(in crate::features) use labels::{
ai_agent_step_status_style, cloud_sync_history_status, cloud_sync_history_summary,
cloud_sync_kind_text_color, cloud_sync_status_dot_color, cloud_sync_status_text_color,
compact_id, configured_cloud_sync_provider, docker_compose_project_key, docker_state_color,
docker_state_label, docker_state_rank, download_file_name_from_remote_path,
format_cloud_provider, format_duration_ms, format_history_timestamp_ms, format_last_used_ms,
format_permissions_octal, format_rate, format_terminal_line_timestamp_ms, format_uptime,
non_empty_string, none_if_blank, normalize_startup_command, parse_telnet_enter_mode,
recent_terminal_output, recording_file_path, risk_label, session_kind_label, short_id,
split_shell_args, ssh_multiplex_key, status_label, trim_terminal_output_to, tunnel_endpoint,
tunnel_mode, tunnel_name,
};
mod ai_history;
pub(in crate::features) use ai_history::*;
pub(in crate::features) use ai_history::group_ai_sessions_by_date;
mod markdown;
pub(in crate::features) use markdown::*;
pub(in crate::features) use markdown::{
InlineMdStyle, MarkdownBlock, extract_think_content, parse_inline_markdown,
parse_markdown_blocks,
};
impl NyaTermApp {
pub(in crate::features) fn tr(&self, key: &'static str) -> &'static str {
@@ -72,7 +72,7 @@ pub(super) fn resolve_alias(normalized: &str) -> &str {
#[cfg(test)]
mod tests {
use super::*;
use super::{CONNECTION_ICON_ALIASES, normalize_connection_icon_key, resolve_alias};
#[test]
fn normalization_strips_the_svg_suffix_case_insensitively() {
@@ -242,7 +242,10 @@ pub(in crate::features) fn default_connection_icon_for_kind(kind: &str) -> IconD
mod tests {
use super::super::IconPaint;
use super::super::aliases::CONNECTION_ICON_ALIASES;
use super::*;
use super::{
CONNECTION_ICON_OPTIONS, LINUX_ICONS, SERVER_ICONS, SYSTEM_ICONS,
default_connection_icon_for_kind, lookup, resolve_connection_icon,
};
/// Every key the GPUI picker has ever offered. Stored connections carry these
/// verbatim, so none may stop resolving.
@@ -117,7 +117,7 @@ pub(in crate::features) fn file_entry_icon(
#[cfg(test)]
mod tests {
use super::*;
use super::{IconDef, ThemePalette, file_entry_icon};
fn palette() -> ThemePalette {
crate::theme::theme_palette("github-dark")
@@ -127,7 +127,7 @@ fn legible_on(color: u32, palette: ThemePalette) -> u32 {
#[cfg(test)]
mod tests {
use super::*;
use super::{IconDef, ThemePalette, legible_on, relative_luminance};
fn dark() -> ThemePalette {
crate::theme::theme_palette("github-dark")
@@ -50,7 +50,7 @@ pub(in crate::features) fn quick_command_icon(icon_tag: &str) -> Option<IconDef>
#[cfg(test)]
mod tests {
use super::super::IconPaint;
use super::*;
use super::{BRAND_ICONS, GENERIC_ICONS, QUICK_COMMAND_ICON_OPTIONS, quick_command_icon};
/// Tags the GPUI picker has offered since the migration. Saved commands carry
/// them, so none may stop resolving.
@@ -124,7 +124,7 @@ pub(in crate::features) fn infer_connection_icon_key_from_remote_system(
mod tests {
use super::super::connection::resolve_connection_icon;
use super::super::{IconPaint, connection::default_connection_icon_for_kind};
use super::*;
use super::{DISTRO_MATCHES, infer_connection_icon_key_from_remote_system};
fn infer(os: &str) -> Option<&'static str> {
infer_connection_icon_key_from_remote_system(os, "x86_64")
@@ -58,7 +58,7 @@ pub(in crate::features) fn search_engine_icon(
#[cfg(test)]
mod tests {
use super::*;
use super::{SEARCH_ENGINE_ICON_IDS, ThemePalette, search_engine_icon};
fn palette() -> ThemePalette {
crate::theme::theme_palette("github-dark")
+17 -2
View File
@@ -57,7 +57,16 @@ pub(in crate::features) use connections::{
ConnectionDragKind, ConnectionDragPayload, ConnectionDragPreview, ConnectionDropPosition,
ConnectionDropTarget, ConnectionEditorToggle, ConnectionFeatureFocus, ConnectionFeatureState,
};
pub(in crate::features) use formatting::*;
pub(in crate::features) use formatting::{
cloud_sync_history_status, cloud_sync_status_dot_color, cloud_sync_status_text_color,
compact_id, configured_cloud_sync_provider, docker_compose_project_key, docker_state_color,
docker_state_label, docker_state_rank, download_file_name_from_remote_path,
format_cloud_provider, format_duration_ms, format_history_timestamp_ms, format_last_used_ms,
format_permissions_octal, format_rate, format_terminal_line_timestamp_ms, format_uptime,
non_empty_string, none_if_blank, normalize_startup_command, recent_terminal_output,
session_kind_label, short_id, status_label, trim_terminal_output_to, tunnel_endpoint,
tunnel_mode, tunnel_name,
};
pub(in crate::features) use icons::{
CONNECTION_ICON_OPTIONS, DEFAULT_CONNECTION_ICON, IconDef, QUICK_COMMAND_ICON_OPTIONS,
SEARCH_ENGINE_ICON_IDS, file_entry_icon, infer_connection_icon_key_from_remote_system,
@@ -103,7 +112,13 @@ pub(in crate::features) use transfers::{
TransferFeatureFocus, TransferFeatureState, duplicate_decision_label, duplicate_policy_label,
format_file_size, transfer_job_title, transfer_status_label,
};
pub(in crate::features) use view_widgets::*;
pub(in crate::features) use view_widgets::{
activity_icon, child_window_header, child_window_titlebar, cloud_sync_history_row, color_icon,
connection_type_icon, dialog_action_button, empty_workspace_action, logo_mark, metric,
modal_close_icon_button, modal_dialog_footer_localized, modal_dialog_footer_localized_danger,
modal_dialog_shell, mono_icon, nyaterm_logo_mark, panel_header_with_actions, service_status,
stats_progress_bar, themed_icon, transfer_entry_icon, window_control_button,
};
const LEGACY_ROOT: &str = "./temp/nyaterm-tauri";
pub(crate) const INITIAL_TERMINAL_BANNER: &str = "$ nyaterm --native\nGPUI shell initialized.\nStart a local terminal or open a saved connection.\n";
@@ -1,5 +1,10 @@
use super::*;
use gpui::AnyElement;
use gpui::{
AnyElement, App, ClickEvent, FontWeight, IntoElement, SharedString, TitlebarOptions, Window,
WindowControlArea, div, prelude::*, px, rgb, rgba, svg,
};
use crate::theme::ThemePalette;
use crate::widgets::small_button;
pub(in crate::features) fn logo_mark(palette: ThemePalette) -> impl IntoElement {
div()
@@ -1,4 +1,8 @@
use super::*;
use gpui::{
App, ClickEvent, FontWeight, IntoElement, SharedString, Window, div, prelude::*, px, rgb, svg,
};
use crate::theme::ThemePalette;
/// Tauri EmptyWorkspaceState row: action label (primary) + shortcut key chips.
pub(in crate::features) fn empty_workspace_action(
@@ -1,4 +1,12 @@
use super::*;
use gpui::{
FontStyle, FontWeight, HighlightStyle, IntoElement, SharedString, StrikethroughStyle,
StyledText, UnderlineStyle, div, prelude::*, px, rgb,
};
use crate::features::formatting::{
InlineMdStyle, MarkdownBlock, parse_inline_markdown, parse_markdown_blocks,
};
use crate::theme::ThemePalette;
/// Lightweight GFM markdown renderer for AI transcript (Tauri MarkdownContent parity).
pub(in crate::features) fn markdown_content_view(
@@ -1,37 +1,26 @@
use gpui::{
App, ClickEvent, FontStyle, FontWeight, HighlightStyle, IntoElement, SharedString,
StrikethroughStyle, StyledText, TitlebarOptions, UnderlineStyle, Window, WindowControlArea,
div, prelude::*, px, rgb, rgba, svg,
};
use nyaterm_core::{
CloudSyncHistoryEntry, ConnectionType, NativeServiceStatus, SavedConnection, TunnelConfig,
truncate_preview,
};
use nyaterm_transport::{DockerContainer, NetworkInfo, RemoteProcess};
use crate::models::WorkspaceSplitDirection;
use crate::widgets::{mode_button, small_button, status_pill};
use super::{
InlineMdStyle, MarkdownBlock, ThemePalette, cloud_sync_history_summary,
cloud_sync_kind_text_color, cloud_sync_status_dot_color, cloud_sync_status_text_color,
compact_id, docker_state_color, docker_state_label, format_history_timestamp_ms, format_rate,
parse_inline_markdown, parse_markdown_blocks, tunnel_endpoint, tunnel_name,
};
mod chrome;
pub(in crate::features) use chrome::*;
pub(in crate::features) use chrome::{
child_window_header, child_window_titlebar, dialog_action_button, logo_mark,
modal_close_icon_button, modal_dialog_footer_localized, modal_dialog_footer_localized_danger,
modal_dialog_shell, panel_header_with_actions, window_control_button,
};
mod inspector_widgets;
pub(in crate::features) use inspector_widgets::*;
pub(in crate::features) use inspector_widgets::{
empty_workspace_action, tab_action_button, tab_menu_item, tab_menu_item_enabled,
tab_menu_separator,
};
mod stats;
pub(in crate::features) use stats::*;
pub(in crate::features) use stats::{metric, service_status, stats_progress_bar};
mod rows;
pub(in crate::features) use rows::*;
pub(in crate::features) use rows::cloud_sync_history_row;
mod icons;
pub(in crate::features) use icons::*;
pub(in crate::features) use icons::{
activity_icon, color_icon, connection_type_icon, mono_icon, nyaterm_logo_mark, themed_icon,
transfer_entry_icon,
};
mod markdown;
pub(in crate::features) use markdown::*;
pub(in crate::features) use markdown::markdown_content_view;
@@ -1,4 +1,13 @@
use super::*;
use gpui::{
App, ClickEvent, FontWeight, IntoElement, SharedString, Window, div, prelude::*, px, rgb,
};
use nyaterm_core::{CloudSyncHistoryEntry, truncate_preview};
use crate::features::formatting::{
cloud_sync_history_summary, cloud_sync_kind_text_color, cloud_sync_status_dot_color,
cloud_sync_status_text_color, compact_id, format_history_timestamp_ms,
};
use crate::theme::ThemePalette;
pub(in crate::features) fn cloud_sync_history_row(
palette: ThemePalette,
@@ -1,4 +1,8 @@
use super::*;
use gpui::{FontWeight, IntoElement, SharedString, div, prelude::*, px, rgb};
use nyaterm_core::NativeServiceStatus;
use crate::theme::ThemePalette;
use crate::widgets::status_pill;
pub(in crate::features) fn stats_progress_bar(
palette: ThemePalette,
+13 -1
View File
@@ -12,7 +12,7 @@ Last updated from the working tree on 2026-07-28.
| `NyaTermApp` fields | 261 | Counted from `features/app_state/mod.rs`; down from 585, still transitional. |
| `impl NyaTermApp` blocks | 239 | Spread across 234 files under `crates/nyaterm-desktop/src`. |
| `#[path = "..."]` declarations in desktop | 0 | Cleared. Every directory is a real module; the boundary script fails on any new occurrence. |
| `use super::*` imports in desktop | 144 | Includes indented test-module imports; historical migration debt, do not add new occurrences. |
| `use super::*` imports in desktop | 130 | Includes indented test-module imports; historical migration debt, do not add new occurrences. |
| `features/prelude.rs` rough exported-token count | 179 | Still a broad shared prelude; two hundred sixty-six low-frequency GPUI/transport/core/http/model/helper/widget exports are now explicit imports. |
| Entity Store structs | 4 | `Runtime`, `WindowRuntime`, `StartupRestore`, `Overlay`. Each owns state the app does not. |
| Snapshot structs | 0 | Cleared. No store is a projection of `NyaTermApp` any more. |
@@ -497,6 +497,18 @@ these as staged extraction candidates, not as formatting-only refactor targets.
imports and prevents those prelude exports from returning. SSH host-key and
credential prompting, OTP lookup, credential autofill, session startup and
restore, recording, and TRZSZ/ZMODEM behavior are unchanged.
- The complete 18-module presentation-support set under `features/icons`,
`features/formatting` and `features/view_widgets` is now free of
`use super::*` imports. Icon compatibility tests, markdown parser tests and
GPUI view helpers name their exact data, theme, formatting, widget and GPUI
dependencies. The formatting, view-widget and top-level feature façades also
use named re-exports instead of glob re-exports; twenty-three low-frequency
aliases no longer flatten into `crate::features` and remain available only
through their owning module paths. The architecture script governs all three
trees and prevents their module-entry glob re-exports from returning.
Persisted connection/quick-command icon keys, icon resolution order, markdown
parsing and rendering, cloud-sync history rows, and shared widget behavior
are unchanged.
- `connection_runtime/helpers.rs` no longer depends on the connection runtime
wildcard import; its GPUI, app, model, and core dependencies are explicit.
- `connection_runtime/actions.rs` no longer depends on the connection runtime
+26
View File
@@ -167,6 +167,11 @@ check_no_matches \
crates/nyaterm-desktop/src/features/panels/mod.rs \
crates/nyaterm-desktop/src/features/panels/tab_actions_overlay/mod.rs
check_no_matches \
"presentation support module entry points must use named re-exports" \
'^[[:space:]]*pub\(in crate::features\)[[:space:]]+use[[:space:]]+(formatting|view_widgets|labels|ai_history|markdown|chrome|inspector_widgets|stats|rows|icons)::\*;' \
crates/nyaterm-desktop/src/features
check_no_matches \
"cloud sync HTTP backend helpers must stay out of features/prelude.rs" \
'(^|[,{[:space:]])(NativeAliyunDriveRemote|NativeGoogleDriveRemote|NativeOneDriveRemote|NativeS3Remote|NativeSnippetHttpClient|NativeWebdavRemote|run_github_gist_device_flow)([},[:space:]]|$)' \
@@ -672,6 +677,17 @@ declare -A SUPER_BASELINE=(
[crates/nyaterm-desktop/src/features/settings/settings_runtime/recording_transfer.rs]=0
[crates/nyaterm-desktop/src/features/settings/settings_runtime/search_engines.rs]=0
[crates/nyaterm-desktop/src/features/settings/settings_runtime/terminal_remote.rs]=0
[crates/nyaterm-desktop/src/features/formatting/ai_history.rs]=0
[crates/nyaterm-desktop/src/features/formatting/labels.rs]=0
[crates/nyaterm-desktop/src/features/formatting/markdown.rs]=0
[crates/nyaterm-desktop/src/features/formatting/mod.rs]=0
[crates/nyaterm-desktop/src/features/icons/aliases.rs]=0
[crates/nyaterm-desktop/src/features/icons/connection.rs]=0
[crates/nyaterm-desktop/src/features/icons/file_kind.rs]=0
[crates/nyaterm-desktop/src/features/icons/mod.rs]=0
[crates/nyaterm-desktop/src/features/icons/quick.rs]=0
[crates/nyaterm-desktop/src/features/icons/remote_system.rs]=0
[crates/nyaterm-desktop/src/features/icons/search.rs]=0
[crates/nyaterm-desktop/src/features/inspector/mod.rs]=0
[crates/nyaterm-desktop/src/features/inspector/ai_ask.rs]=0
[crates/nyaterm-desktop/src/features/inspector/commands.rs]=0
@@ -792,6 +808,13 @@ declare -A SUPER_BASELINE=(
[crates/nyaterm-desktop/src/features/tunnels/tunnel_runtime/helpers.rs]=0
[crates/nyaterm-desktop/src/features/tunnels/tunnel_runtime/proxy_editor.rs]=0
[crates/nyaterm-desktop/src/features/tunnels/tunnel_runtime/tunnel_editor.rs]=0
[crates/nyaterm-desktop/src/features/view_widgets/chrome.rs]=0
[crates/nyaterm-desktop/src/features/view_widgets/icons.rs]=0
[crates/nyaterm-desktop/src/features/view_widgets/inspector_widgets.rs]=0
[crates/nyaterm-desktop/src/features/view_widgets/markdown.rs]=0
[crates/nyaterm-desktop/src/features/view_widgets/mod.rs]=0
[crates/nyaterm-desktop/src/features/view_widgets/rows.rs]=0
[crates/nyaterm-desktop/src/features/view_widgets/stats.rs]=0
)
for file in "${!SUPER_BASELINE[@]}"; do
@@ -806,10 +829,13 @@ done < <(rg -n --path-separator / '^[[:space:]]*use super::\*;' \
crates/nyaterm-desktop/src/features/ai \
crates/nyaterm-desktop/src/features/connections \
crates/nyaterm-desktop/src/features/commands \
crates/nyaterm-desktop/src/features/formatting \
crates/nyaterm-desktop/src/features/icons \
crates/nyaterm-desktop/src/features/inspector \
crates/nyaterm-desktop/src/features/panels \
crates/nyaterm-desktop/src/features/session \
crates/nyaterm-desktop/src/features/settings \
crates/nyaterm-desktop/src/features/view_widgets \
crates/nyaterm-desktop/src/features/pages/mod.rs \
crates/nyaterm-desktop/src/features/pages/connections \
crates/nyaterm-desktop/src/features/pages/tunnels \