🗝
summary refs log tree commit diff
path: root/src/tui/accounts.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/tui/accounts.rs')
-rw-r--r--src/tui/accounts.rs169
1 files changed, 169 insertions, 0 deletions
diff --git a/src/tui/accounts.rs b/src/tui/accounts.rs
new file mode 100644
index 0000000..a43028c
--- /dev/null
+++ b/src/tui/accounts.rs
@@ -0,0 +1,169 @@
+use std::{cell::RefCell, rc::Rc};
+
+use cursive::{
+    view::Nameable,
+    views::{Button, Dialog, LinearLayout, SelectView, TextArea},
+    Cursive,
+};
+
+use crate::ipc::{
+    DeleteAccountRequest, GetAccountRequest, ListAccountsRequest, UpdateScopesRequest,
+};
+
+use super::{CursiveIpc, ToTextView, ViewExt};
+
+pub fn show(siv: &mut Cursive) {
+    if let Some(accounts) = siv.ipc(ListAccountsRequest {}) {
+        siv.add_layer(
+            SelectView::new()
+                .autojump()
+                .with_all_str(accounts.names)
+                .on_submit(|siv, name: &str| {
+                    manage_account(siv, name);
+                })
+                .float("accounts"),
+        );
+    }
+}
+
+fn manage_account(siv: &mut Cursive, name: &str) {
+    let name = name.to_string();
+    if let Some(_) = siv.ipc(GetAccountRequest { name: name.clone() }) {
+        siv.add_layer(
+            LinearLayout::vertical()
+                .child({
+                    let name = name.clone();
+                    enum SelectOption {
+                        Back,
+                        Scopes,
+                        Delete,
+                    }
+                    SelectView::new()
+                        .item("back", SelectOption::Back)
+                        .item("scopes", SelectOption::Scopes)
+                        .item("delete", SelectOption::Delete)
+                        .on_submit(move |siv, opt| match opt {
+                            SelectOption::Back => {
+                                siv.pop_layer();
+                            }
+                            SelectOption::Scopes => edit_scopes(siv, &name),
+                            SelectOption::Delete => delete_account(siv, &name),
+                        })
+                })
+                .float(&name),
+        )
+    }
+}
+
+fn edit_scopes(siv: &mut Cursive, name: &str) {
+    let name = name.to_string();
+    let Some(account) = siv.ipc(GetAccountRequest { name: name.clone() }) else {
+        siv.pop_layer();
+        return; // it was just there!
+    };
+    let scopes = Rc::new(RefCell::new(account.scopes));
+    enum SelectOption {
+        Scope(String),
+        Back,
+        Add,
+    }
+    siv.add_layer(
+        SelectView::new()
+            .autojump()
+            .item("back", SelectOption::Back)
+            .item("add", SelectOption::Add)
+            .with_all(
+                scopes
+                    .clone()
+                    .borrow()
+                    .iter()
+                    .map(|scope| (scope.to_string(), SelectOption::Scope(scope.clone()))),
+            )
+            .on_submit(move |siv, opt| {
+                match opt {
+                    SelectOption::Scope(scope) => {
+                        let mut scopes = scopes.borrow_mut();
+                        let index = scopes
+                            .iter()
+                            .enumerate()
+                            .find(|(_, check)| *check == scope)
+                            .unwrap()
+                            .0;
+                        scopes.swap_remove(index);
+                        ipc_update_scopes(siv, &name, &scopes);
+                        siv.pop_layer();
+                        edit_scopes(siv, &name);
+                    }
+                    SelectOption::Back => {
+                        siv.pop_layer();
+                    }
+                    SelectOption::Add => add_scope(siv, name.clone(), scopes.clone()),
+                };
+            })
+            .float("edit scopes"),
+    );
+}
+
+fn add_scope(siv: &mut Cursive, name: String, scopes: Rc<RefCell<Vec<String>>>) {
+    siv.add_layer(
+        LinearLayout::vertical()
+            .child(TextArea::new().with_name("scope"))
+            .child(Button::new("add", {
+                move |siv| {
+                    let text_area = siv.find_name::<TextArea>("scope").unwrap();
+                    let scope = text_area.get_content();
+                    if scope.is_empty() {
+                        siv.pop_layer();
+                        return;
+                    }
+                    let mut scopes = scopes.borrow_mut();
+                    scopes.push(scope.to_string());
+                    ipc_update_scopes(siv, &name, &scopes);
+                    siv.pop_layer();
+                    siv.pop_layer();
+                    edit_scopes(siv, &name);
+                }
+            }))
+            .float("add scope"),
+    )
+}
+
+fn ipc_update_scopes(siv: &mut Cursive, name: &str, scopes: &Vec<String>) {
+    siv.ipc(UpdateScopesRequest {
+        account: name.to_string(),
+        scopes: scopes.clone(),
+    });
+}
+
+fn delete_account(siv: &mut Cursive, name: &str) {
+    let name = name.to_string();
+    siv.add_layer(
+        LinearLayout::vertical()
+            .child(format!("delete {name}?").text_view())
+            .child(TextArea::new().with_name("confirm"))
+            .child(Button::new("submit", move |siv| {
+                if let Some(confirm) = siv.find_name::<TextArea>("confirm") {
+                    if confirm.get_content() == "yes" {
+                        if siv
+                            .ipc(DeleteAccountRequest { name: name.clone() })
+                            .is_some()
+                        {
+                            siv.add_layer(Dialog::around("success".text_view()).button(
+                                "ok",
+                                |siv| {
+                                    // all the way back to the root
+                                    siv.pop_layer();
+                                    siv.pop_layer();
+                                    siv.pop_layer();
+                                    siv.pop_layer();
+                                },
+                            ))
+                        }
+                    } else {
+                        siv.pop_layer();
+                    }
+                }
+            }))
+            .float("are you sure"),
+    );
+}