Radish alpha
r
Radicle terminal user interface
Radicle
Git (anonymous pull)
Log in to clone via SSH
refactor: Generalize event handling for forms
Erik Kundt committed 2 years ago
commit de2362134ac06bdf7c021795a207b079c4cfce08
parent 9b3095e47068cec5b7ac4f90b56833a45efc74b0
3 files changed +15 -69
modified src/app.rs
@@ -110,6 +110,7 @@ pub enum Message {
    Issue(IssueMessage),
    Patch(PatchMessage),
    NavigationChanged(u16),
+
    FormSubmitted(String),
    Popup(PopupMessage),
    Tick,
    Quit,
modified src/app/event.rs
@@ -14,7 +14,7 @@ use radicle_tui::ui::widget::{issue, patch};

use radicle_tui::ui::widget::Widget;

-
use super::{IssueCid, IssueCobMessage, IssueMessage, Message, PatchMessage, PopupMessage};
+
use super::{IssueCid, IssueMessage, Message, PatchMessage, PopupMessage};

/// Since the framework does not know the type of messages that are being
/// passed around in the app, the following handlers need to be implemented for
@@ -132,7 +132,7 @@ impl tuirealm::Component<Message, NoUserEvent> for Widget<issue::IssueDetails> {
    }
}

-
impl tuirealm::Component<Message, NoUserEvent> for Widget<issue::NewForm> {
+
impl tuirealm::Component<Message, NoUserEvent> for Widget<Form> {
    fn on(&mut self, event: Event<NoUserEvent>) -> Option<Message> {
        match event {
            Event::Keyboard(KeyEvent {
@@ -190,64 +190,9 @@ impl tuirealm::Component<Message, NoUserEvent> for Widget<issue::NewForm> {
                code: Key::Char('s'),
                modifiers: KeyModifiers::CONTROL,
            }) => {
-
                match self.perform(Cmd::Submit) {
-
                    CmdResult::Submit(State::Linked(mut states)) => {
-
                        let mut missing_values = vec![];
-

-
                        let title = match states.front() {
-
                            Some(State::One(StateValue::String(title))) if !title.is_empty() => {
-
                                Some(title.clone())
-
                            }
-
                            _ => None,
-
                        };
-
                        states.pop_front();
-

-
                        let tags = match states.front() {
-
                            Some(State::One(StateValue::String(tags))) => Some(tags.clone()),
-
                            _ => Some(String::from("[]")),
-
                        };
-
                        states.pop_front();
-

-
                        let assignees = match states.front() {
-
                            Some(State::One(StateValue::String(assignees))) => {
-
                                Some(assignees.clone())
-
                            }
-
                            _ => Some(String::from("[]")),
-
                        };
-
                        states.pop_front();
-

-
                        let description = match states.front() {
-
                            Some(State::One(StateValue::String(description)))
-
                                if !description.is_empty() =>
-
                            {
-
                                Some(description.clone())
-
                            }
-
                            _ => None,
-
                        };
-
                        states.pop_front();
-

-
                        if title.is_none() {
-
                            missing_values.push("title");
-
                        }
-
                        if description.is_none() {
-
                            missing_values.push("description");
-
                        }
-

-
                        // show error popup if missing.
-
                        if !missing_values.is_empty() {
-
                            let error = format!("Missing fields: {:?}", missing_values);
-
                            Some(Message::Popup(PopupMessage::Error(error)))
-
                        } else {
-
                            Some(Message::Issue(IssueMessage::Cob(IssueCobMessage::Create {
-
                                title: title.unwrap(),
-
                                tags: tags.unwrap(),
-
                                assignees: assignees.unwrap(),
-
                                description: description.unwrap(),
-
                            })))
-
                        }
-
                    }
-
                    _ => None,
-
                }
+
                self.perform(Cmd::Submit);
+
                self.query(tuirealm::Attribute::Custom(Form::PROP_ID))
+
                    .map(|cid| Message::FormSubmitted(cid.unwrap_string()))
            }
            Event::Keyboard(KeyEvent { code: Key::Esc, .. }) => {
                Some(Message::Issue(IssueMessage::HideForm))
modified src/ui/widget/common/form.rs
@@ -187,6 +187,8 @@ impl Form {
    pub const CMD_NEWLINE: &str = "cmd-newline";
    pub const CMD_PASTE: &str = "cmd-paste";

+
    pub const PROP_ID: &str = "prop-id";
+

    pub fn new(_theme: Theme, inputs: Vec<Box<dyn MockComponent>>) -> Self {
        let state = FormState::new(Some(0), inputs.len());

@@ -228,7 +230,12 @@ impl WidgetComponent for Form {
    }

    fn state(&self) -> State {
-
        State::None
+
        let states = self
+
            .inputs
+
            .iter()
+
            .map(|input| input.state())
+
            .collect::<LinkedList<_>>();
+
        State::Linked(states)
    }

    fn perform(&mut self, _properties: &Props, cmd: Cmd) -> CmdResult {
@@ -241,14 +248,7 @@ impl WidgetComponent for Form {
                self.state.focus_next();
                CmdResult::None
            }
-
            Cmd::Submit => {
-
                let states = self
-
                    .inputs
-
                    .iter()
-
                    .map(|input| input.state())
-
                    .collect::<LinkedList<_>>();
-
                CmdResult::Submit(State::Linked(states))
-
            }
+
            Cmd::Submit => CmdResult::Submit(self.state()),
            _ => {
                let focus = self.state.focus().unwrap_or(0);
                if let Some(input) = self.inputs.get_mut(focus) {