diff --git a/frontend/src-tauri/src/main.rs b/frontend/src-tauri/src/main.rs index 60a6025..ee3fc7b 100644 --- a/frontend/src-tauri/src/main.rs +++ b/frontend/src-tauri/src/main.rs @@ -58,6 +58,7 @@ async fn main() { .plugin(tauri_plugin_global_shortcut::Builder::new().build()) .invoke_handler(tauri::generate_handler![toggle_popup, prompt_llm]) .setup(|app| { + /* Auto-hide popup when focus is lost if let Some(window) = app.get_webview_window("popup") { let w = window.clone(); window.on_window_event(move |event| { @@ -68,6 +69,8 @@ async fn main() { } }) } + */ + // Global shortcut to pull up the popup let shortcut = Shortcut::new(Some(Modifiers::META), Code::Space); app.global_shortcut() .on_shortcut(shortcut, move |app, _shortcut, event| { diff --git a/frontend/src-tauri/tauri.conf.json b/frontend/src-tauri/tauri.conf.json index 0873f91..bc148f1 100644 --- a/frontend/src-tauri/tauri.conf.json +++ b/frontend/src-tauri/tauri.conf.json @@ -22,8 +22,8 @@ "label": "popup", "title": "AI Quick Action", "url": "/popup", - "width": 600, - "height": 260, + "width": 800, + "height": 400, "decorations": false, "transparent": true, "alwaysOnTop": true, diff --git a/frontend/src/popup.rs b/frontend/src/popup.rs index 0ca1419..d0433dd 100644 --- a/frontend/src/popup.rs +++ b/frontend/src/popup.rs @@ -3,12 +3,19 @@ use leptos::{ev::keydown, html::Input, prelude::*}; use wasm_bindgen::{prelude::Closure, JsCast, JsValue}; use wasm_bindgen_futures::spawn_local; +#[derive(Clone, Debug)] +struct Message { + id: usize, + text: String, + is_user: bool, +} + #[component] pub fn Popup() -> impl IntoView { // Prompt signals and and action let prompt_input_ref = NodeRef::::new(); let (prompt_text, set_prompt_text) = signal(String::new()); - let (prompt_result, set_prompt_result) = signal(String::new()); + let (messages, set_messages) = signal(Vec::::new()); // Action that calls the promp daemon let prompt_action = Action::new_local(|prompt: &String| { let prompt = prompt.clone(); @@ -25,7 +32,13 @@ pub fn Popup() -> impl IntoView { // Update the model response div with the prompt result Effect::new(move |_| { if let Some(result) = prompt_action.value().get() { - set_prompt_result.set(result) + set_messages.update(|previous| { + previous.push(Message { + id: previous.len(), + text: result, + is_user: false, + }); + }); } }); // Clear the propt text-input when the window loses focus (and is hidden) @@ -64,15 +77,26 @@ pub fn Popup() -> impl IntoView { on:input=move |ev| set_prompt_text.set(event_target_value(&ev)) on:keydown=move |ev| { if ev.key() == "Enter" { + set_messages.update(|previous| { + previous.push(Message { + id: previous.len(), + text: prompt_text.get(), + is_user: true, + }); + }); prompt_action.dispatch(prompt_text.get()); - //set_prompt_result.update(|s| *s = prompt_action.value()); set_prompt_text.update(|s| *s = "".to_string()); } } prop:value=prompt_text />
-

{move || prompt_result.get()}

+ +
{msg.text}
+
} diff --git a/frontend/styles.css b/frontend/styles.css index ed24123..73e4320 100644 --- a/frontend/styles.css +++ b/frontend/styles.css @@ -1,23 +1,38 @@ body { - background-color: transparent !important; - margin: 0; - color: #f0f0f0; + background-color: transparent !important; + margin: 0; + color: #f0f0f0; } .window-shell { - width: 100vw; - height: 100vh; - display: flex; - flex-direction: column; - box-sizing: border-box; - padding: 15px; + width: 100vw; + height: 100vh; + display: flex; + flex-direction: column; + box-sizing: border-box; + padding: 15px; } .opaque-bg { - background-color: #212121; + background-color: #212121; } .rounded-container { - background-color: #212121; - border-radius: 15px; + background-color: #212121; + border-radius: 15px; +} + +.response-area { + width: 100%; + height: 300px; + overflow-y: scroll; +} + +.msg { + margin: 1px; + border: solid 1px #808080; +} + +.msg-user { + text-align: end; }