summaryrefslogblamecommitdiffstats
path: root/src/components/message_composer.rs
blob: 6b34298732ea661ba6795afe1625421db69907ea (plain) (tree)
1
2
3
4
5
6

                          
                                                                  
                                                       

                                          


























































                                                                         





























                                                                                                                                                                                                                                         

                        
                                                 















                                                                                       
                             
                                   
                         
                     




                                                               
                     

                       
                                         


               
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>
    }
}