show prompt responses in dialog
This commit is contained in:
@@ -58,6 +58,7 @@ async fn main() {
|
|||||||
.plugin(tauri_plugin_global_shortcut::Builder::new().build())
|
.plugin(tauri_plugin_global_shortcut::Builder::new().build())
|
||||||
.invoke_handler(tauri::generate_handler![toggle_popup, prompt_llm])
|
.invoke_handler(tauri::generate_handler![toggle_popup, prompt_llm])
|
||||||
.setup(|app| {
|
.setup(|app| {
|
||||||
|
/* Auto-hide popup when focus is lost
|
||||||
if let Some(window) = app.get_webview_window("popup") {
|
if let Some(window) = app.get_webview_window("popup") {
|
||||||
let w = window.clone();
|
let w = window.clone();
|
||||||
window.on_window_event(move |event| {
|
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);
|
let shortcut = Shortcut::new(Some(Modifiers::META), Code::Space);
|
||||||
app.global_shortcut()
|
app.global_shortcut()
|
||||||
.on_shortcut(shortcut, move |app, _shortcut, event| {
|
.on_shortcut(shortcut, move |app, _shortcut, event| {
|
||||||
|
|||||||
@@ -22,8 +22,8 @@
|
|||||||
"label": "popup",
|
"label": "popup",
|
||||||
"title": "AI Quick Action",
|
"title": "AI Quick Action",
|
||||||
"url": "/popup",
|
"url": "/popup",
|
||||||
"width": 600,
|
"width": 800,
|
||||||
"height": 260,
|
"height": 400,
|
||||||
"decorations": false,
|
"decorations": false,
|
||||||
"transparent": true,
|
"transparent": true,
|
||||||
"alwaysOnTop": true,
|
"alwaysOnTop": true,
|
||||||
|
|||||||
@@ -3,12 +3,19 @@ use leptos::{ev::keydown, html::Input, prelude::*};
|
|||||||
use wasm_bindgen::{prelude::Closure, JsCast, JsValue};
|
use wasm_bindgen::{prelude::Closure, JsCast, JsValue};
|
||||||
use wasm_bindgen_futures::spawn_local;
|
use wasm_bindgen_futures::spawn_local;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
struct Message {
|
||||||
|
id: usize,
|
||||||
|
text: String,
|
||||||
|
is_user: bool,
|
||||||
|
}
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
pub fn Popup() -> impl IntoView {
|
pub fn Popup() -> impl IntoView {
|
||||||
// Prompt signals and and action
|
// Prompt signals and and action
|
||||||
let prompt_input_ref = NodeRef::<Input>::new();
|
let prompt_input_ref = NodeRef::<Input>::new();
|
||||||
let (prompt_text, set_prompt_text) = signal(String::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::<Message>::new());
|
||||||
// Action that calls the promp daemon
|
// Action that calls the promp daemon
|
||||||
let prompt_action = Action::new_local(|prompt: &String| {
|
let prompt_action = Action::new_local(|prompt: &String| {
|
||||||
let prompt = prompt.clone();
|
let prompt = prompt.clone();
|
||||||
@@ -25,7 +32,13 @@ pub fn Popup() -> impl IntoView {
|
|||||||
// Update the model response div with the prompt result
|
// Update the model response div with the prompt result
|
||||||
Effect::new(move |_| {
|
Effect::new(move |_| {
|
||||||
if let Some(result) = prompt_action.value().get() {
|
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)
|
// 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:input=move |ev| set_prompt_text.set(event_target_value(&ev))
|
||||||
on:keydown=move |ev| {
|
on:keydown=move |ev| {
|
||||||
if ev.key() == "Enter" {
|
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());
|
prompt_action.dispatch(prompt_text.get());
|
||||||
//set_prompt_result.update(|s| *s = prompt_action.value());
|
|
||||||
set_prompt_text.update(|s| *s = "".to_string());
|
set_prompt_text.update(|s| *s = "".to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
prop:value=prompt_text
|
prop:value=prompt_text
|
||||||
/>
|
/>
|
||||||
<div class="response-area">
|
<div class="response-area">
|
||||||
<p>{move || prompt_result.get()}</p>
|
<For each=move || messages.get()
|
||||||
|
key=|msg| msg.id
|
||||||
|
let(msg)
|
||||||
|
>
|
||||||
|
<div class=if msg.is_user {"msg msg-user"} else {"msg msg-model"}>{msg.text}</div>
|
||||||
|
</For>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,3 +21,18 @@ body {
|
|||||||
background-color: #212121;
|
background-color: #212121;
|
||||||
border-radius: 15px;
|
border-radius: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.response-area {
|
||||||
|
width: 100%;
|
||||||
|
height: 300px;
|
||||||
|
overflow-y: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
.msg {
|
||||||
|
margin: 1px;
|
||||||
|
border: solid 1px #808080;
|
||||||
|
}
|
||||||
|
|
||||||
|
.msg-user {
|
||||||
|
text-align: end;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user