zellij/zellij-client/src/web_client/session_management.rs
Aram Drevekenin 403f0a07be
fix(sessions): remove popups from welcome screen (#4294)
* remove popups from welcome screen

* docs(changelog): add pr
2025-07-16 11:43:18 +02:00

222 lines
7.1 KiB
Rust

use crate::os_input_output::ClientOsApi;
use crate::spawn_server;
use std::{fs, path::PathBuf};
use zellij_utils::{
cli::CliArgs,
data::{ConnectToSession, LayoutInfo, WebSharing},
envs,
input::{
config::{Config, ConfigError},
layout::Layout,
options::Options,
},
ipc::{ClientAttributes, ClientToServerMsg},
sessions::{generate_unique_session_name, resurrection_layout, session_exists},
setup::{find_default_config_dir, get_layout_dir},
};
pub fn build_initial_connection(
session_name: Option<String>,
config: &Config,
) -> Result<(Option<ConnectToSession>, bool), &'static str> {
// bool -> is_welcome_screen
let should_start_with_welcome_screen = session_name.is_none();
let default_layout_from_config =
LayoutInfo::from_config(&config.options.layout_dir, &config.options.default_layout);
if should_start_with_welcome_screen {
let Some(initial_session_name) = session_name.clone().or_else(generate_unique_session_name)
else {
return Err("Failed to generate unique session name, bailing.");
};
Ok((
Some(ConnectToSession {
name: Some(initial_session_name.clone()),
layout: Some(LayoutInfo::BuiltIn("welcome".to_owned())),
..Default::default()
}),
should_start_with_welcome_screen,
))
} else if let Some(session_name) = session_name {
Ok((
Some(ConnectToSession {
name: Some(session_name.clone()),
layout: default_layout_from_config,
..Default::default()
}),
should_start_with_welcome_screen,
))
} else if default_layout_from_config.is_some() {
Ok((
Some(ConnectToSession {
layout: default_layout_from_config,
..Default::default()
}),
should_start_with_welcome_screen,
))
} else {
Ok((None, should_start_with_welcome_screen))
}
}
fn layout_for_new_session(
config: &Config,
requested_layout: Option<LayoutInfo>,
) -> Result<(Layout, Config), ConfigError> {
let layout_dir = config
.options
.layout_dir
.clone()
.or_else(|| get_layout_dir(find_default_config_dir()));
match requested_layout {
Some(LayoutInfo::BuiltIn(layout_name)) => Layout::from_default_assets(
&PathBuf::from(layout_name),
layout_dir.clone(),
config.clone(),
),
Some(LayoutInfo::File(layout_name)) => Layout::from_path_or_default(
Some(&PathBuf::from(layout_name)),
layout_dir.clone(),
config.clone(),
),
Some(LayoutInfo::Url(url)) => Layout::from_url(&url, config.clone()),
Some(LayoutInfo::Stringified(stringified_layout)) => {
Layout::from_stringified_layout(&stringified_layout, config.clone())
},
None => Layout::from_default_assets(
&PathBuf::from("default"),
layout_dir.clone(),
config.clone(),
),
}
}
pub fn spawn_session_if_needed(
session_name: &str,
path: String,
client_attributes: ClientAttributes,
config: &Config,
config_options: &Options,
is_web_client: bool,
os_input: Box<dyn ClientOsApi>,
requested_layout: Option<LayoutInfo>,
is_welcome_screen: bool,
) -> (ClientToServerMsg, PathBuf) {
if session_exists(&session_name).unwrap_or(false) {
ipc_pipe_and_first_message_for_existing_session(
path,
client_attributes,
&config,
&config_options,
is_web_client,
)
} else {
let force_run_commands = false;
let resurrection_layout =
resurrection_layout(&session_name).map(|mut resurrection_layout| {
if force_run_commands {
resurrection_layout.recursively_add_start_suspended(Some(false));
}
resurrection_layout
});
match resurrection_layout {
Some(resurrection_layout) => spawn_new_session(
&session_name,
os_input.clone(),
config.clone(),
config_options.clone(),
Some(resurrection_layout),
client_attributes,
is_welcome_screen,
),
None => {
let new_session_layout = layout_for_new_session(&config, requested_layout);
spawn_new_session(
&session_name,
os_input.clone(),
config.clone(),
config_options.clone(),
new_session_layout.ok().map(|(l, _c)| l),
client_attributes,
is_welcome_screen,
)
},
}
}
}
fn spawn_new_session(
name: &str,
mut os_input: Box<dyn ClientOsApi>,
mut config: Config,
config_opts: Options,
layout: Option<Layout>,
client_attributes: ClientAttributes,
is_welcome_screen: bool,
) -> (ClientToServerMsg, PathBuf) {
let debug = false;
envs::set_session_name(name.to_owned());
os_input.update_session_name(name.to_owned());
let zellij_ipc_pipe: PathBuf = {
let mut sock_dir = zellij_utils::consts::ZELLIJ_SOCK_DIR.clone();
fs::create_dir_all(&sock_dir).unwrap();
zellij_utils::shared::set_permissions(&sock_dir, 0o700).unwrap();
sock_dir.push(name);
sock_dir
};
spawn_server(&*zellij_ipc_pipe, debug).unwrap();
let successfully_written_config = Config::write_config_to_disk_if_it_does_not_exist(
config.to_string(true),
&Default::default(),
);
let should_launch_setup_wizard = successfully_written_config;
let cli_args = CliArgs::default();
config.options.web_server = Some(true);
config.options.web_sharing = Some(WebSharing::On);
let is_web_client = true;
(
ClientToServerMsg::NewClient(
client_attributes,
Box::new(cli_args),
Box::new(config.clone()),
Box::new(config_opts.clone()),
Box::new(layout.unwrap()),
Box::new(config.plugins.clone()),
should_launch_setup_wizard,
is_web_client,
is_welcome_screen,
),
zellij_ipc_pipe,
)
}
fn ipc_pipe_and_first_message_for_existing_session(
session_name: String,
client_attributes: ClientAttributes,
config: &Config,
config_options: &Options,
is_web_client: bool,
) -> (ClientToServerMsg, PathBuf) {
let zellij_ipc_pipe: PathBuf = {
let mut sock_dir = zellij_utils::consts::ZELLIJ_SOCK_DIR.clone();
fs::create_dir_all(&sock_dir).unwrap();
zellij_utils::shared::set_permissions(&sock_dir, 0o700).unwrap();
sock_dir.push(session_name);
sock_dir
};
let first_message = ClientToServerMsg::AttachClient(
client_attributes,
config.clone(),
config_options.clone(),
None,
None,
is_web_client,
);
(first_message, zellij_ipc_pipe)
}