Indicate to the user when text is copied to the clipboard (#642)

* Indicate to the user when text is copied to the clipboard

- broadcast CopyToClipboard event to plugins after selection has been
  copied, and InputReceived event after any input has been received.
- add new ClientToServerMsg InputReceived
- subscribe status-bar plugin to new events, modify second line after
  CopyToClipboard, reset it on InputReceived.

* remove unnecessary InputReceived ClientToServerMsg

- use existing Actions instead to know that user input has been received

* make status bar text copied hint bold green

* cleanup

* cleanup

* cleanup
This commit is contained in:
Thomas Linford 2021-08-23 15:51:33 +02:00 committed by GitHub
parent d1b5a69918
commit 94f20cfd53
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 47 additions and 5 deletions

View file

@ -8,7 +8,7 @@ use zellij_tile::prelude::*;
use zellij_tile_utils::style; use zellij_tile_utils::style;
use first_line::{ctrl_keys, superkey}; use first_line::{ctrl_keys, superkey};
use second_line::keybinds; use second_line::{keybinds, text_copied_hint};
// for more of these, copy paste from: https://en.wikipedia.org/wiki/Box-drawing_character // for more of these, copy paste from: https://en.wikipedia.org/wiki/Box-drawing_character
static ARROW_SEPARATOR: &str = ""; static ARROW_SEPARATOR: &str = "";
@ -17,6 +17,7 @@ static MORE_MSG: &str = " ... ";
#[derive(Default)] #[derive(Default)]
struct State { struct State {
mode_info: ModeInfo, mode_info: ModeInfo,
diplay_text_copied_hint: bool,
} }
register_plugin!(State); register_plugin!(State);
@ -136,12 +137,25 @@ impl ZellijPlugin for State {
set_selectable(false); set_selectable(false);
set_invisible_borders(true); set_invisible_borders(true);
set_fixed_height(2); set_fixed_height(2);
subscribe(&[EventType::ModeUpdate]); subscribe(&[
EventType::ModeUpdate,
EventType::CopyToClipboard,
EventType::InputReceived,
]);
} }
fn update(&mut self, event: Event) { fn update(&mut self, event: Event) {
if let Event::ModeUpdate(mode_info) = event { match event {
self.mode_info = mode_info; Event::ModeUpdate(mode_info) => {
self.mode_info = mode_info;
}
Event::CopyToClipboard => {
self.diplay_text_copied_hint = true;
}
Event::InputReceived => {
self.diplay_text_copied_hint = false;
}
_ => {}
} }
} }
@ -161,7 +175,11 @@ impl ZellijPlugin for State {
); );
let first_line = format!("{}{}", superkey, ctrl_keys); let first_line = format!("{}{}", superkey, ctrl_keys);
let second_line = keybinds(&self.mode_info, cols); let second_line = if self.diplay_text_copied_hint {
text_copied_hint(&self.mode_info.palette)
} else {
keybinds(&self.mode_info, cols)
};
// [48;5;238m is gray background, [0K is so that it fills the rest of the line // [48;5;238m is gray background, [0K is so that it fills the rest of the line
// [m is background reset, [0K is so that it clears the rest of the line // [m is background reset, [0K is so that it clears the rest of the line

View file

@ -375,3 +375,15 @@ pub fn keybinds(help: &ModeInfo, max_width: usize) -> LinePart {
} }
best_effort_shortcut_list(help, max_width) best_effort_shortcut_list(help, max_width)
} }
pub fn text_copied_hint(palette: &Palette) -> LinePart {
let hint = " Text copied to clipboard";
let green_color = match palette.green {
PaletteColor::Rgb((r, g, b)) => RGB(r, g, b),
PaletteColor::EightBit(color) => Fixed(color),
};
LinePart {
part: format!("{}", Style::new().fg(green_color).bold().paint(hint)),
len: hint.len(),
}
}

View file

@ -23,6 +23,10 @@ fn route_action(
to_server: &SenderWithContext<ServerInstruction>, to_server: &SenderWithContext<ServerInstruction>,
) -> bool { ) -> bool {
let mut should_break = false; let mut should_break = false;
session
.senders
.send_to_plugin(PluginInstruction::Update(None, Event::InputReceived))
.unwrap();
match action { match action {
Action::Write(val) => { Action::Write(val) => {
session session

View file

@ -2871,6 +2871,9 @@ impl Tab {
let selected_text = self.get_active_pane().and_then(|p| p.get_selected_text()); let selected_text = self.get_active_pane().and_then(|p| p.get_selected_text());
if let Some(selected_text) = selected_text { if let Some(selected_text) = selected_text {
self.write_selection_to_clipboard(&selected_text); self.write_selection_to_clipboard(&selected_text);
self.senders
.send_to_plugin(PluginInstruction::Update(None, Event::CopyToClipboard))
.unwrap();
} }
} }
@ -2879,6 +2882,9 @@ impl Tab {
self.senders self.senders
.send_to_server(ServerInstruction::Render(Some(output))) .send_to_server(ServerInstruction::Render(Some(output)))
.unwrap(); .unwrap();
self.senders
.send_to_plugin(PluginInstruction::Update(None, Event::CopyToClipboard))
.unwrap();
} }
fn is_inside_viewport(&self, pane_id: &PaneId) -> bool { fn is_inside_viewport(&self, pane_id: &PaneId) -> bool {
let pane_position_and_size = self.panes.get(pane_id).unwrap().position_and_size(); let pane_position_and_size = self.panes.get(pane_id).unwrap().position_and_size();

View file

@ -33,6 +33,8 @@ pub enum Event {
TabUpdate(Vec<TabInfo>), TabUpdate(Vec<TabInfo>),
KeyPress(Key), KeyPress(Key),
Timer(f64), Timer(f64),
CopyToClipboard,
InputReceived,
} }
/// Describes the different input modes, which change the way that keystrokes will be interpreted. /// Describes the different input modes, which change the way that keystrokes will be interpreted.