pinakes-ui: fix reactive dependencies in backlinks panel; improve wikilink click handling
Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: Ib9a36bbaa16a7aa46b624027c1eb00fe6a6a6964
This commit is contained in:
parent
4ed61bc62e
commit
bf76820ddd
2 changed files with 113 additions and 37 deletions
|
|
@ -1,3 +1,4 @@
|
|||
use dioxus::document::eval;
|
||||
use dioxus::prelude::*;
|
||||
|
||||
/// Event handler for wikilink clicks. Called with the target note name.
|
||||
|
|
@ -43,6 +44,49 @@ pub fn MarkdownViewer(
|
|||
});
|
||||
});
|
||||
|
||||
// Set up global wikilink click handler that the inline onclick attributes will call
|
||||
// This bridges JavaScript → Rust communication
|
||||
use_effect(move || {
|
||||
if let Some(handler) = on_wikilink_click {
|
||||
spawn(async move {
|
||||
// Set up a global function that wikilink onclick handlers can call
|
||||
// The function stores the clicked target in localStorage
|
||||
let setup_js = r#"
|
||||
window.__dioxus_wikilink_click = function(target) {
|
||||
console.log('Wikilink clicked:', target);
|
||||
localStorage.setItem('__wikilink_clicked', target);
|
||||
};
|
||||
"#;
|
||||
|
||||
let _ = eval(setup_js).await;
|
||||
|
||||
// Poll localStorage to detect wikilink clicks
|
||||
loop {
|
||||
tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
|
||||
|
||||
let check_js = r#"
|
||||
(function() {
|
||||
const target = localStorage.getItem('__wikilink_clicked');
|
||||
if (target) {
|
||||
localStorage.removeItem('__wikilink_clicked');
|
||||
return target;
|
||||
}
|
||||
return '';
|
||||
})();
|
||||
"#;
|
||||
|
||||
if let Ok(result) = eval(check_js).await {
|
||||
if let Some(target) = result.as_str() {
|
||||
if !target.is_empty() {
|
||||
handler.call(target.to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
let is_loading = *loading.read();
|
||||
|
||||
rsx! {
|
||||
|
|
@ -159,7 +203,7 @@ fn render_markdown(text: &str) -> String {
|
|||
}
|
||||
|
||||
/// Convert wikilinks [[target]] and [[target|display]] to styled HTML links.
|
||||
/// Uses data attributes only - no inline JavaScript for security.
|
||||
/// Uses a special URL scheme that can be intercepted by click handlers.
|
||||
fn convert_wikilinks(text: &str) -> String {
|
||||
use regex::Regex;
|
||||
|
||||
|
|
@ -181,12 +225,13 @@ fn convert_wikilinks(text: &str) -> String {
|
|||
let text = wikilink_re.replace_all(&text, |caps: ®ex::Captures| {
|
||||
let target = caps.get(1).unwrap().as_str().trim();
|
||||
let display = caps.get(2).map(|m| m.as_str().trim()).unwrap_or(target);
|
||||
// Create a styled link with data attributes only - no inline JavaScript.
|
||||
// Event handling is done via event delegation in the frontend.
|
||||
// Create a styled link that uses a special pseudo-protocol scheme
|
||||
// This makes it easier to intercept clicks via JavaScript
|
||||
format!(
|
||||
"<a href=\"#wikilink\" class=\"wikilink\" data-wikilink-target=\"{}\">{}</a>",
|
||||
escape_html_attr(target),
|
||||
escape_html(display)
|
||||
"<a href=\"javascript:void(0)\" class=\"wikilink\" data-wikilink-target=\"{target}\" onclick=\"if(window.__dioxus_wikilink_click){{window.__dioxus_wikilink_click('{target_escaped}')}}\">{display}</a>",
|
||||
target = escape_html_attr(target),
|
||||
target_escaped = escape_html_attr(&target.replace('\\', "\\\\").replace('\'', "\\'")),
|
||||
display = escape_html(display)
|
||||
)
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue