quinjet 0.0.50

A fast, live, keyboard-first Git source-control interface for the terminal
#[cfg_attr(not(test), expect(clippy::wildcard_imports, reason = "shared"))]
use super::*;

impl App {
    #[expect(
        clippy::too_many_lines,
        reason = "the exhaustive action match keeps mouse and keyboard behavior aligned"
    )]
    pub(super) fn handle_modal_action(
        &mut self,
        action: ModalAction,
        effects: &mut Vec<AppEffect>,
    ) {
        match action {
            ModalAction::CommitSubmit => {
                let Some(Modal::Commit { input, amend }) = self.modal.take() else {
                    return;
                };
                let message = input.value.trim().to_owned();
                if message.is_empty() {
                    self.modal = Some(Modal::Commit { input, amend });
                    return;
                }
                if amend {
                    self.modal = Some(Modal::Confirm {
                        title: "Amend Commit?".to_owned(),
                        message: "Replace the previous commit with this message?".to_owned(),
                        action: ConfirmAction::Operate(GitOperation::Commit {
                            message,
                            amend: true,
                        }),
                    });
                } else {
                    self.queue_operation(
                        GitOperation::Commit {
                            message,
                            amend: false,
                        },
                        effects,
                    );
                }
            }
            ModalAction::CommitCancel | ModalAction::ConfirmNo => {
                self.modal = None;
            }
            ModalAction::CommitToggleAmend => {
                if let Some(Modal::Commit { amend, .. }) = &mut self.modal {
                    *amend = !*amend;
                }
            }
            ModalAction::ConfirmYes => {
                let Some(Modal::Confirm { action, .. }) = self.modal.take() else {
                    return;
                };
                match action {
                    ConfirmAction::Operate(operation) => {
                        self.queue_operation(operation, effects);
                    }
                    ConfirmAction::OpenPrompt { title, kind } => {
                        self.modal = Some(Modal::Prompt {
                            title,
                            input: TextBuffer::default(),
                            kind,
                        });
                    }
                    ConfirmAction::PullRequest {
                        pull_request,
                        operation,
                    } => {
                        self.queue_pull_request_operation(*pull_request, operation, effects);
                    }
                    ConfirmAction::PullRequestReview(operation) => {
                        self.queue_pull_request_review_operation(operation, effects);
                    }
                }
            }
            ModalAction::SwitchSshMachine(index) => {
                let Some(Modal::Projects { mode, .. }) = self.modal.as_ref() else {
                    return;
                };
                let Some(context) = self.ssh_context.as_ref() else {
                    return;
                };
                if let Some(machine) = context.machines.get(index)
                    && machine.accessible
                    && machine.target != context.current
                {
                    effects.push(AppEffect::SwitchSshMachine(crate::ssh::SshSwitch {
                        index,
                        mode: if *mode == ProjectOpenMode::NewTab {
                            crate::ssh::SshProjectOpenMode::New
                        } else {
                            crate::ssh::SshProjectOpenMode::Current
                        },
                    }));
                }
            }
            ModalAction::PullRequestAction(index) => {
                let Some(Modal::PullRequestActions { items, .. }) = self.modal.take() else {
                    return;
                };
                if let Some(item) = items.get(index).copied() {
                    self.handle_pr_action_item(item);
                }
            }
            ModalAction::PullRequestReviewThreadAction(index) => {
                let Some(Modal::PullRequestReviewThreadActions { items, .. }) = self.modal.take()
                else {
                    return;
                };
                if let Some(item) = items.get(index).cloned() {
                    self.handle_review_thread_action(item, effects);
                }
            }
            ModalAction::PullRequestReviewDecision(index) => {
                if let Some(Modal::PullRequestReviewSubmit { decision, .. }) = &mut self.modal
                    && let Some(selected) = PullRequestReviewDecision::ALL.get(index)
                {
                    *decision = *selected;
                }
            }
            ModalAction::ConflictOurs
            | ModalAction::ConflictTheirs
            | ModalAction::ConflictResolved => {
                let Some(Modal::Conflict { change }) = self.modal.take() else {
                    return;
                };
                let operation = match action {
                    ModalAction::ConflictOurs => GitOperation::ResolveConflict {
                        path: change.path,
                        choice: ConflictChoice::Ours,
                    },
                    ModalAction::ConflictTheirs => GitOperation::ResolveConflict {
                        path: change.path,
                        choice: ConflictChoice::Theirs,
                    },
                    ModalAction::ConflictResolved => GitOperation::Stage(vec![change.path]),
                    _ => return,
                };
                self.queue_operation(operation, effects);
            }
        }
    }
}