mirror of
https://github.com/rust-kotlin/ashell.git
synced 2026-09-24 08:01:05 +00:00
refactor: restructure project
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
pub(crate) const DEFAULT_COLS: u16 = 100;
|
||||
pub(crate) const DEFAULT_ROWS: u16 = 30;
|
||||
pub(crate) const SIDEBAR_WIDTH: f32 = 306.0;
|
||||
pub(crate) const TAB_BAR_HEIGHT: f32 = 52.0;
|
||||
pub(crate) const TERMINAL_PADDING_X: f32 = 32.0;
|
||||
pub(crate) const TERMINAL_PADDING_Y: f32 = 32.0;
|
||||
pub(crate) const TERMINAL_KEY_CONTEXT: &str = "AshellTerminal";
|
||||
@@ -19,7 +19,7 @@ use rust_i18n::t;
|
||||
|
||||
use crate::{
|
||||
Ashell,
|
||||
config::AuthMethod,
|
||||
session::config::AuthMethod,
|
||||
system::format_bytes,
|
||||
};
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
pub mod constants;
|
||||
pub mod dialogs;
|
||||
pub mod startup;
|
||||
pub mod theme;
|
||||
pub mod ui;
|
||||
|
||||
use std::{
|
||||
cell::{Cell, RefCell},
|
||||
collections::HashMap,
|
||||
@@ -22,11 +28,11 @@ use rust_i18n::t;
|
||||
use tokio::runtime::Runtime;
|
||||
|
||||
use crate::{
|
||||
config::{AuthMethod, ConfigStore},
|
||||
sftp::SftpHandle,
|
||||
session::config::{AuthMethod, ConfigStore},
|
||||
system::{SystemSampler, SystemSnapshot},
|
||||
terminal::{self, BackendCommand, BackendEvent, TabKind, TerminalTab},
|
||||
ssh_terminal,
|
||||
backend::ssh,
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
@@ -638,6 +644,8 @@ impl Ashell {
|
||||
self.focused_pane_path = vec![];
|
||||
self.active_tab = None;
|
||||
self.active_group = None;
|
||||
self.tab_groups.clear();
|
||||
self.tabs.clear();
|
||||
self.system_tab_id = None;
|
||||
self.cpu_history.clear();
|
||||
self.net_rx_history.clear();
|
||||
@@ -799,7 +807,7 @@ impl Ashell {
|
||||
let events = self.events_tx.clone();
|
||||
let tab_id = tab_id.clone();
|
||||
self.runtime.spawn(async move {
|
||||
match ssh_terminal::sample_remote_system(session).await {
|
||||
match ssh::sample_remote_system(session).await {
|
||||
Ok(snapshot) => {
|
||||
let _ = events.send(BackendEvent::RemoteSystem { tab_id, snapshot });
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
use gpui::{App, AppContext as _, Bounds, WindowOptions, point, px, size};
|
||||
use gpui_component::Root;
|
||||
|
||||
use crate::session::config::ConfigStore;
|
||||
use crate::Ashell;
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
pub(crate) fn sync_macos_launch_environment() {
|
||||
let shell = std::env::var("SHELL").unwrap_or_else(|_| "/bin/zsh".to_string());
|
||||
let Ok(output) = std::process::Command::new(&shell).args(["-l", "-c", "env -0"]).output() else {
|
||||
return;
|
||||
};
|
||||
if !output.status.success() {
|
||||
return;
|
||||
}
|
||||
|
||||
for entry in output.stdout.split(|b| *b == 0) {
|
||||
if entry.is_empty() {
|
||||
continue;
|
||||
}
|
||||
let Some(eq) = entry.iter().position(|b| *b == b'=') else {
|
||||
continue;
|
||||
};
|
||||
let Ok(key) = std::str::from_utf8(&entry[..eq]) else {
|
||||
continue;
|
||||
};
|
||||
let Ok(value) = std::str::from_utf8(&entry[eq + 1..]) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
let should_import = matches!(
|
||||
key,
|
||||
"PATH"
|
||||
| "MANPATH"
|
||||
| "INFOPATH"
|
||||
| "LANG"
|
||||
| "LC_ALL"
|
||||
| "LC_CTYPE"
|
||||
| "SHELL"
|
||||
| "HOME"
|
||||
| "HOMEBREW_PREFIX"
|
||||
| "HOMEBREW_CELLAR"
|
||||
| "HOMEBREW_REPOSITORY"
|
||||
) || key.starts_with("LC_");
|
||||
|
||||
if should_import {
|
||||
unsafe {
|
||||
std::env::set_var(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
pub(crate) fn sync_macos_launch_environment() {}
|
||||
|
||||
pub(crate) fn open_main_window(cx: &mut App) {
|
||||
let mut window_options = WindowOptions::default();
|
||||
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
if let Ok(img) = image::load_from_memory(include_bytes!("../../assets/icons/ashell.png")) {
|
||||
window_options.icon = Some(std::sync::Arc::new(img.into_rgba8()));
|
||||
}
|
||||
|
||||
let config = ConfigStore::load().unwrap_or_else(|_| ConfigStore::in_memory());
|
||||
if let Some(bounds) = config.window_bounds() {
|
||||
window_options.window_bounds = Some(match bounds {
|
||||
crate::session::config::SavedWindowBounds::Fullscreen {
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height,
|
||||
} => gpui::WindowBounds::Fullscreen(Bounds::new(
|
||||
point(px(*x), px(*y)),
|
||||
size(px(*width), px(*height)),
|
||||
)),
|
||||
crate::session::config::SavedWindowBounds::Maximized {
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height,
|
||||
} => gpui::WindowBounds::Maximized(Bounds::new(
|
||||
point(px(*x), px(*y)),
|
||||
size(px(*width), px(*height)),
|
||||
)),
|
||||
crate::session::config::SavedWindowBounds::Windowed {
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height,
|
||||
} => gpui::WindowBounds::Windowed(Bounds::new(
|
||||
point(px(*x), px(*y)),
|
||||
size(px(*width), px(*height)),
|
||||
)),
|
||||
});
|
||||
} else if let Some(display) = cx.displays().first().cloned() {
|
||||
let display_bounds = display.bounds();
|
||||
let width = display_bounds.size.width * 0.8;
|
||||
let height = display_bounds.size.height * 0.9;
|
||||
|
||||
let x = display_bounds.origin.x + (display_bounds.size.width - width) / 2.0;
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
let y = display_bounds.origin.y;
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
let y = display_bounds.origin.y + (display_bounds.size.height - height) / 2.0;
|
||||
|
||||
window_options.window_bounds = Some(gpui::WindowBounds::Windowed(Bounds::new(
|
||||
point(x, y),
|
||||
size(width, height),
|
||||
)));
|
||||
}
|
||||
|
||||
cx.open_window(window_options, |window, cx| {
|
||||
window.activate_window();
|
||||
window.set_window_title("ashell");
|
||||
gpui_component::Theme::sync_system_appearance(Some(window), cx);
|
||||
let view = cx.new(|cx| Ashell::new(window, cx));
|
||||
|
||||
let workspace_panels_clone = view.read(cx).workspace_panels.clone();
|
||||
let body_panels_clone = view.read(cx).body_panels.clone();
|
||||
window.on_window_should_close(cx, move |window: &mut gpui::Window, cx: &mut gpui::App| {
|
||||
let mut config = ConfigStore::load().unwrap_or_else(|_| ConfigStore::in_memory());
|
||||
let current_bounds = window.window_bounds();
|
||||
let saved_bounds = match current_bounds {
|
||||
gpui::WindowBounds::Fullscreen(b) => crate::session::config::SavedWindowBounds::Fullscreen {
|
||||
x: b.origin.x.into(),
|
||||
y: b.origin.y.into(),
|
||||
width: b.size.width.into(),
|
||||
height: b.size.height.into(),
|
||||
},
|
||||
gpui::WindowBounds::Maximized(b) => crate::session::config::SavedWindowBounds::Maximized {
|
||||
x: b.origin.x.into(),
|
||||
y: b.origin.y.into(),
|
||||
width: b.size.width.into(),
|
||||
height: b.size.height.into(),
|
||||
},
|
||||
gpui::WindowBounds::Windowed(b) => crate::session::config::SavedWindowBounds::Windowed {
|
||||
x: b.origin.x.into(),
|
||||
y: b.origin.y.into(),
|
||||
width: b.size.width.into(),
|
||||
height: b.size.height.into(),
|
||||
},
|
||||
};
|
||||
let workspace_sizes: Vec<f32> = workspace_panels_clone
|
||||
.read(cx)
|
||||
.sizes()
|
||||
.iter()
|
||||
.map(|s| s.into())
|
||||
.collect();
|
||||
let body_sizes: Vec<f32> = body_panels_clone
|
||||
.read(cx)
|
||||
.sizes()
|
||||
.iter()
|
||||
.map(|s| s.into())
|
||||
.collect();
|
||||
config.set_layout_state(Some(saved_bounds), Some(workspace_sizes), Some(body_sizes));
|
||||
let _ = config.save();
|
||||
true
|
||||
});
|
||||
|
||||
cx.new(|cx| Root::new(view, window, cx))
|
||||
})
|
||||
.expect("failed to open window");
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use gpui::{Anchor, Context, IntoElement, SharedString, Window, px};
|
||||
use anyhow::{Context as _, Result};
|
||||
use gpui::{Anchor, App, Context, IntoElement, SharedString, Window, px};
|
||||
use gpui_component::{
|
||||
ActiveTheme as _, IconName, Sizable as _, Theme, ThemeMode, ThemeRegistry,
|
||||
button::{Button, ButtonVariants as _},
|
||||
@@ -8,6 +9,33 @@ use rust_i18n::t;
|
||||
|
||||
use crate::Ashell;
|
||||
|
||||
pub(crate) const EMBEDDED_THEME_JSONS: &[&str] = &[
|
||||
include_str!("../../assets/themes/matrix.json"),
|
||||
include_str!("../../assets/themes/tokyonight.json"),
|
||||
include_str!("../../assets/themes/gruvbox.json"),
|
||||
include_str!("../../assets/themes/solarized.json"),
|
||||
];
|
||||
|
||||
pub(crate) fn load_fonts(cx: &mut App) -> Result<()> {
|
||||
let regular =
|
||||
std::borrow::Cow::Borrowed(include_bytes!("../../assets/fonts/MapleMono-NF-CN-Regular.ttf").as_slice());
|
||||
let bold = std::borrow::Cow::Borrowed(include_bytes!("../../assets/fonts/MapleMono-NF-CN-Bold.ttf").as_slice());
|
||||
cx.text_system()
|
||||
.add_fonts(vec![regular, bold])
|
||||
.context("load Maple Mono NF CN fonts")?;
|
||||
set_theme_font_names(cx.global_mut::<Theme>(), ".SystemUIFont");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn load_embedded_themes(cx: &mut App) {
|
||||
let registry = ThemeRegistry::global_mut(cx);
|
||||
for theme_json in EMBEDDED_THEME_JSONS {
|
||||
if let Err(err) = registry.load_themes_from_str(theme_json) {
|
||||
tracing::warn!("failed to load embedded theme: {err:#}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn set_theme_font_names(theme: &mut Theme, ui_font_family: &str) {
|
||||
theme.font_family = ui_font_family.into();
|
||||
theme.mono_font_family = ui_font_family.into();
|
||||
@@ -22,12 +22,12 @@ use gpui_component::{
|
||||
use rust_i18n::t;
|
||||
|
||||
use crate::{
|
||||
Ashell, PaneLayout, SIDEBAR_WIDTH, TERMINAL_KEY_CONTEXT,
|
||||
sftp_ops::is_editable_text_file,
|
||||
Ashell, PaneLayout,
|
||||
app::constants::{SIDEBAR_WIDTH, TERMINAL_KEY_CONTEXT},
|
||||
sftp::ops::is_editable_text_file,
|
||||
sftp::format_mtime,
|
||||
system::format_bytes,
|
||||
terminal::{TabKind, TerminalTab},
|
||||
terminal_element,
|
||||
terminal::{self, TabKind, TerminalTab},
|
||||
};
|
||||
|
||||
impl Ashell {
|
||||
@@ -1574,7 +1574,7 @@ impl Ashell {
|
||||
this.focus_pane_with_id(tab_id_clone2.clone());
|
||||
cx.notify();
|
||||
}))
|
||||
.child(terminal_element::TerminalElement::new(
|
||||
.child(terminal::element::TerminalElement::new(
|
||||
cx.entity(),
|
||||
focus_handle,
|
||||
snapshot,
|
||||
@@ -0,0 +1,2 @@
|
||||
pub mod local;
|
||||
pub mod ssh;
|
||||
@@ -14,7 +14,7 @@ use russh::{
|
||||
use tokio::sync::mpsc;
|
||||
|
||||
use crate::{
|
||||
config::{AuthMethod, Session},
|
||||
session::config::{AuthMethod, Session},
|
||||
system::{SystemSnapshot, remote_snapshot_from_kv},
|
||||
terminal::{BackendCommand, BackendEvent, BackendTx},
|
||||
};
|
||||
+11
-222
@@ -1,235 +1,25 @@
|
||||
#![windows_subsystem = "windows"]
|
||||
|
||||
|
||||
use anyhow::{Context as _, Result};
|
||||
use gpui::{App, AppContext as _, Bounds, KeyBinding, WindowOptions, point, px, size};
|
||||
use gpui_component::{Root, Theme, ThemeRegistry};
|
||||
use gpui::{ KeyBinding };
|
||||
use gpui_component_assets::Assets;
|
||||
|
||||
mod config;
|
||||
mod local_terminal;
|
||||
mod app;
|
||||
mod backend;
|
||||
mod session;
|
||||
mod sftp;
|
||||
mod ssh_terminal;
|
||||
mod system;
|
||||
mod terminal;
|
||||
mod terminal_element;
|
||||
mod terminal_input;
|
||||
mod app;
|
||||
mod session;
|
||||
mod sftp_ops;
|
||||
mod theme;
|
||||
mod dialogs;
|
||||
mod ui;
|
||||
|
||||
use config::ConfigStore;
|
||||
|
||||
rust_i18n::i18n!("locales", fallback = "en");
|
||||
|
||||
const DEFAULT_COLS: u16 = 100;
|
||||
const DEFAULT_ROWS: u16 = 30;
|
||||
|
||||
const SIDEBAR_WIDTH: f32 = 306.0;
|
||||
const TAB_BAR_HEIGHT: f32 = 52.0;
|
||||
const TERMINAL_PADDING_X: f32 = 32.0;
|
||||
const TERMINAL_PADDING_Y: f32 = 32.0;
|
||||
const TERMINAL_KEY_CONTEXT: &str = "AshellTerminal";
|
||||
const EMBEDDED_THEME_JSONS: &[&str] = &[
|
||||
include_str!("../assets/themes/matrix.json"),
|
||||
include_str!("../assets/themes/tokyonight.json"),
|
||||
include_str!("../assets/themes/gruvbox.json"),
|
||||
include_str!("../assets/themes/solarized.json"),
|
||||
];
|
||||
|
||||
gpui::actions!(ashell_terminal, [TerminalTabKey, TerminalBacktabKey]);
|
||||
|
||||
pub(crate) use app::{
|
||||
Ashell, ConnectionProgress, PaneLayout, SelectorEntry, SftpContextMenuState, TabGroup,
|
||||
};
|
||||
|
||||
fn load_fonts(cx: &mut App) -> Result<()> {
|
||||
let regular =
|
||||
std::borrow::Cow::Borrowed(include_bytes!("../assets/fonts/MapleMono-NF-CN-Regular.ttf").as_slice());
|
||||
let bold = std::borrow::Cow::Borrowed(include_bytes!("../assets/fonts/MapleMono-NF-CN-Bold.ttf").as_slice());
|
||||
cx.text_system()
|
||||
.add_fonts(vec![regular, bold])
|
||||
.context("load Maple Mono NF CN fonts")?;
|
||||
// At startup we don't have a config yet, so pass the default UI font family.
|
||||
// It will be reapplied in Ashell::new() -> apply_theme_preferences.
|
||||
theme::set_theme_font_names(cx.global_mut::<Theme>(), ".SystemUIFont");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn load_embedded_themes(cx: &mut App) {
|
||||
let registry = ThemeRegistry::global_mut(cx);
|
||||
for theme_json in EMBEDDED_THEME_JSONS {
|
||||
if let Err(err) = registry.load_themes_from_str(theme_json) {
|
||||
tracing::warn!("failed to load embedded theme: {err:#}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
fn sync_macos_launch_environment() {
|
||||
let shell = std::env::var("SHELL").unwrap_or_else(|_| "/bin/zsh".to_string());
|
||||
let Ok(output) = std::process::Command::new(&shell).args(["-l", "-c", "env -0"]).output() else {
|
||||
return;
|
||||
};
|
||||
if !output.status.success() {
|
||||
return;
|
||||
}
|
||||
|
||||
for entry in output.stdout.split(|b| *b == 0) {
|
||||
if entry.is_empty() {
|
||||
continue;
|
||||
}
|
||||
let Some(eq) = entry.iter().position(|b| *b == b'=') else {
|
||||
continue;
|
||||
};
|
||||
let Ok(key) = std::str::from_utf8(&entry[..eq]) else {
|
||||
continue;
|
||||
};
|
||||
let Ok(value) = std::str::from_utf8(&entry[eq + 1..]) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
let should_import = matches!(
|
||||
key,
|
||||
"PATH"
|
||||
| "MANPATH"
|
||||
| "INFOPATH"
|
||||
| "LANG"
|
||||
| "LC_ALL"
|
||||
| "LC_CTYPE"
|
||||
| "SHELL"
|
||||
| "HOME"
|
||||
| "HOMEBREW_PREFIX"
|
||||
| "HOMEBREW_CELLAR"
|
||||
| "HOMEBREW_REPOSITORY"
|
||||
) || key.starts_with("LC_");
|
||||
|
||||
if should_import {
|
||||
unsafe {
|
||||
std::env::set_var(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
fn sync_macos_launch_environment() {}
|
||||
|
||||
fn open_main_window(cx: &mut App) {
|
||||
let mut window_options = WindowOptions::default();
|
||||
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
if let Ok(img) = image::load_from_memory(include_bytes!("../assets/icons/ashell.png")) {
|
||||
window_options.icon = Some(std::sync::Arc::new(img.into_rgba8()));
|
||||
}
|
||||
|
||||
let config = ConfigStore::load().unwrap_or_else(|_| ConfigStore::in_memory());
|
||||
if let Some(bounds) = config.window_bounds() {
|
||||
window_options.window_bounds = Some(match bounds {
|
||||
crate::config::SavedWindowBounds::Fullscreen {
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height,
|
||||
} => gpui::WindowBounds::Fullscreen(Bounds::new(
|
||||
point(px(*x), px(*y)),
|
||||
size(px(*width), px(*height)),
|
||||
)),
|
||||
crate::config::SavedWindowBounds::Maximized {
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height,
|
||||
} => gpui::WindowBounds::Maximized(Bounds::new(
|
||||
point(px(*x), px(*y)),
|
||||
size(px(*width), px(*height)),
|
||||
)),
|
||||
crate::config::SavedWindowBounds::Windowed {
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height,
|
||||
} => gpui::WindowBounds::Windowed(Bounds::new(
|
||||
point(px(*x), px(*y)),
|
||||
size(px(*width), px(*height)),
|
||||
)),
|
||||
});
|
||||
} else if let Some(display) = cx.displays().first().cloned() {
|
||||
let display_bounds = display.bounds();
|
||||
let width = display_bounds.size.width * 0.8;
|
||||
let height = display_bounds.size.height * 0.9;
|
||||
|
||||
let x = display_bounds.origin.x + (display_bounds.size.width - width) / 2.0;
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
let y = display_bounds.origin.y;
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
let y = display_bounds.origin.y + (display_bounds.size.height - height) / 2.0;
|
||||
|
||||
window_options.window_bounds = Some(gpui::WindowBounds::Windowed(Bounds::new(
|
||||
point(x, y),
|
||||
size(width, height),
|
||||
)));
|
||||
}
|
||||
|
||||
cx.open_window(window_options, |window, cx| {
|
||||
window.activate_window();
|
||||
window.set_window_title("ashell");
|
||||
Theme::sync_system_appearance(Some(window), cx);
|
||||
let view = cx.new(|cx| Ashell::new(window, cx));
|
||||
|
||||
let workspace_panels_clone = view.read(cx).workspace_panels.clone();
|
||||
let body_panels_clone = view.read(cx).body_panels.clone();
|
||||
window.on_window_should_close(cx, move |window: &mut gpui::Window, cx: &mut gpui::App| {
|
||||
let mut config = ConfigStore::load().unwrap_or_else(|_| ConfigStore::in_memory());
|
||||
let current_bounds = window.window_bounds();
|
||||
let saved_bounds = match current_bounds {
|
||||
gpui::WindowBounds::Fullscreen(b) => crate::config::SavedWindowBounds::Fullscreen {
|
||||
x: b.origin.x.into(),
|
||||
y: b.origin.y.into(),
|
||||
width: b.size.width.into(),
|
||||
height: b.size.height.into(),
|
||||
},
|
||||
gpui::WindowBounds::Maximized(b) => crate::config::SavedWindowBounds::Maximized {
|
||||
x: b.origin.x.into(),
|
||||
y: b.origin.y.into(),
|
||||
width: b.size.width.into(),
|
||||
height: b.size.height.into(),
|
||||
},
|
||||
gpui::WindowBounds::Windowed(b) => crate::config::SavedWindowBounds::Windowed {
|
||||
x: b.origin.x.into(),
|
||||
y: b.origin.y.into(),
|
||||
width: b.size.width.into(),
|
||||
height: b.size.height.into(),
|
||||
},
|
||||
};
|
||||
let workspace_sizes: Vec<f32> = workspace_panels_clone
|
||||
.read(cx)
|
||||
.sizes()
|
||||
.iter()
|
||||
.map(|s| s.into())
|
||||
.collect();
|
||||
let body_sizes: Vec<f32> = body_panels_clone
|
||||
.read(cx)
|
||||
.sizes()
|
||||
.iter()
|
||||
.map(|s| s.into())
|
||||
.collect();
|
||||
config.set_layout_state(Some(saved_bounds), Some(workspace_sizes), Some(body_sizes));
|
||||
let _ = config.save();
|
||||
true
|
||||
});
|
||||
|
||||
cx.new(|cx| Root::new(view, window, cx))
|
||||
})
|
||||
.expect("failed to open window");
|
||||
}
|
||||
|
||||
fn main() {
|
||||
sync_macos_launch_environment();
|
||||
app::startup::sync_macos_launch_environment();
|
||||
tracing_subscriber::fmt()
|
||||
.with_env_filter(
|
||||
tracing_subscriber::EnvFilter::try_from_default_env()
|
||||
@@ -246,20 +36,19 @@ fn main() {
|
||||
let app = gpui_platform::application().with_assets(Assets);
|
||||
app.on_reopen(|cx| {
|
||||
if cx.windows().is_empty() {
|
||||
open_main_window(cx);
|
||||
app::startup::open_main_window(cx);
|
||||
}
|
||||
});
|
||||
app.run(move |cx| {
|
||||
gpui_component::init(cx);
|
||||
cx.bind_keys([
|
||||
KeyBinding::new("tab", TerminalTabKey, Some(TERMINAL_KEY_CONTEXT)),
|
||||
KeyBinding::new("shift-tab", TerminalBacktabKey, Some(TERMINAL_KEY_CONTEXT)),
|
||||
KeyBinding::new("tab", TerminalTabKey, Some(app::constants::TERMINAL_KEY_CONTEXT)),
|
||||
KeyBinding::new("shift-tab", TerminalBacktabKey, Some(app::constants::TERMINAL_KEY_CONTEXT)),
|
||||
]);
|
||||
load_embedded_themes(cx);
|
||||
if let Err(err) = load_fonts(cx) {
|
||||
app::theme::load_embedded_themes(cx);
|
||||
if let Err(err) = app::theme::load_fonts(cx) {
|
||||
tracing::warn!("failed to load embedded fonts: {err:#}");
|
||||
}
|
||||
open_main_window(cx);
|
||||
app::startup::open_main_window(cx);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
pub mod config;
|
||||
|
||||
use gpui::{
|
||||
App, AppContext as _, Context, Entity, KeyDownEvent, MouseButton,
|
||||
MouseDownEvent, MouseMoveEvent, SharedString, Window, px,
|
||||
@@ -9,21 +11,20 @@ use gpui_component::{
|
||||
use rust_i18n::t;
|
||||
use uuid::Uuid;
|
||||
|
||||
use self::config::{AuthMethod, Session};
|
||||
|
||||
use crate::{
|
||||
Ashell, ConnectionProgress, PaneLayout, SelectorEntry, TabGroup,
|
||||
config::{AuthMethod, Session},
|
||||
local_terminal,
|
||||
backend::{local, ssh},
|
||||
sftp,
|
||||
ssh_terminal,
|
||||
terminal::{BackendCommand, RenderSnapshot, TabKind, TerminalTab},
|
||||
DEFAULT_COLS, DEFAULT_ROWS, SIDEBAR_WIDTH, TAB_BAR_HEIGHT, TERMINAL_PADDING_X,
|
||||
TERMINAL_PADDING_Y,
|
||||
app::constants::{DEFAULT_COLS, DEFAULT_ROWS, SIDEBAR_WIDTH, TAB_BAR_HEIGHT, TERMINAL_PADDING_X, TERMINAL_PADDING_Y},
|
||||
};
|
||||
|
||||
impl Ashell {
|
||||
pub(crate) fn open_local(&mut self, cx: &mut Context<Self>) {
|
||||
let id = Uuid::new_v4().to_string();
|
||||
match local_terminal::spawn_local_terminal(
|
||||
match local::spawn_local_terminal(
|
||||
id.clone(),
|
||||
DEFAULT_COLS,
|
||||
DEFAULT_ROWS,
|
||||
@@ -221,7 +222,7 @@ impl Ashell {
|
||||
if let Err(err) = self.config.save() {
|
||||
tracing::warn!("failed to save UI font family: {err:#}");
|
||||
}
|
||||
crate::theme::set_theme_font_names(Theme::global_mut(cx), &self.ui_font_family);
|
||||
crate::app::theme::set_theme_font_names(Theme::global_mut(cx), &self.ui_font_family);
|
||||
cx.notify();
|
||||
window.refresh();
|
||||
}
|
||||
@@ -346,7 +347,7 @@ impl Ashell {
|
||||
|
||||
pub(crate) fn open_ssh_session(&mut self, session: Session, cx: &mut Context<Self>) {
|
||||
let id = Uuid::new_v4().to_string();
|
||||
let backend = ssh_terminal::spawn_ssh_terminal(
|
||||
let backend = ssh::spawn_ssh_terminal(
|
||||
self.runtime.handle(),
|
||||
id.clone(),
|
||||
session.clone(),
|
||||
@@ -528,6 +529,8 @@ impl Ashell {
|
||||
self.focused_pane_path = vec![];
|
||||
self.active_tab = None;
|
||||
self.active_group = None;
|
||||
self.tab_groups.clear();
|
||||
self.tabs.clear();
|
||||
self.system_tab_id = None;
|
||||
self.cpu_history.clear();
|
||||
self.net_rx_history.clear();
|
||||
@@ -718,7 +721,7 @@ impl Ashell {
|
||||
let new_id = Uuid::new_v4().to_string();
|
||||
let mut tab = match current_tab.kind {
|
||||
TabKind::Local => {
|
||||
match local_terminal::spawn_local_terminal(
|
||||
match local::spawn_local_terminal(
|
||||
new_id.clone(),
|
||||
DEFAULT_COLS,
|
||||
DEFAULT_ROWS,
|
||||
@@ -743,7 +746,7 @@ impl Ashell {
|
||||
cx.notify();
|
||||
return;
|
||||
};
|
||||
let backend = ssh_terminal::spawn_ssh_terminal(
|
||||
let backend = ssh::spawn_ssh_terminal(
|
||||
self.runtime.handle(),
|
||||
new_id.clone(),
|
||||
session.clone(),
|
||||
@@ -1,3 +1,5 @@
|
||||
pub mod ops;
|
||||
|
||||
use std::{
|
||||
fs,
|
||||
path::{Path, PathBuf},
|
||||
@@ -27,7 +29,7 @@ use zip::read::ZipArchive;
|
||||
use rust_i18n::t;
|
||||
|
||||
use crate::{
|
||||
config::{AuthMethod, Session},
|
||||
session::config::{AuthMethod, Session},
|
||||
terminal::BackendEvent,
|
||||
};
|
||||
|
||||
@@ -496,7 +498,7 @@ async fn run_sftp(
|
||||
}
|
||||
SftpCommand::EditFile { remote_path } => {
|
||||
let id = uuid::Uuid::new_v4().to_string();
|
||||
let config = crate::config::ConfigStore::load().unwrap();
|
||||
let config = crate::session::config::ConfigStore::load().unwrap();
|
||||
let tmp_dir = config.tmp_dir().unwrap_or_else(|| PathBuf::from("/tmp"));
|
||||
let base = base_name(&remote_path);
|
||||
let local_path = tmp_dir.join(format!("{}-{}", id, base));
|
||||
@@ -1,3 +1,6 @@
|
||||
pub mod element;
|
||||
pub mod input;
|
||||
|
||||
use std::sync::mpsc::Sender;
|
||||
|
||||
use alacritty_terminal::{
|
||||
@@ -10,7 +13,7 @@ use alacritty_terminal::{
|
||||
};
|
||||
use gpui::Keystroke;
|
||||
|
||||
use crate::config::Session;
|
||||
use crate::session::config::Session;
|
||||
use crate::sftp::{PreviewData, RemoteEntry};
|
||||
use crate::system::SystemSnapshot;
|
||||
|
||||
Reference in New Issue
Block a user