use std::rc::Rc;
use terrazzo::autoclone;
use terrazzo::html;
use terrazzo::prelude::*;
use terrazzo::widgets::tabs::TabsDescriptor;
use terrazzo::widgets::tabs::TabsState;
use super::terminal_tab::TerminalTab;
use super::ui::TerminalsState;
use crate::api::client_address::ClientAddress;
use crate::assets::icons;
use crate::frontend::menu::menu;
use crate::frontend::remotes::RemotesState;
use crate::terminal::terminal_tabs::add_tab::create_terminal;
use crate::terminal_id::TerminalId;
mod add_tab;
mod move_tab;
terrazzo_css::import_style!(style, "terminal_tabs.scss");
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct TerminalTabs {
terminal_tabs: Rc<Vec<TerminalTab>>,
}
impl From<Rc<Vec<TerminalTab>>> for TerminalTabs {
fn from(terminal_tabs: Rc<Vec<TerminalTab>>) -> Self {
Self { terminal_tabs }
}
}
impl TabsDescriptor for TerminalTabs {
type TabDescriptor = TerminalTab;
type State = TerminalsState;
fn tab_descriptors(&self) -> &[Self::TabDescriptor] {
&self.terminal_tabs
}
#[html]
fn before_titles(&self, state: &TerminalsState) -> impl IntoIterator<Item = impl Into<XNode>> {
Some(menu(state.tile.clone()))
}
#[autoclone]
#[html]
fn after_titles(&self, state: &TerminalsState) -> impl IntoIterator<Item = impl Into<XNode>> {
let remotes_state = RemotesState::new();
[div(
class = style::ADD_TAB_ICON,
#[cfg(not(feature = "client-prod"))]
class = "add-tab-icon",
key = "add-tab-icon",
div(
class %= add_tab::active(remotes_state.remotes.clone()),
img(src = icons::add_tab()),
click = move |_| {
autoclone!(state);
add_tab::create_terminal(state.clone(), ClientAddress::default())
},
mouseenter = remotes_state.mouseenter(),
),
mouseleave = remotes_state.mouseleave(),
remotes_state.show_remotes_dropdown(
|remote| {
let remote_name = if remote.is_empty() {
"Local".into()
} else {
format!("{remote} ⏎")
};
(remote_name, None)
},
move |_, remote| {
autoclone!(state);
create_terminal(state.clone(), remote)
},
),
)]
}
}
impl TerminalTabs {
pub fn add_tab(mut self, new: TerminalTab) -> Self {
let terminal_tabs = Ptr::make_mut(&mut self.terminal_tabs);
terminal_tabs.push(new);
self
}
pub fn remove_tab(mut self, id: &TerminalId) -> Self {
let terminal_tabs = Ptr::make_mut(&mut self.terminal_tabs);
terminal_tabs.retain(|tab| tab.address.id != *id);
self
}
pub fn lookup_tab(&self, id: &TerminalId) -> Option<&TerminalTab> {
self.terminal_tabs.iter().find(|tab| tab.address.id == *id)
}
}
impl TabsState for TerminalsState {
type TabDescriptor = TerminalTab;
fn move_tab(&self, after_tab: Option<TerminalTab>, moved_tab_key: String) {
move_tab::move_tab(self.clone(), after_tab, moved_tab_key)
}
fn drag_key() -> &'static str {
"terminal_id"
}
fn zone_id(&self) -> Option<String> {
format!("tile_id:{}", self.tile.id).into()
}
}