Include terminal theme in live stream init payload

This commit is contained in:
Marcin Kulik
2024-02-15 15:11:50 +01:00
parent ad764088d9
commit 17121c4b61
6 changed files with 61 additions and 18 deletions

View File

@@ -1953,7 +1953,7 @@ span.ap-marker-container:hover span.ap-marker-tooltip {
.ap-terminal .bg-255 { .ap-terminal .bg-255 {
background-color: #eeeeee; background-color: #eeeeee;
} }
.asciinema-theme-asciinema { .asciinema-player-theme-asciinema {
--term-color-foreground: #cccccc; --term-color-foreground: #cccccc;
--term-color-background: #121314; --term-color-background: #121314;
--term-color-0: hsl(0, 0%, 0%); --term-color-0: hsl(0, 0%, 0%);
@@ -1976,7 +1976,7 @@ span.ap-marker-container:hover span.ap-marker-tooltip {
/* /*
Based on Dracula: https://draculatheme.com Based on Dracula: https://draculatheme.com
*/ */
.asciinema-theme-dracula { .asciinema-player-theme-dracula {
--term-color-foreground: #f8f8f2; --term-color-foreground: #f8f8f2;
--term-color-background: #282a36; --term-color-background: #282a36;
--term-color-0: #21222c; --term-color-0: #21222c;
@@ -1997,7 +1997,7 @@ span.ap-marker-container:hover span.ap-marker-tooltip {
--term-color-15: #ffffff; --term-color-15: #ffffff;
} }
/* Based on Monokai from base16 collection - https://github.com/chriskempson/base16 */ /* Based on Monokai from base16 collection - https://github.com/chriskempson/base16 */
.asciinema-theme-monokai { .asciinema-player-theme-monokai {
--term-color-foreground: #f8f8f2; --term-color-foreground: #f8f8f2;
--term-color-background: #272822; --term-color-background: #272822;
--term-color-0: #272822; --term-color-0: #272822;
@@ -2015,7 +2015,7 @@ span.ap-marker-container:hover span.ap-marker-tooltip {
Based on Nord: https://github.com/arcticicestudio/nord Based on Nord: https://github.com/arcticicestudio/nord
Via: https://github.com/neilotoole/asciinema-theme-nord Via: https://github.com/neilotoole/asciinema-theme-nord
*/ */
.asciinema-theme-nord { .asciinema-player-theme-nord {
--term-color-foreground: #eceff4; --term-color-foreground: #eceff4;
--term-color-background: #2e3440; --term-color-background: #2e3440;
--term-color-0: #3b4252; --term-color-0: #3b4252;
@@ -2027,7 +2027,7 @@ span.ap-marker-container:hover span.ap-marker-tooltip {
--term-color-6: #88c0d0; --term-color-6: #88c0d0;
--term-color-7: #eceff4; --term-color-7: #eceff4;
} }
.asciinema-theme-seti { .asciinema-player-theme-seti {
--term-color-foreground: #cacecd; --term-color-foreground: #cacecd;
--term-color-background: #111213; --term-color-background: #111213;
--term-color-0: #323232; --term-color-0: #323232;
@@ -2043,7 +2043,7 @@ span.ap-marker-container:hover span.ap-marker-tooltip {
/* /*
Based on Solarized Dark: https://ethanschoonover.com/solarized/ Based on Solarized Dark: https://ethanschoonover.com/solarized/
*/ */
.asciinema-theme-solarized-dark { .asciinema-player-theme-solarized-dark {
--term-color-foreground: #839496; --term-color-foreground: #839496;
--term-color-background: #002b36; --term-color-background: #002b36;
--term-color-0: #073642; --term-color-0: #073642;
@@ -2066,7 +2066,7 @@ span.ap-marker-container:hover span.ap-marker-tooltip {
/* /*
Based on Solarized Light: https://ethanschoonover.com/solarized/ Based on Solarized Light: https://ethanschoonover.com/solarized/
*/ */
.asciinema-theme-solarized-light { .asciinema-player-theme-solarized-light {
--term-color-foreground: #657b83; --term-color-foreground: #657b83;
--term-color-background: #fdf6e3; --term-color-background: #fdf6e3;
--term-color-0: #073642; --term-color-0: #073642;
@@ -2086,16 +2086,16 @@ span.ap-marker-container:hover span.ap-marker-tooltip {
--term-color-14: #93a1a1; --term-color-14: #93a1a1;
--term-color-15: #fdf6e3; --term-color-15: #fdf6e3;
} }
.asciinema-theme-solarized-light .ap-overlay-start .ap-play-button svg .ap-play-btn-fill { .asciinema-player-theme-solarized-light .ap-overlay-start .ap-play-button svg .ap-play-btn-fill {
fill: var(--term-color-1); fill: var(--term-color-1);
} }
.asciinema-theme-solarized-light .ap-overlay-start .ap-play-button svg .ap-play-btn-stroke { .asciinema-player-theme-solarized-light .ap-overlay-start .ap-play-button svg .ap-play-btn-stroke {
stroke: var(--term-color-1); stroke: var(--term-color-1);
} }
/* /*
Based on Tango: https://en.wikipedia.org/wiki/Tango_Desktop_Project Based on Tango: https://en.wikipedia.org/wiki/Tango_Desktop_Project
*/ */
.asciinema-theme-tango { .asciinema-player-theme-tango {
--term-color-foreground: #cccccc; --term-color-foreground: #cccccc;
--term-color-background: #121314; --term-color-background: #121314;
--term-color-0: #000000; --term-color-0: #000000;

File diff suppressed because one or more lines are too long

View File

@@ -45,7 +45,6 @@ impl Cli {
let record_input = self.input || config.cmd_stream_input(); let record_input = self.input || config.cmd_stream_input();
let exec_command = super::build_exec_command(command.as_ref().cloned()); let exec_command = super::build_exec_command(command.as_ref().cloned());
let exec_extra_env = super::build_exec_extra_env(); let exec_extra_env = super::build_exec_extra_env();
let mut streamer = streamer::Streamer::new(self.listen_addr, record_input, keys, notifier);
logger::info!( logger::info!(
"Streaming session started, web server listening on http://{}", "Streaming session started, web server listening on http://{}",
@@ -64,6 +63,14 @@ impl Cli {
Box::new(tty::NullTty::open()?) Box::new(tty::NullTty::open()?)
}; };
let mut streamer = streamer::Streamer::new(
self.listen_addr,
record_input,
keys,
notifier,
tty.get_theme(),
);
self.init_logging()?; self.init_logging()?;
pty::exec( pty::exec(

View File

@@ -27,7 +27,7 @@ fn encode_event(event: session::Event) -> Vec<u8> {
use session::Event::*; use session::Event::*;
match event { match event {
Init(size, time, init) => { Init(size, time, theme, init) => {
let (cols, rows): (u16, u16) = (size.0, size.1); let (cols, rows): (u16, u16) = (size.0, size.1);
let cols_bytes = cols.to_le_bytes(); let cols_bytes = cols.to_le_bytes();
let rows_bytes = rows.to_le_bytes(); let rows_bytes = rows.to_le_bytes();
@@ -40,6 +40,29 @@ fn encode_event(event: session::Event) -> Vec<u8> {
msg.extend_from_slice(&cols_bytes); // 2 bytes msg.extend_from_slice(&cols_bytes); // 2 bytes
msg.extend_from_slice(&rows_bytes); // 2 bytes msg.extend_from_slice(&rows_bytes); // 2 bytes
msg.extend_from_slice(&time_bytes); // 4 bytes msg.extend_from_slice(&time_bytes); // 4 bytes
match theme {
Some(theme) => {
msg.push(1);
msg.push(theme.fg.r);
msg.push(theme.fg.g);
msg.push(theme.fg.b);
msg.push(theme.bg.r);
msg.push(theme.bg.g);
msg.push(theme.bg.b);
for color in &theme.palette {
msg.push(color.r);
msg.push(color.g);
msg.push(color.b);
}
}
None => {
msg.push(0);
}
}
msg.extend_from_slice(&init_len_bytes); // 4 bytes msg.extend_from_slice(&init_len_bytes); // 4 bytes
msg.extend_from_slice(init.as_bytes()); // init_len bytes msg.extend_from_slice(init.as_bytes()); // init_len bytes

View File

@@ -27,6 +27,7 @@ pub struct Streamer {
paused: bool, paused: bool,
prefix_mode: bool, prefix_mode: bool,
listen_addr: net::SocketAddr, listen_addr: net::SocketAddr,
theme: Option<tty::Theme>,
} }
enum Event { enum Event {
@@ -41,6 +42,7 @@ impl Streamer {
record_input: bool, record_input: bool,
keys: KeyBindings, keys: KeyBindings,
notifier: Box<dyn Notifier>, notifier: Box<dyn Notifier>,
theme: Option<tty::Theme>,
) -> Self { ) -> Self {
let (notifier_tx, notifier_rx) = std::sync::mpsc::channel(); let (notifier_tx, notifier_rx) = std::sync::mpsc::channel();
let (pty_tx, pty_rx) = mpsc::unbounded_channel(); let (pty_tx, pty_rx) = mpsc::unbounded_channel();
@@ -59,6 +61,7 @@ impl Streamer {
paused: false, paused: false,
prefix_mode: false, prefix_mode: false,
listen_addr, listen_addr,
theme,
} }
} }
@@ -84,10 +87,11 @@ impl pty::Recorder for Streamer {
let listener = TcpListener::bind(self.listen_addr)?; let listener = TcpListener::bind(self.listen_addr)?;
let runtime = build_tokio_runtime(); let runtime = build_tokio_runtime();
let server = runtime.spawn(server::serve(listener, clients_tx, server_shutdown_rx)); let server = runtime.spawn(server::serve(listener, clients_tx, server_shutdown_rx));
let theme = self.theme.clone();
self.event_loop_handle = wrap_thread_handle(thread::spawn(move || { self.event_loop_handle = wrap_thread_handle(thread::spawn(move || {
runtime.block_on(async move { runtime.block_on(async move {
event_loop(pty_rx, &mut clients_rx, tty_size).await; event_loop(pty_rx, &mut clients_rx, tty_size, theme).await;
let _ = server_shutdown_tx.send(()); let _ = server_shutdown_tx.send(());
let _ = server.await; let _ = server.await;
let _ = clients_rx.recv().await; let _ = clients_rx.recv().await;
@@ -162,8 +166,9 @@ async fn event_loop(
mut events: mpsc::UnboundedReceiver<Event>, mut events: mpsc::UnboundedReceiver<Event>,
clients: &mut mpsc::Receiver<session::Client>, clients: &mut mpsc::Receiver<session::Client>,
tty_size: tty::TtySize, tty_size: tty::TtySize,
theme: Option<tty::Theme>,
) { ) {
let mut session = session::Session::new(tty_size); let mut session = session::Session::new(tty_size, theme);
loop { loop {
tokio::select! { tokio::select! {

View File

@@ -11,11 +11,12 @@ pub struct Session {
stream_time: u64, stream_time: u64,
last_event_time: Instant, last_event_time: Instant,
tty_size: tty::TtySize, tty_size: tty::TtySize,
theme: Option<tty::Theme>,
} }
#[derive(Clone)] #[derive(Clone)]
pub enum Event { pub enum Event {
Init(tty::TtySize, u64, Option<String>), Init(tty::TtySize, u64, Option<tty::Theme>, Option<String>),
Stdout(u64, String), Stdout(u64, String),
Resize(u64, tty::TtySize), Resize(u64, tty::TtySize),
} }
@@ -28,7 +29,7 @@ pub struct Subscription {
} }
impl Session { impl Session {
pub fn new(tty_size: tty::TtySize) -> Self { pub fn new(tty_size: tty::TtySize, theme: Option<tty::Theme>) -> Self {
let (broadcast_tx, _) = broadcast::channel(1024); let (broadcast_tx, _) = broadcast::channel(1024);
Self { Self {
@@ -37,6 +38,7 @@ impl Session {
stream_time: 0, stream_time: 0,
last_event_time: Instant::now(), last_event_time: Instant::now(),
tty_size, tty_size,
theme,
} }
} }
@@ -63,7 +65,13 @@ impl Session {
} }
pub fn subscribe(&self) -> Subscription { pub fn subscribe(&self) -> Subscription {
let init = Event::Init(self.tty_size, self.elapsed_time(), Some(self.vt.dump())); let init = Event::Init(
self.tty_size,
self.elapsed_time(),
self.theme.clone(),
Some(self.vt.dump()),
);
let broadcast_rx = self.broadcast_tx.subscribe(); let broadcast_rx = self.broadcast_tx.subscribe();
Subscription { init, broadcast_rx } Subscription { init, broadcast_rx }