Fix deadlock on getting the focused window

This commit is contained in:
Gregory Schier
2024-08-22 05:46:09 -07:00
parent 4c6684623f
commit 503b7f1c87
7 changed files with 37 additions and 30 deletions

8
package-lock.json generated
View File

@@ -27,7 +27,7 @@
"@tauri-apps/plugin-log": "^2.0.0-rc.0",
"@tauri-apps/plugin-os": "^2.0.0-rc.0",
"@tauri-apps/plugin-shell": "^2.0.0-rc.0",
"@yaakapp/api": "^0.1.9",
"@yaakapp/api": "^0.1.10",
"buffer": "^6.0.3",
"classnames": "^2.3.2",
"cm6-graphql": "^0.0.9",
@@ -2990,9 +2990,9 @@
"integrity": "sha512-N8tkAACJx2ww8vFMneJmaAgmjAG1tnVBZJRLRcx061tmsLRZHSEZSLuGWnwPtunsSLvSqXQ2wfp7Mgqg1I+2dQ=="
},
"node_modules/@yaakapp/api": {
"version": "0.1.9",
"resolved": "https://registry.npmjs.org/@yaakapp/api/-/api-0.1.9.tgz",
"integrity": "sha512-5mgBoNplXUnNIUpLgGPCjcf6p/BcsU485cH3/MnIzcXIaMfFpZVVwHq5vf9cm+NDcr5hwYmPyIbwmBf9uVoV2Q==",
"version": "0.1.10",
"resolved": "https://registry.npmjs.org/@yaakapp/api/-/api-0.1.10.tgz",
"integrity": "sha512-K4iV7Et+5MmE+4Eui0mu/e8Y5vlvfSyykEy6Wl2sBOg6vRqr87N+OyUs/gkct7TU07QM8zew/hbM/OTESVhQWQ==",
"dependencies": {
"@types/node": "^22.0.0"
}

View File

@@ -42,7 +42,7 @@
"@tauri-apps/plugin-log": "^2.0.0-rc.0",
"@tauri-apps/plugin-os": "^2.0.0-rc.0",
"@tauri-apps/plugin-shell": "^2.0.0-rc.0",
"@yaakapp/api": "^0.1.9",
"@yaakapp/api": "^0.1.10",
"buffer": "^6.0.3",
"classnames": "^2.3.2",
"cm6-graphql": "^0.0.9",

View File

@@ -24,7 +24,7 @@ use tauri::{Manager, WindowEvent};
use tauri_plugin_clipboard_manager::ClipboardExt;
use tauri_plugin_log::{fern, Target, TargetKind};
use tauri_plugin_shell::ShellExt;
use tokio::sync::{watch, Mutex};
use tokio::sync::Mutex;
use yaak_grpc::manager::{DynamicMessage, GrpcHandle};
use yaak_grpc::{deserialize_message, serialize_message, Code, ServiceDefinition};
@@ -1992,11 +1992,7 @@ async fn handle_plugin_event<R: Runtime>(
))
}
InternalEventPayload::RenderHttpRequestRequest(req) => {
let webview_windows = app_handle.get_focused_window()?.webview_windows();
let w = match webview_windows.iter().next() {
None => return None,
Some((_, w)) => w,
};
let w = get_focused_window_no_lock(app_handle)?;
let workspace = get_workspace(app_handle, req.http_request.workspace_id.as_str())
.await
.expect("Failed to get workspace for request");
@@ -2008,7 +2004,7 @@ async fn handle_plugin_event<R: Runtime>(
.map(|(_k, v)| v.to_string());
let environment = match environment_id {
None => None,
Some(id) => get_environment(w, id.as_str()).await.ok(),
Some(id) => get_environment(&w, id.as_str()).await.ok(),
};
let rendered_http_request = render_http_request(
app_handle,
@@ -2024,12 +2020,7 @@ async fn handle_plugin_event<R: Runtime>(
))
}
InternalEventPayload::SendHttpRequestRequest(req) => {
let webview_windows = app_handle.get_focused_window()?.webview_windows();
let w = match webview_windows.iter().next() {
None => return None,
Some((_, w)) => w,
};
let w = get_focused_window_no_lock(app_handle)?;
let url = w.url().unwrap();
let mut query_pairs = url.query_pairs();
@@ -2038,7 +2029,7 @@ async fn handle_plugin_event<R: Runtime>(
.map(|(_k, v)| v.to_string());
let cookie_jar = match cookie_jar_id {
None => None,
Some(id) => get_cookie_jar(w, id.as_str()).await.ok(),
Some(id) => get_cookie_jar(app_handle, id.as_str()).await.ok(),
};
let environment_id = query_pairs
@@ -2046,10 +2037,10 @@ async fn handle_plugin_event<R: Runtime>(
.map(|(_k, v)| v.to_string());
let environment = match environment_id {
None => None,
Some(id) => get_environment(w, id.as_str()).await.ok(),
Some(id) => get_environment(app_handle, id.as_str()).await.ok(),
};
let resp = create_default_http_response(w, req.http_request.id.as_str())
let resp = create_default_http_response(app_handle, req.http_request.id.as_str())
.await
.unwrap();
@@ -2059,7 +2050,7 @@ async fn handle_plugin_event<R: Runtime>(
&resp,
environment,
cookie_jar,
&mut watch::channel(false).1, // No-op cancel channel
&mut tokio::sync::watch::channel(false).1, // No-op cancel channel
)
.await;
@@ -2077,3 +2068,16 @@ async fn handle_plugin_event<R: Runtime>(
event
}
// app_handle.get_focused_window locks, so this one is a non-locking version, safe for use in async context
fn get_focused_window_no_lock<R: Runtime>(app_handle: &AppHandle<R>) -> Option<WebviewWindow<R>> {
app_handle
.windows()
.iter()
.find(|w| w.1.is_focused().unwrap_or(false))
.map(|w| w.1.clone())?
.webview_windows()
.iter()
.next()
.map(|(_, w)| w.to_owned())
}

View File

@@ -214,13 +214,13 @@ impl PluginRuntimeGrpcServer {
let msg = format!("Failed to find plugin for {plugin_name}");
Err(PluginNotFoundErr(msg))
}
pub async fn send(&self, payload: &InternalEventPayload, plugin_ref_id: &str, reply_id: Option<String>)-> Result<()> {
let plugin = self.plugin_by_ref_id(plugin_ref_id).await?;
let event = plugin.build_event_to_send(payload, reply_id);
plugin.send(&event).await
}
pub async fn send_to_plugin(
&self,

View File

@@ -56,15 +56,14 @@ export function TemplateFunctionDialog({ templateFunction, hide, initialTokens,
}, []);
const tokens: Tokens = useMemo(() => {
console.log('HELLO', argValues);
const argTokens: FnArg[] = Object.keys(argValues).map((name) => ({
name,
value:
argValues[name] === NULL_ARG
? { type: 'null' }
: typeof argValues[name] === 'boolean'
? { type: 'bool', value: argValues[name] }
: { type: 'str', text: argValues[name] ?? '' },
? { type: 'bool', value: argValues[name] === true }
: { type: 'str', text: String(argValues[name] ?? '') },
}));
return {

View File

@@ -39,11 +39,12 @@ export function twig({
const functionOptions: TwigCompletionOption[] =
templateFunctions.map((fn) => {
const NUM_ARGS = 2;
const shortArgs =
fn.args
.slice(0, 1)
.slice(0, NUM_ARGS)
.map((a) => a.name)
.join(', ') + (fn.args.length > 1 ? ', …' : '');
.join(', ') + (fn.args.length > NUM_ARGS ? ', …' : '');
return {
name: fn.name,
type: 'function',

View File

@@ -37,7 +37,10 @@ class TemplateTagWidget extends WidgetType {
}`;
elt.title = this.option.invalid ? 'Not Found' : this.option.value ?? '';
elt.setAttribute('data-tag-type', this.option.type);
elt.textContent = this.option.label;
elt.textContent =
this.option.type === 'variable'
? this.option.name
: `${this.option.name}(${this.option.args.length ? '…' : ''})`;
elt.addEventListener('click', this.#clickListenerCallback);
return elt;
}