delfin/delfin/src/servers/server_list.rs
2024-02-14 10:45:13 -05:00

167 lines
5.3 KiB
Rust

use adw::prelude::*;
use relm4::{factory::FactoryVecDeque, prelude::*};
use crate::{
borgar::borgar_menu::BorgarMenu, config, globals::CONFIG, tr, utils::constants::PAGE_MARGIN,
};
use super::{
add_server::{AddServerDialog, AddServerOutput},
server_list_item::{ServerListItem, ServerListItemOutput},
};
pub struct ServerList {
servers: FactoryVecDeque<ServerListItem>,
add_server_dialog: Option<Controller<AddServerDialog>>,
borgar: Controller<BorgarMenu>,
}
#[derive(Debug)]
pub enum ServerListInput {
ReloadServers,
AddServer,
ServerAdded(config::Server),
ServerSelected(DynamicIndex),
}
#[derive(Debug)]
pub enum ServerListOutput {
ServerSelected(config::Server),
}
#[relm4::component(pub)]
impl Component for ServerList {
type Init = ();
type Input = ServerListInput;
type Output = ServerListOutput;
type CommandOutput = ();
view! {
adw::NavigationPage {
set_title: tr!("server-list-page-title"),
connect_showing[sender] => move |_| {
sender.input(ServerListInput::ReloadServers);
},
#[wrap(Some)]
set_child = &adw::ToolbarView {
add_top_bar = &adw::HeaderBar {
pack_end = model.borgar.widget(),
},
#[wrap(Some)]
set_content = &adw::Clamp {
set_margin_top: PAGE_MARGIN,
adw::PreferencesGroup {
set_title: tr!("server-list.title"),
set_description: Some(tr!("server-list.description")),
#[wrap(Some)]
set_header_suffix = &gtk::Button {
connect_clicked[sender] => move |_| {
sender.input(ServerListInput::AddServer);
},
adw::ButtonContent {
set_icon_name: "list-add-symbolic",
set_label: tr!("server-list-add-server-button"),
},
},
#[local_ref]
servers_box -> gtk::ListBox {
add_css_class: "boxed-list",
set_selection_mode: gtk::SelectionMode::None,
},
gtk::ListBox {
add_css_class: "boxed-list",
set_selection_mode: gtk::SelectionMode::None,
#[watch]
set_visible: model.servers.is_empty(),
adw::ActionRow {
set_title: tr!("server-list-empty.title"),
set_subtitle: tr!("server-list-empty.subtitle"),
},
},
},
},
},
}
}
fn init(
_init: Self::Init,
root: Self::Root,
sender: relm4::ComponentSender<Self>,
) -> relm4::ComponentParts<Self> {
let servers = FactoryVecDeque::builder()
.launch(gtk::ListBox::default())
.forward(sender.input_sender(), convert_server_list_item_output);
let model = ServerList {
servers,
add_server_dialog: None,
borgar: BorgarMenu::builder().launch(None).detach(),
};
let servers_box = model.servers.widget();
let widgets = view_output!();
sender.input(ServerListInput::ReloadServers);
ComponentParts { model, widgets }
}
fn update(
&mut self,
message: Self::Input,
sender: relm4::ComponentSender<Self>,
root: &Self::Root,
) {
match message {
ServerListInput::ReloadServers => {
let mut servers = self.servers.guard();
servers.clear();
for server in &CONFIG.read().servers {
servers.push_back(server.clone());
}
}
ServerListInput::AddServer => {
self.add_server_dialog = Some(
AddServerDialog::builder()
.transient_for(root)
.launch(())
.forward(sender.input_sender(), convert_add_server_output),
);
}
ServerListInput::ServerAdded(server) => {
self.servers.guard().push_back(server.clone());
let mut config = CONFIG.write();
config.servers.push(server);
config.save().unwrap();
}
ServerListInput::ServerSelected(index) => {
let index: usize = index.current_index();
let server = &CONFIG.read().servers[index];
sender
.output(ServerListOutput::ServerSelected(server.clone()))
.unwrap();
}
};
}
}
fn convert_add_server_output(output: AddServerOutput) -> ServerListInput {
match output {
AddServerOutput::ServerAdded(server) => ServerListInput::ServerAdded(server),
}
}
fn convert_server_list_item_output(output: ServerListItemOutput) -> ServerListInput {
match output {
ServerListItemOutput::ServerSelected(index) => ServerListInput::ServerSelected(index),
}
}