koibumi-sync 0.0.1

An experimental Bitmessage client (sync version)
use copypasta::ClipboardProvider;
use crossbeam_channel::Sender;
use log::error;

use koibumi_box_sync::Contact;
use koibumi_common_sync::boxes::{Boxes, DEFAULT_USER_ID};
use koibumi_node_sync::Command as NodeCommand;

use crate::{config::Config as GuiConfig, ids::Ids};

#[derive(Clone, Debug, Default)]
pub(crate) struct Tab {}

impl Tab {
    // Draw the Ui.
    #[allow(clippy::too_many_arguments)]
    pub(crate) fn set_widgets(
        &mut self,
        ui: &mut conrod_core::UiCell,
        ids: &mut Ids,
        config: &GuiConfig,
        contacts: &[Contact],
        selected_index: Option<usize>,
        boxes: &mut Option<Boxes>,
        command_sender: &mut Sender<NodeCommand>,
    ) {
        let text_size = config.text_size();
        let font_id = ui.fonts.ids().next().unwrap();

        if boxes.is_none() {
            return;
        }
        let boxes = boxes.as_mut().unwrap();

        use conrod_core::{
            color,
            position::{Place, Relative},
            text, widget, Colorable, Labelable, Positionable, Sizeable, Widget,
        };

        widget::Canvas::new()
            .flow_down(&[
                (
                    ids.contacts_list_canvas,
                    widget::Canvas::new().pad_bottom(2.0),
                ),
                (
                    ids.contacts_buttons_canvas,
                    widget::Canvas::new()
                        .length((text_size as f64 + 8.0 + 4.0) * 1.0 + 4.0)
                        .pad_bottom(2.0),
                ),
            ])
            .top_left_of(ids.tabs_body)
            .wh_of(ids.tabs_body)
            .set(ids.contacts, ui);

        let (mut items, scrollbar) = widget::List::flow_down(contacts.len())
            .top_left_of(ids.contacts_list_canvas)
            .wh_of(ids.contacts_list_canvas)
            .item_size(text_size as f64 + 8.0)
            .scrollbar_on_top()
            .set(ids.contacts_list, ui);

        while let Some(item) = items.next(ui) {
            let i = item.i;
            let label = boxes.user().rich_alias(&contacts[i].address().to_string());
            let c = if let Some(index) = selected_index {
                if i == index {
                    color::DARK_YELLOW
                } else {
                    color::DARK_CHARCOAL
                }
            } else {
                color::DARK_CHARCOAL
            };
            for _v in item.set(
                widget::Button::new()
                    .label(&label)
                    .label_color(color::WHITE)
                    .label_font_size(text_size as u32)
                    .label_x(Relative::Place(Place::Start(Some(2.0))))
                    .color(c),
                ui,
            ) {
                boxes.set_selected_contact_index(Some(i));
            }
        }

        if let Some(s) = scrollbar {
            s.set(ui)
        }

        let label = "Copy to clipboard";
        let width = text::line::width(label, ui.fonts.get(font_id).unwrap(), text_size as u32);
        for _click in widget::Button::new()
            .top_left_with_margins_on(ids.contacts_buttons_canvas, 2.0, 2.0)
            .w_h(width + 8.0, text_size as f64 + 8.0)
            .label_font_size(text_size as u32)
            .label(label)
            .color(color::DARK_GRAY)
            .label_color(color::WHITE)
            .set(ids.contacts_copy_button, ui)
        {
            if boxes.selected_contact_index().is_none() {
                continue;
            }
            let index = boxes.selected_contact_index().unwrap();
            let address = boxes.user().contacts()[index].address();
            let ctx = copypasta::ClipboardContext::new();
            if let Err(err) = ctx {
                error!("{}", err);
                continue;
            }
            let mut ctx = ctx.unwrap();
            if let Err(err) = ctx.set_contents(address.to_string()) {
                error!("{}", err);
            }
        }

        let label = "Subscribe";
        let width = text::line::width(label, ui.fonts.get(font_id).unwrap(), text_size as u32);
        for _click in widget::Button::new()
            .right_from(ids.contacts_copy_button, 4.0)
            .w_h(width + 8.0, text_size as f64 + 8.0)
            .label_font_size(text_size as u32)
            .label(label)
            .color(color::DARK_GRAY)
            .label_color(color::WHITE)
            .set(ids.contacts_subscribe_button, ui)
        {
            if boxes.selected_contact_index().is_none() {
                continue;
            }
            let index = boxes.selected_contact_index().unwrap();
            let address = boxes.user().contacts()[index].address().clone();
            if boxes.user().subscriptions().contains(&address) {
                continue;
            }
            if let Err(err) = boxes.manager().subscribe(DEFAULT_USER_ID, &address) {
                error!("{}", err);
                continue;
            }
            if let Err(err) = command_sender.send(NodeCommand::Subscribe {
                id: DEFAULT_USER_ID.to_vec(),
                address: address.clone(),
            }) {
                error!("{}", err);
                continue;
            }
            boxes.user_mut().subscriptions_mut().push(address);
        }
    }
}