feat(ux): change themes at runtime (#3559)

This commit is contained in:
Aram Drevekenin 2024-08-20 16:10:27 +02:00 committed by GitHub
parent 45501793d1
commit e96491a3cf
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 81 additions and 31 deletions

View file

@ -215,7 +215,7 @@ pub fn start_client(
config.env.set_vars();
let palette = config
.theme_config(&config_options)
.theme_config(config_options.theme.as_ref())
.unwrap_or_else(|| os_input.load_palette());
let full_screen_ws = os_input.get_terminal_size_using_fd(0);
@ -615,7 +615,7 @@ pub fn start_server_detached(
config.env.set_vars();
let palette = config
.theme_config(&config_options)
.theme_config(config_options.theme.as_ref())
.unwrap_or_else(|| os_input.load_palette());
let client_attributes = ClientAttributes {

View file

@ -55,6 +55,7 @@ use zellij_utils::{
plugins::PluginAliases,
},
ipc::{ClientAttributes, ExitReason, ServerToClientMsg},
shared::default_palette,
};
pub type ClientId = u16;
@ -267,6 +268,9 @@ impl SessionMetaData {
client_id,
keybinds: Some(new_config.keybinds.clone()),
default_mode: new_config.options.default_mode,
theme: new_config
.theme_config(new_config.options.theme.as_ref())
.or_else(|| Some(default_palette())),
})
.unwrap();
self.senders

View file

@ -22,7 +22,7 @@ use std::collections::{BTreeMap, HashMap, HashSet};
use std::rc::Rc;
use std::time::Instant;
use zellij_utils::{
data::{ModeInfo, Style},
data::{ModeInfo, Palette, Style},
errors::prelude::*,
input::command::RunCommand,
input::layout::{FloatingPaneLayout, Run, RunPluginOrAlias},
@ -913,4 +913,10 @@ impl FloatingPanes {
},
}
}
pub fn update_pane_themes(&mut self, theme: Palette) {
self.style.colors = theme;
for pane in self.panes.values_mut() {
pane.update_theme(theme);
}
}
}

View file

@ -2155,6 +2155,9 @@ impl Grid {
pub fn unlock_renders(&mut self) {
self.lock_renders = false;
}
pub fn update_theme(&mut self, theme: Palette) {
self.style.colors = theme.clone();
}
}
impl Perform for Grid {

View file

@ -675,6 +675,12 @@ impl Pane for PluginPane {
self.pane_name = String::from_utf8_lossy(&buf).to_string();
self.set_should_render(true);
}
fn update_theme(&mut self, theme: Palette) {
self.style.colors = theme.clone();
for grid in self.grids.values_mut() {
grid.update_theme(theme.clone());
}
}
}
impl PluginPane {

View file

@ -790,6 +790,14 @@ impl Pane for TerminalPane {
run_command.clone()
})
}
fn update_theme(&mut self, theme: Palette) {
self.style.colors = theme.clone();
self.grid.update_theme(theme);
if self.banner.is_some() {
// we do this so that the banner will be updated with the new theme colors
self.render_first_run_banner();
}
}
}
impl TerminalPane {

View file

@ -18,7 +18,7 @@ use crate::{
};
use stacked_panes::StackedPanes;
use zellij_utils::{
data::{Direction, ModeInfo, PaneInfo, ResizeStrategy, Style},
data::{Direction, ModeInfo, Palette, PaneInfo, ResizeStrategy, Style},
errors::prelude::*,
input::{
command::RunCommand,
@ -1766,6 +1766,12 @@ impl TiledPanes {
}
pane_infos
}
pub fn update_pane_themes(&mut self, theme: Palette) {
self.style.colors = theme;
for pane in self.panes.values_mut() {
pane.update_theme(theme);
}
}
}
#[allow(clippy::borrowed_box)]

View file

@ -93,23 +93,6 @@ pub(crate) fn route_action(
},
Action::SwitchToMode(mode) => {
let attrs = &client_attributes;
// TODO: use the palette from the client and remove it from the server os api
// this is left here as a stop gap measure until we shift some code around
// to allow for this
// TODO: Need access to `ClientAttributes` here
senders
.send_to_plugin(PluginInstruction::Update(vec![(
None,
Some(client_id),
Event::ModeUpdate(get_mode_info(
mode,
attrs,
capabilities,
&client_keybinds,
Some(default_mode),
)),
)]))
.with_context(err_context)?;
senders
.send_to_server(ServerInstruction::ChangeMode(client_id, mode))
.with_context(err_context)?;

View file

@ -368,6 +368,7 @@ pub enum ScreenInstruction {
client_id: ClientId,
keybinds: Option<Keybinds>,
default_mode: Option<InputMode>,
theme: Option<Palette>,
},
RerunCommandPane(u32), // u32 - terminal pane id
}
@ -1735,11 +1736,13 @@ impl Screen {
if mode_info.session_name.as_ref() != Some(&self.session_name) {
mode_info.session_name = Some(self.session_name.clone());
}
let previous_mode = self
let previous_mode_info = self
.mode_info
.get(&client_id)
.unwrap_or(&self.default_mode_info)
.mode;
.unwrap_or(&self.default_mode_info);
let previous_mode = previous_mode_info.mode;
mode_info.style = previous_mode_info.style;
let err_context = || {
format!(
@ -2183,10 +2186,22 @@ impl Screen {
&mut self,
new_keybinds: Option<Keybinds>,
new_default_mode: Option<InputMode>,
theme: Option<Palette>,
client_id: ClientId,
) -> Result<()> {
let should_update_mode_info =
new_keybinds.is_some() || new_default_mode.is_some() || theme.is_some();
// themes are currently global and not per-client
if let Some(theme) = theme {
self.default_mode_info.update_theme(theme);
for tab in self.tabs.values_mut() {
tab.update_theme(theme);
}
}
// client specific configuration
if self.connected_clients_contains(&client_id) {
let should_update_mode_info = new_keybinds.is_some() || new_default_mode.is_some();
let mode_info = self
.mode_info
.entry(client_id)
@ -2197,15 +2212,21 @@ impl Screen {
if let Some(new_default_mode) = new_default_mode {
mode_info.update_default_mode(new_default_mode);
}
if let Some(theme) = theme {
mode_info.update_theme(theme);
}
if should_update_mode_info {
for tab in self.tabs.values_mut() {
tab.change_mode_info(mode_info.clone(), client_id);
tab.mark_active_pane_for_rerender(client_id);
tab.update_input_modes()?;
}
}
} else {
log::error!("Could not find client_id {client_id} to rebind keys");
}
if should_update_mode_info {
for tab in self.tabs.values_mut() {
tab.update_input_modes()?;
}
}
Ok(())
}
@ -4082,9 +4103,10 @@ pub(crate) fn screen_thread_main(
client_id,
keybinds,
default_mode,
theme,
} => {
screen
.reconfigure_mode_info(keybinds, default_mode, client_id)
.reconfigure_mode_info(keybinds, default_mode, theme, client_id)
.non_fatal();
},
ScreenInstruction::RerunCommandPane(terminal_pane_id) => {

View file

@ -492,6 +492,7 @@ pub trait Pane {
fn rerun(&mut self) -> Option<RunCommand> {
None
} // only relevant to terminal panes
fn update_theme(&mut self, _theme: Palette) {}
}
#[derive(Clone, Debug)]
@ -3951,6 +3952,14 @@ impl Tab {
},
}
}
pub fn update_theme(&mut self, theme: Palette) {
self.style.colors = theme;
self.floating_panes.update_pane_themes(theme);
self.tiled_panes.update_pane_themes(theme);
for (_, pane) in self.suppressed_panes.values_mut() {
pane.update_theme(theme);
}
}
}
pub fn pane_info_for_pane(pane_id: &PaneId, pane: &Box<dyn Pane>) -> PaneInfo {

View file

@ -1175,6 +1175,9 @@ impl ModeInfo {
pub fn update_default_mode(&mut self, new_default_mode: InputMode) {
self.base_mode = Some(new_default_mode);
}
pub fn update_theme(&mut self, theme: Palette) {
self.style.colors = theme;
}
}
#[derive(Debug, Default, Clone, PartialEq, Eq, Deserialize, Serialize)]

View file

@ -163,8 +163,8 @@ impl TryFrom<&CliArgs> for Config {
}
impl Config {
pub fn theme_config(&self, opts: &Options) -> Option<Palette> {
match &opts.theme {
pub fn theme_config(&self, theme_name: Option<&String>) -> Option<Palette> {
match &theme_name {
Some(theme_name) => self.themes.get_theme(theme_name).map(|theme| theme.palette),
None => self.themes.get_theme("default").map(|theme| theme.palette),
}