summaryrefslogtreecommitdiffstats
path: root/src/components/message_composer.rs
blob: 6b34298732ea661ba6795afe1625421db69907ea (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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
use filamento::chat::Body;
use jid::BareJID;
use js_sys::{wasm_bindgen::UnwrapThrowExt, Object, Reflect, JSON};
use leptos::{html::Div, prelude::*, task::spawn_local};
use overlay_scrollbars::OverlayScrollbars;
use tracing::debug;

use crate::client::Client;

#[component]
pub fn ChatViewMessageComposer(chat: BareJID) -> impl IntoView {
    let message_input: NodeRef<Div> = NodeRef::new();

    // TODO: load last message draft
    let new_message = RwSignal::new("".to_string());
    let client: Client = use_context().expect("no client in context");
    let client = RwSignal::new(client);
    let (shift_pressed, set_shift_pressed) = signal(false);

    let send_message = move || {
        let value = chat.clone();
        spawn_local(async move {
            match client
                .read()
                .send_message(
                    value,
                    Body {
                        body: new_message.get(),
                    },
                )
                .await
            {
                Ok(_) => {
                    new_message.set("".to_string());
                    message_input
                        .write()
                        .as_ref()
                        .expect("message input div not mounted")
                        .set_text_content(Some(""));
                }
                Err(e) => tracing::error!("message send error: {}", e),
            }
        })
    };

    let _focus = Effect::new(move |_| {
        if let Some(input) = message_input.get() {
            let _ = input.focus();
            // TODO: set the last draft
            input.set_text_content(Some(""));
            // input.style("height: 0");
            // let height = input.scroll_height();
            // input.style(format!("height: {}px", height));
        }
    });

    // let on_input = move |ev: Event| {
    //     // let keyboard_event: KeyboardEvent = ev.try_into().unwrap();
    //     debug!("got input event");
    //     let key= event_target_value(&ev);
    //     new_message.set(key);
    //     debug!("set new message");
    // };
    //

    let composer: NodeRef<Div> = NodeRef::new();

    let _scrollbars = Effect::new(move |_| {
        if let Some(buffer) = composer.get() {
            if let Some(viewport) = message_input.get() {
                let scrollbars_obj = Object::new();
                Reflect::set(&scrollbars_obj, &"theme".into(), &"os-macaw".into()).unwrap_throw();
                Reflect::set(&scrollbars_obj, &"autoHide".into(), &"leave".into()).unwrap_throw();
                let options_obj = Object::new();
                Reflect::set(&options_obj, &"scrollbars".into(), &scrollbars_obj).unwrap_throw();

                let elements_obj = Object::new();
                Reflect::set(&elements_obj, &"viewport".into(), &viewport.into()).unwrap_throw();
                let element_obj = Object::new();
                Reflect::set(&elements_obj, &"elements".into(), &elements_obj).unwrap_throw();
                Reflect::set(&element_obj, &"target".into(), &buffer.into()).unwrap_throw();
                // let element = Object::define_property(&Object::define_property(&Object::new(), &"target".into(), &buffer.into()), &"elements".into(), &Object::define_property(&Object::new(), &"viewport".into(), &viewport.into()));
                debug!(
                    "scrollable element: {}",
                    JSON::stringify(&element_obj.clone().into()).unwrap_throw()
                );
                debug!(
                    "scrollable options: {}",
                    JSON::stringify(&options_obj.clone().into()).unwrap_throw()
                );
                OverlayScrollbars(element_obj, options_obj);
            }
        }
    });

    // TODO: placeholder
    view! {
        <form class="new-message-composer panel">
            <div class="overlay-scroll" node_ref=composer>
                <div
                    class="text-box"
                    on:input:target=move |ev| {
                        new_message.set(ev.target().text_content().unwrap_or_default())
                    }
                    node_ref=message_input
                    contenteditable
                    on:keydown=move |ev| {
                        match ev.key_code() {
                            16 => set_shift_pressed.set(true),
                            13 => {
                                if !shift_pressed.get() {
                                    ev.prevent_default();
                                    send_message();
                                }
                            }
                            _ => {}
                        }
                    }
                    on:keyup=move |ev| {
                        match ev.key_code() {
                            16 => set_shift_pressed.set(false),
                            _ => {}
                        }
                    }
                ></div>
            </div>
        // <input hidden type="submit" />
        </form>
    }
}