aboutsummaryrefslogtreecommitdiff
path: root/examples/todo/commands/configure.rs
blob: 18ace89c27b0caeef8feac04249007d785f30528 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
use crate::TodoConfig;
use anyhow::Result;
use notion::ids::{AsIdentifier, DatabaseId};
use notion::models::search::NotionSearch;
use notion::models::Database;
use notion::NotionApi;
use skim::{Skim, SkimItem, SkimItemReceiver, SkimItemSender, SkimOptions};
use std::borrow::Cow;
use std::ops::Deref;
use std::sync::Arc;

fn skim_select_database(databases: Vec<Database>) -> Result<DatabaseId> {
    let options = SkimOptions::default();

    let (sender, receiver): (SkimItemSender, SkimItemReceiver) = crossbeam_channel::bounded(500);

    struct SkimDB {
        db: Database,
    }

    impl SkimItem for SkimDB {
        fn text(&self) -> Cow<str> {
            Cow::Owned(self.db.title_plain_text())
        }
    }

    for db in databases {
        sender.send(Arc::new(SkimDB { db }))?;
    }

    // `run_with` would read and show items from the stream
    let selected_items = Skim::run_with(&options, Some(receiver))
        .filter(|out| !out.is_abort)
        .map(|out| out.selected_items)
        .unwrap_or_else(|| Vec::new());

    let db = selected_items
        .first()
        .expect("No database selected, aborting...")
        .clone();
    let db: &SkimDB = db
        .deref()
        .as_any()
        .downcast_ref()
        .expect("Couldn't cast back to SkimDB");

    let database_id = db.db.as_id();

    Ok(database_id.clone())
}

pub async fn configure(notion_api: NotionApi) -> Result<()> {
    let databases: Vec<Database> = notion_api
        .search(NotionSearch::filter_by_databases())
        .await?
        .only_databases()
        .results;

    let database_id = skim_select_database(databases)?;

    println!("Selected database's id: {}", database_id);

    let bytes = toml::to_vec(&TodoConfig {
        api_token: None,
        task_database_id: Some(database_id),
    })?;

    std::fs::write("../todo_config.toml", bytes)?;

    Ok(())
}